Annotation of embedaddon/dhcp/client/clparse.c, revision 1.1.1.1

1.1       misho       1: /* clparse.c
                      2: 
                      3:    Parser for dhclient config and lease files... */
                      4: 
                      5: /*
1.1.1.1 ! misho       6:  * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
1.1       misho       7:  * Copyright (c) 1996-2003 by Internet Software Consortium
                      8:  *
                      9:  * Permission to use, copy, modify, and distribute this software for any
                     10:  * purpose with or without fee is hereby granted, provided that the above
                     11:  * copyright notice and this permission notice appear in all copies.
                     12:  *
                     13:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     14:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     15:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     16:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     17:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     18:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     19:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     20:  *
                     21:  *   Internet Systems Consortium, Inc.
                     22:  *   950 Charter Street
                     23:  *   Redwood City, CA 94063
                     24:  *   <info@isc.org>
                     25:  *   https://www.isc.org/
                     26:  *
                     27:  * This software has been written for Internet Systems Consortium
                     28:  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
                     29:  * To learn more about Internet Systems Consortium, see
                     30:  * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
                     31:  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
                     32:  * ``http://www.nominum.com''.
                     33:  */
                     34: 
                     35: #include "dhcpd.h"
                     36: #include <errno.h>
                     37: 
                     38: struct client_config top_level_config;
                     39: 
                     40: #define NUM_DEFAULT_REQUESTED_OPTS     9
                     41: struct option *default_requested_options[NUM_DEFAULT_REQUESTED_OPTS + 1];
                     42: 
                     43: static void parse_client_default_duid(struct parse *cfile);
                     44: static void parse_client6_lease_statement(struct parse *cfile);
                     45: #ifdef DHCPv6
                     46: static struct dhc6_ia *parse_client6_ia_na_statement(struct parse *cfile);
                     47: static struct dhc6_ia *parse_client6_ia_ta_statement(struct parse *cfile);
                     48: static struct dhc6_ia *parse_client6_ia_pd_statement(struct parse *cfile);
                     49: static struct dhc6_addr *parse_client6_iaaddr_statement(struct parse *cfile);
                     50: static struct dhc6_addr *parse_client6_iaprefix_statement(struct parse *cfile);
                     51: #endif /* DHCPv6 */
                     52: 
                     53: /* client-conf-file :== client-declarations END_OF_FILE
                     54:    client-declarations :== <nil>
                     55:                         | client-declaration
                     56:                         | client-declarations client-declaration */
                     57: 
                     58: isc_result_t read_client_conf ()
                     59: {
                     60:        struct client_config *config;
                     61:        struct interface_info *ip;
                     62:        isc_result_t status;
                     63:        unsigned code;
                     64: 
1.1.1.1 ! misho      65:         /* 
        !            66:          * TODO: LATER constant is very undescriptive. We should review it and
        !            67:          * change it to something more descriptive or even better remove it
        !            68:          * completely as it is currently not used.
        !            69:          */
        !            70: #ifdef LATER
        !            71:         struct parse *parse = NULL;
        !            72: #endif
        !            73: 
1.1       misho      74:        /* Initialize the default request list. */
                     75:        memset(default_requested_options, 0, sizeof(default_requested_options));
                     76: 
                     77:        /* 1 */
                     78:        code = DHO_SUBNET_MASK;
                     79:        option_code_hash_lookup(&default_requested_options[0],
                     80:                                dhcp_universe.code_hash, &code, 0, MDL);
                     81: 
                     82:        /* 2 */
                     83:        code = DHO_BROADCAST_ADDRESS;
                     84:        option_code_hash_lookup(&default_requested_options[1],
                     85:                                dhcp_universe.code_hash, &code, 0, MDL);
                     86: 
                     87:        /* 3 */
                     88:        code = DHO_TIME_OFFSET;
                     89:        option_code_hash_lookup(&default_requested_options[2],
                     90:                                dhcp_universe.code_hash, &code, 0, MDL);
                     91: 
                     92:        /* 4 */
                     93:        code = DHO_ROUTERS;
                     94:        option_code_hash_lookup(&default_requested_options[3],
                     95:                                dhcp_universe.code_hash, &code, 0, MDL);
                     96: 
                     97:        /* 5 */
                     98:        code = DHO_DOMAIN_NAME;
                     99:        option_code_hash_lookup(&default_requested_options[4],
                    100:                                dhcp_universe.code_hash, &code, 0, MDL);
                    101: 
                    102:        /* 6 */
                    103:        code = DHO_DOMAIN_NAME_SERVERS;
                    104:        option_code_hash_lookup(&default_requested_options[5],
                    105:                                dhcp_universe.code_hash, &code, 0, MDL);
                    106: 
                    107:        /* 7 */
                    108:        code = DHO_HOST_NAME;
                    109:        option_code_hash_lookup(&default_requested_options[6],
                    110:                                dhcp_universe.code_hash, &code, 0, MDL);
                    111: 
                    112:        /* 8 */
                    113:        code = D6O_NAME_SERVERS;
                    114:        option_code_hash_lookup(&default_requested_options[7],
                    115:                                dhcpv6_universe.code_hash, &code, 0, MDL);
                    116: 
                    117:        /* 9 */
                    118:        code = D6O_DOMAIN_SEARCH;
                    119:        option_code_hash_lookup(&default_requested_options[8],
                    120:                                dhcpv6_universe.code_hash, &code, 0, MDL);
                    121: 
                    122:        for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) {
                    123:                if (default_requested_options[code] == NULL)
                    124:                        log_fatal("Unable to find option definition for "
                    125:                                  "index %u during default parameter request "
                    126:                                  "assembly.", code);
                    127:        }
                    128: 
                    129:        /* Initialize the top level client configuration. */
                    130:        memset (&top_level_config, 0, sizeof top_level_config);
                    131: 
                    132:        /* Set some defaults... */
                    133:        top_level_config.timeout = 60;
                    134:        top_level_config.select_interval = 0;
                    135:        top_level_config.reboot_timeout = 10;
                    136:        top_level_config.retry_interval = 300;
                    137:        top_level_config.backoff_cutoff = 15;
                    138:        top_level_config.initial_interval = 3;
                    139: 
                    140:        /*
                    141:         * RFC 2131, section 4.4.1 specifies that the client SHOULD wait a
                    142:         * random time between 1 and 10 seconds. However, we choose to not
                    143:         * implement this default. If user is inclined to really have that
                    144:         * delay, he is welcome to do so, using 'initial-delay X;' parameter
                    145:         * in config file.
                    146:         */
                    147:        top_level_config.initial_delay = 0;
                    148: 
                    149:        top_level_config.bootp_policy = P_ACCEPT;
                    150:        top_level_config.script_name = path_dhclient_script;
                    151:        top_level_config.requested_options = default_requested_options;
                    152:        top_level_config.omapi_port = -1;
                    153:        top_level_config.do_forward_update = 1;
                    154:        /* Requested lease time, used by DHCPv6 (DHCPv4 uses the option cache)
                    155:         */
                    156:        top_level_config.requested_lease = 7200;
                    157: 
                    158:        group_allocate (&top_level_config.on_receipt, MDL);
                    159:        if (!top_level_config.on_receipt)
                    160:                log_fatal ("no memory for top-level on_receipt group");
                    161: 
                    162:        group_allocate (&top_level_config.on_transmission, MDL);
                    163:        if (!top_level_config.on_transmission)
                    164:                log_fatal ("no memory for top-level on_transmission group");
                    165: 
                    166:        status = read_client_conf_file (path_dhclient_conf,
                    167:                                        (struct interface_info *)0,
                    168:                                        &top_level_config);
                    169: 
                    170:        if (status != ISC_R_SUCCESS) {
                    171:                ;
                    172: #ifdef LATER
                    173:                /* Set up the standard name service updater routine. */
                    174:                status = new_parse(&parse, -1, default_client_config,
                    175:                                   sizeof(default_client_config) - 1,
                    176:                                   "default client configuration", 0);
                    177:                if (status != ISC_R_SUCCESS)
                    178:                        log_fatal ("can't begin default client config!");
                    179:        }
                    180: 
                    181:        if (parse != NULL) {
                    182:                do {
                    183:                        token = peek_token(&val, NULL, cfile);
                    184:                        if (token == END_OF_FILE)
                    185:                                break;
                    186:                        parse_client_statement(cfile, NULL, &top_level_config);
                    187:                } while (1);
                    188:                end_parse(&parse);
                    189: #endif
                    190:        }
                    191: 
                    192:        /* Set up state and config structures for clients that don't
                    193:           have per-interface configuration statements. */
                    194:        config = (struct client_config *)0;
                    195:        for (ip = interfaces; ip; ip = ip -> next) {
                    196:                if (!ip -> client) {
                    197:                        ip -> client = (struct client_state *)
                    198:                                dmalloc (sizeof (struct client_state), MDL);
                    199:                        if (!ip -> client)
                    200:                                log_fatal ("no memory for client state.");
                    201:                        memset (ip -> client, 0, sizeof *(ip -> client));
                    202:                        ip -> client -> interface = ip;
                    203:                }
                    204: 
                    205:                if (!ip -> client -> config) {
                    206:                        if (!config) {
                    207:                                config = (struct client_config *)
                    208:                                        dmalloc (sizeof (struct client_config),
                    209:                                                 MDL);
                    210:                                if (!config)
                    211:                                    log_fatal ("no memory for client config.");
                    212:                                memcpy (config, &top_level_config,
                    213:                                        sizeof top_level_config);
                    214:                        }
                    215:                        ip -> client -> config = config;
                    216:                }
                    217:        }
                    218:        return status;
                    219: }
                    220: 
                    221: int read_client_conf_file (const char *name, struct interface_info *ip,
                    222:                           struct client_config *client)
                    223: {
                    224:        int file;
                    225:        struct parse *cfile;
                    226:        const char *val;
                    227:        int token;
                    228:        isc_result_t status;
                    229: 
                    230:        if ((file = open (name, O_RDONLY)) < 0)
                    231:                return uerr2isc (errno);
                    232: 
                    233:        cfile = NULL;
                    234:        status = new_parse(&cfile, file, NULL, 0, path_dhclient_conf, 0);
                    235:        if (status != ISC_R_SUCCESS || cfile == NULL)
                    236:                return status;
                    237: 
                    238:        do {
                    239:                token = peek_token (&val, (unsigned *)0, cfile);
                    240:                if (token == END_OF_FILE)
                    241:                        break;
                    242:                parse_client_statement (cfile, ip, client);
                    243:        } while (1);
                    244:        token = next_token (&val, (unsigned *)0, cfile);
                    245:        status = (cfile -> warnings_occurred
                    246:                  ? ISC_R_BADPARSE
                    247:                  : ISC_R_SUCCESS);
                    248:        end_parse (&cfile);
                    249:        return status;
                    250: }
                    251: 
                    252: 
                    253: /* lease-file :== client-lease-statements END_OF_FILE
                    254:    client-lease-statements :== <nil>
                    255:                     | client-lease-statements LEASE client-lease-statement */
                    256: 
                    257: void read_client_leases ()
                    258: {
                    259:        int file;
                    260:        isc_result_t status;
                    261:        struct parse *cfile;
                    262:        const char *val;
                    263:        int token;
                    264: 
                    265:        /* Open the lease file.   If we can't open it, just return -
                    266:           we can safely trust the server to remember our state. */
                    267:        if ((file = open (path_dhclient_db, O_RDONLY)) < 0)
                    268:                return;
                    269: 
                    270:        cfile = NULL;
                    271:        status = new_parse(&cfile, file, NULL, 0, path_dhclient_db, 0);
                    272:        if (status != ISC_R_SUCCESS || cfile == NULL)
                    273:                return;
                    274: 
                    275:        do {
                    276:                token = next_token (&val, (unsigned *)0, cfile);
                    277:                if (token == END_OF_FILE)
                    278:                        break;
                    279: 
                    280:                switch (token) {
                    281:                      case DEFAULT_DUID:
                    282:                        parse_client_default_duid(cfile);
                    283:                        break;
                    284: 
                    285:                      case LEASE:
                    286:                        parse_client_lease_statement(cfile, 0);
                    287:                        break;
                    288: 
                    289:                      case LEASE6:
                    290:                        parse_client6_lease_statement(cfile);
                    291:                        break;
                    292: 
                    293:                      default:
                    294:                        log_error ("Corrupt lease file - possible data loss!");
                    295:                        skip_to_semi (cfile);
                    296:                        break;
                    297:                }
                    298:        } while (1);
                    299: 
                    300:        end_parse (&cfile);
                    301: }
                    302: 
                    303: /* client-declaration :== 
                    304:        SEND option-decl |
                    305:        DEFAULT option-decl |
                    306:        SUPERSEDE option-decl |
                    307:        PREPEND option-decl |
                    308:        APPEND option-decl |
                    309:        hardware-declaration |
                    310:        ALSO REQUEST option-list |
                    311:        ALSO REQUIRE option-list |
                    312:        REQUEST option-list |
                    313:        REQUIRE option-list |
                    314:        TIMEOUT number |
                    315:        RETRY number |
                    316:        REBOOT number |
                    317:        SELECT_TIMEOUT number |
                    318:        SCRIPT string |
                    319:        VENDOR_SPACE string |
                    320:        interface-declaration |
                    321:        LEASE client-lease-statement |
                    322:        ALIAS client-lease-statement |
                    323:        KEY key-definition */
                    324: 
                    325: void parse_client_statement (cfile, ip, config)
                    326:        struct parse *cfile;
                    327:        struct interface_info *ip;
                    328:        struct client_config *config;
                    329: {
                    330:        int token;
                    331:        const char *val;
                    332:        struct option *option = NULL;
                    333:        struct executable_statement *stmt;
                    334:        int lose;
                    335:        char *name;
                    336:        enum policy policy;
                    337:        int known;
                    338:        int tmp, i;
                    339:        isc_result_t status;
                    340:        struct option ***append_list, **new_list, **cat_list;
                    341: 
                    342:        switch (peek_token (&val, (unsigned *)0, cfile)) {
                    343:              case INCLUDE:
                    344:                next_token (&val, (unsigned *)0, cfile);
                    345:                token = next_token (&val, (unsigned *)0, cfile);
                    346:                if (token != STRING) {
                    347:                        parse_warn (cfile, "filename string expected.");
                    348:                        skip_to_semi (cfile);
                    349:                } else {
                    350:                        status = read_client_conf_file (val, ip, config);
                    351:                        if (status != ISC_R_SUCCESS)
                    352:                                parse_warn (cfile, "%s: bad parse.", val);
                    353:                        parse_semi (cfile);
                    354:                }
                    355:                return;
                    356:                
                    357:              case KEY:
                    358:                next_token (&val, (unsigned *)0, cfile);
                    359:                if (ip) {
                    360:                        /* This may seem arbitrary, but there's a reason for
                    361:                           doing it: the authentication key database is not
                    362:                           scoped.  If we allow the user to declare a key other
                    363:                           than in the outer scope, the user is very likely to
                    364:                           believe that the key will only be used in that
                    365:                           scope.  If the user only wants the key to be used on
                    366:                           one interface, because it's known that the other
                    367:                           interface may be connected to an insecure net and
                    368:                           the secret key is considered sensitive, we don't
                    369:                           want to lull them into believing they've gotten
                    370:                           their way.   This is a bit contrived, but people
                    371:                           tend not to be entirely rational about security. */
                    372:                        parse_warn (cfile, "key definition not allowed here.");
                    373:                        skip_to_semi (cfile);
                    374:                        break;
                    375:                }
                    376:                parse_key (cfile);
                    377:                return;
                    378: 
                    379:              case TOKEN_ALSO:
                    380:                /* consume ALSO */
                    381:                next_token(&val, NULL, cfile);
                    382: 
                    383:                /* consume type of ALSO list. */
                    384:                token = next_token(&val, NULL, cfile);
                    385: 
                    386:                if (token == REQUEST) {
                    387:                        append_list = &config->requested_options;
                    388:                } else if (token == REQUIRE) {
                    389:                        append_list = &config->required_options;
                    390:                } else {
                    391:                        parse_warn(cfile, "expected REQUEST or REQUIRE list");
                    392:                        skip_to_semi(cfile);
                    393:                        return;
                    394:                }
                    395: 
                    396:                /* If there is no list, cut the concat short. */
                    397:                if (*append_list == NULL) {
                    398:                        parse_option_list(cfile, append_list);
                    399:                        return;
                    400:                }
                    401: 
                    402:                /* Count the length of the existing list. */
                    403:                for (i = 0 ; (*append_list)[i] != NULL ; i++)
                    404:                        ; /* This space intentionally left blank. */
                    405: 
                    406:                /* If there's no codes on the list, cut the concat short. */
                    407:                if (i == 0) {
                    408:                        parse_option_list(cfile, append_list);
                    409:                        return;
                    410:                }
                    411: 
                    412:                tmp = parse_option_list(cfile, &new_list);
                    413: 
                    414:                if (tmp == 0 || new_list == NULL)
                    415:                        return;
                    416: 
                    417:                /* Allocate 'i + tmp' buckets plus a terminator. */
                    418:                cat_list = dmalloc(sizeof(struct option *) * (i + tmp + 1),
                    419:                                   MDL);
                    420: 
                    421:                if (cat_list == NULL) {
                    422:                        log_error("Unable to allocate memory for new "
                    423:                                  "request list.");
                    424:                        skip_to_semi(cfile);
                    425:                        return;
                    426:                }
                    427: 
                    428:                for (i = 0 ; (*append_list)[i] != NULL ; i++)
                    429:                        option_reference(&cat_list[i], (*append_list)[i], MDL);
                    430: 
                    431:                tmp = i;
                    432: 
                    433:                for (i = 0 ; new_list[i] != 0 ; i++)
                    434:                        option_reference(&cat_list[tmp++], new_list[i], MDL);
                    435: 
                    436:                cat_list[tmp] = 0;
                    437: 
                    438:                /* XXX: We cannot free the old list, because it may have been
                    439:                 * XXX: assigned from an outer configuration scope (or may be
                    440:                 * XXX: the static default setting).
                    441:                 */
                    442:                *append_list = cat_list;
                    443: 
                    444:                return;
                    445: 
                    446:                /* REQUIRE can either start a policy statement or a
                    447:                   comma-separated list of names of required options. */
                    448:              case REQUIRE:
                    449:                next_token (&val, (unsigned *)0, cfile);
                    450:                token = peek_token (&val, (unsigned *)0, cfile);
                    451:                if (token == AUTHENTICATION) {
                    452:                        policy = P_REQUIRE;
                    453:                        goto do_policy;
                    454:                }
                    455:                parse_option_list (cfile, &config -> required_options);
                    456:                return;
                    457: 
                    458:              case IGNORE:
                    459:                next_token (&val, (unsigned *)0, cfile);
                    460:                policy = P_IGNORE;
                    461:                goto do_policy;
                    462: 
                    463:              case ACCEPT:
                    464:                next_token (&val, (unsigned *)0, cfile);
                    465:                policy = P_ACCEPT;
                    466:                goto do_policy;
                    467: 
                    468:              case PREFER:
                    469:                next_token (&val, (unsigned *)0, cfile);
                    470:                policy = P_PREFER;
                    471:                goto do_policy;
                    472: 
                    473:              case DONT:
                    474:                next_token (&val, (unsigned *)0, cfile);
                    475:                policy = P_DONT;
                    476:                goto do_policy;
                    477: 
                    478:              do_policy:
                    479:                token = next_token (&val, (unsigned *)0, cfile);
                    480:                if (token == AUTHENTICATION) {
                    481:                        if (policy != P_PREFER &&
                    482:                            policy != P_REQUIRE &&
                    483:                            policy != P_DONT) {
                    484:                                parse_warn (cfile,
                    485:                                            "invalid authentication policy.");
                    486:                                skip_to_semi (cfile);
                    487:                                return;
                    488:                        }
                    489:                        config -> auth_policy = policy;
                    490:                } else if (token != TOKEN_BOOTP) {
                    491:                        if (policy != P_PREFER &&
                    492:                            policy != P_IGNORE &&
                    493:                            policy != P_ACCEPT) {
                    494:                                parse_warn (cfile, "invalid bootp policy.");
                    495:                                skip_to_semi (cfile);
                    496:                                return;
                    497:                        }
                    498:                        config -> bootp_policy = policy;
                    499:                } else {
                    500:                        parse_warn (cfile, "expecting a policy type.");
                    501:                        skip_to_semi (cfile);
                    502:                        return;
                    503:                } 
                    504:                break;
                    505: 
                    506:              case OPTION:
                    507:                token = next_token (&val, (unsigned *)0, cfile);
                    508: 
                    509:                token = peek_token (&val, (unsigned *)0, cfile);
                    510:                if (token == SPACE) {
                    511:                        if (ip) {
                    512:                                parse_warn (cfile,
                    513:                                            "option space definitions %s",
                    514:                                            " may not be scoped.");
                    515:                                skip_to_semi (cfile);
                    516:                                break;
                    517:                        }
                    518:                        parse_option_space_decl (cfile);
                    519:                        return;
                    520:                }
                    521: 
                    522:                known = 0;
                    523:                status = parse_option_name(cfile, 1, &known, &option);
                    524:                if (status != ISC_R_SUCCESS || option == NULL)
                    525:                        return;
                    526: 
                    527:                token = next_token (&val, (unsigned *)0, cfile);
                    528:                if (token != CODE) {
                    529:                        parse_warn (cfile, "expecting \"code\" keyword.");
                    530:                        skip_to_semi (cfile);
                    531:                        option_dereference(&option, MDL);
                    532:                        return;
                    533:                }
                    534:                if (ip) {
                    535:                        parse_warn (cfile,
                    536:                                    "option definitions may only appear in %s",
                    537:                                    "the outermost scope.");
                    538:                        skip_to_semi (cfile);
                    539:                        option_dereference(&option, MDL);
                    540:                        return;
                    541:                }
                    542: 
                    543:                /*
                    544:                 * If the option was known, remove it from the code and name
                    545:                 * hash tables before redefining it.
                    546:                 */
                    547:                if (known) {
                    548:                        option_name_hash_delete(option->universe->name_hash,
                    549:                                                option->name, 0, MDL);
                    550:                        option_code_hash_delete(option->universe->code_hash,
                    551:                                                &option->code, 0, MDL);
                    552:                }
                    553: 
                    554:                parse_option_code_definition(cfile, option);
                    555:                option_dereference(&option, MDL);
                    556:                return;
                    557: 
                    558:              case MEDIA:
                    559:                token = next_token (&val, (unsigned *)0, cfile);
                    560:                parse_string_list (cfile, &config -> media, 1);
                    561:                return;
                    562: 
                    563:              case HARDWARE:
                    564:                token = next_token (&val, (unsigned *)0, cfile);
                    565:                if (ip) {
                    566:                        parse_hardware_param (cfile, &ip -> hw_address);
                    567:                } else {
                    568:                        parse_warn (cfile, "hardware address parameter %s",
                    569:                                    "not allowed here.");
                    570:                        skip_to_semi (cfile);
                    571:                }
                    572:                return;
                    573: 
                    574:              case REQUEST:
                    575:                token = next_token (&val, (unsigned *)0, cfile);
                    576:                if (config -> requested_options == default_requested_options)
                    577:                        config -> requested_options = NULL;
                    578:                parse_option_list (cfile, &config -> requested_options);
                    579:                return;
                    580: 
                    581:              case TIMEOUT:
                    582:                token = next_token (&val, (unsigned *)0, cfile);
                    583:                parse_lease_time (cfile, &config -> timeout);
                    584:                return;
                    585: 
                    586:              case RETRY:
                    587:                token = next_token (&val, (unsigned *)0, cfile);
                    588:                parse_lease_time (cfile, &config -> retry_interval);
                    589:                return;
                    590: 
                    591:              case SELECT_TIMEOUT:
                    592:                token = next_token (&val, (unsigned *)0, cfile);
                    593:                parse_lease_time (cfile, &config -> select_interval);
                    594:                return;
                    595: 
                    596:              case OMAPI:
                    597:                token = next_token (&val, (unsigned *)0, cfile);
                    598:                token = next_token (&val, (unsigned *)0, cfile);
                    599:                if (token != PORT) {
                    600:                        parse_warn (cfile,
                    601:                                    "unexpected omapi subtype: %s", val);
                    602:                        skip_to_semi (cfile);
                    603:                        return;
                    604:                }
                    605:                token = next_token (&val, (unsigned *)0, cfile);
                    606:                if (token != NUMBER) {
                    607:                        parse_warn (cfile, "invalid port number: `%s'", val);
                    608:                        skip_to_semi (cfile);
                    609:                        return;
                    610:                }
                    611:                tmp = atoi (val);
                    612:                if (tmp < 0 || tmp > 65535)
                    613:                        parse_warn (cfile, "invalid omapi port %d.", tmp);
                    614:                else if (config != &top_level_config)
                    615:                        parse_warn (cfile,
                    616:                                    "omapi port only works at top level.");
                    617:                else
                    618:                        config -> omapi_port = tmp;
                    619:                parse_semi (cfile);
                    620:                return;
                    621:                
                    622:              case DO_FORWARD_UPDATE:
                    623:                token = next_token (&val, (unsigned *)0, cfile);
                    624:                token = next_token (&val, (unsigned *)0, cfile);
                    625:                if (!strcasecmp (val, "on") ||
                    626:                    !strcasecmp (val, "true"))
                    627:                        config -> do_forward_update = 1;
                    628:                else if (!strcasecmp (val, "off") ||
                    629:                         !strcasecmp (val, "false"))
                    630:                        config -> do_forward_update = 0;
                    631:                else {
                    632:                        parse_warn (cfile, "expecting boolean value.");
                    633:                        skip_to_semi (cfile);
                    634:                        return;
                    635:                }
                    636:                parse_semi (cfile);
                    637:                return;
                    638: 
                    639:              case REBOOT:
                    640:                token = next_token (&val, (unsigned *)0, cfile);
                    641:                parse_lease_time (cfile, &config -> reboot_timeout);
                    642:                return;
                    643: 
                    644:              case BACKOFF_CUTOFF:
                    645:                token = next_token (&val, (unsigned *)0, cfile);
                    646:                parse_lease_time (cfile, &config -> backoff_cutoff);
                    647:                return;
                    648: 
                    649:              case INITIAL_INTERVAL:
                    650:                token = next_token (&val, (unsigned *)0, cfile);
                    651:                parse_lease_time (cfile, &config -> initial_interval);
                    652:                return;
                    653: 
                    654:              case INITIAL_DELAY:
                    655:                token = next_token (&val, (unsigned *)0, cfile);
                    656:                parse_lease_time (cfile, &config -> initial_delay);
                    657:                return;
                    658: 
                    659:              case SCRIPT:
                    660:                token = next_token (&val, (unsigned *)0, cfile);
                    661:                parse_string (cfile, &config -> script_name, (unsigned *)0);
                    662:                return;
                    663: 
                    664:              case VENDOR:
                    665:                token = next_token (&val, (unsigned *)0, cfile);
                    666:                token = next_token (&val, (unsigned *)0, cfile);
                    667:                if (token != OPTION) {
                    668:                        parse_warn (cfile, "expecting 'vendor option space'");
                    669:                        skip_to_semi (cfile);
                    670:                        return;
                    671:                }
                    672:                token = next_token (&val, (unsigned *)0, cfile);
                    673:                if (token != SPACE) {
                    674:                        parse_warn (cfile, "expecting 'vendor option space'");
                    675:                        skip_to_semi (cfile);
                    676:                        return;
                    677:                }
                    678:                token = next_token (&val, (unsigned *)0, cfile);
                    679:                if (!is_identifier (token)) {
                    680:                        parse_warn (cfile, "expecting an identifier.");
                    681:                        skip_to_semi (cfile);
                    682:                        return;
                    683:                }
                    684:                config -> vendor_space_name = dmalloc (strlen (val) + 1, MDL);
                    685:                if (!config -> vendor_space_name)
                    686:                        log_fatal ("no memory for vendor option space name.");
                    687:                strcpy (config -> vendor_space_name, val);
                    688:                for (i = 0; i < universe_count; i++)
                    689:                        if (!strcmp (universes [i] -> name,
                    690:                                     config -> vendor_space_name))
                    691:                                break;
                    692:                if (i == universe_count) {
                    693:                        log_error ("vendor option space %s not found.",
                    694:                                   config -> vendor_space_name);
                    695:                }
                    696:                parse_semi (cfile);
                    697:                return;
                    698: 
                    699:              case INTERFACE:
                    700:                token = next_token (&val, (unsigned *)0, cfile);
                    701:                if (ip)
                    702:                        parse_warn (cfile, "nested interface declaration.");
                    703:                parse_interface_declaration (cfile, config, (char *)0);
                    704:                return;
                    705: 
                    706:              case PSEUDO:
                    707:                token = next_token (&val, (unsigned *)0, cfile);
                    708:                token = next_token (&val, (unsigned *)0, cfile);
                    709:                name = dmalloc (strlen (val) + 1, MDL);
                    710:                if (!name)
                    711:                        log_fatal ("no memory for pseudo interface name");
                    712:                strcpy (name, val);
                    713:                parse_interface_declaration (cfile, config, name);
                    714:                return;
                    715:                
                    716:              case LEASE:
                    717:                token = next_token (&val, (unsigned *)0, cfile);
                    718:                parse_client_lease_statement (cfile, 1);
                    719:                return;
                    720: 
                    721:              case ALIAS:
                    722:                token = next_token (&val, (unsigned *)0, cfile);
                    723:                parse_client_lease_statement (cfile, 2);
                    724:                return;
                    725: 
                    726:              case REJECT:
                    727:                token = next_token (&val, (unsigned *)0, cfile);
                    728:                parse_reject_statement (cfile, config);
                    729:                return;
                    730: 
                    731:              default:
                    732:                lose = 0;
                    733:                stmt = (struct executable_statement *)0;
                    734:                if (!parse_executable_statement (&stmt,
                    735:                                                 cfile, &lose, context_any)) {
                    736:                        if (!lose) {
                    737:                                parse_warn (cfile, "expecting a statement.");
                    738:                                skip_to_semi (cfile);
                    739:                        }
                    740:                } else {
                    741:                        struct executable_statement **eptr, *sptr;
                    742:                        if (stmt &&
                    743:                            (stmt -> op == send_option_statement ||
                    744:                             (stmt -> op == on_statement &&
                    745:                              (stmt -> data.on.evtypes & ON_TRANSMISSION)))) {
                    746:                            eptr = &config -> on_transmission -> statements;
                    747:                            if (stmt -> op == on_statement) {
                    748:                                    sptr = (struct executable_statement *)0;
                    749:                                    executable_statement_reference
                    750:                                            (&sptr,
                    751:                                             stmt -> data.on.statements, MDL);
                    752:                                    executable_statement_dereference (&stmt,
                    753:                                                                      MDL);
                    754:                                    executable_statement_reference (&stmt,
                    755:                                                                    sptr,
                    756:                                                                    MDL);
                    757:                                    executable_statement_dereference (&sptr,
                    758:                                                                      MDL);
                    759:                            }
                    760:                        } else
                    761:                            eptr = &config -> on_receipt -> statements;
                    762: 
                    763:                        if (stmt) {
                    764:                                for (; *eptr; eptr = &(*eptr) -> next)
                    765:                                        ;
                    766:                                executable_statement_reference (eptr,
                    767:                                                                stmt, MDL);
                    768:                        }
                    769:                        return;
                    770:                }
                    771:                break;
                    772:        }
                    773:        parse_semi (cfile);
                    774: }
                    775: 
                    776: /* option-list :== option_name |
                    777:                   option_list COMMA option_name */
                    778: 
                    779: int
                    780: parse_option_list(struct parse *cfile, struct option ***list)
                    781: {
                    782:        int ix;
                    783:        int token;
                    784:        const char *val;
                    785:        pair p = (pair)0, q = (pair)0, r;
                    786:        struct option *option = NULL;
                    787:        isc_result_t status;
                    788: 
                    789:        ix = 0;
                    790:        do {
                    791:                token = peek_token (&val, (unsigned *)0, cfile);
                    792:                if (token == SEMI) {
                    793:                        token = next_token (&val, (unsigned *)0, cfile);
                    794:                        break;
                    795:                }
                    796:                if (!is_identifier (token)) {
                    797:                        parse_warn (cfile, "%s: expected option name.", val);
                    798:                        token = next_token (&val, (unsigned *)0, cfile);
                    799:                        skip_to_semi (cfile);
                    800:                        return 0;
                    801:                }
                    802:                status = parse_option_name(cfile, 0, NULL, &option);
                    803:                if (status != ISC_R_SUCCESS || option == NULL) {
                    804:                        parse_warn (cfile, "%s: expected option name.", val);
                    805:                        return 0;
                    806:                }
                    807:                r = new_pair (MDL);
                    808:                if (!r)
                    809:                        log_fatal ("can't allocate pair for option code.");
                    810:                /* XXX: we should probably carry a reference across this */
                    811:                r->car = (caddr_t)option;
                    812:                option_dereference(&option, MDL);
                    813:                r -> cdr = (pair)0;
                    814:                if (p)
                    815:                        q -> cdr = r;
                    816:                else
                    817:                        p = r;
                    818:                q = r;
                    819:                ++ix;
                    820:                token = next_token (&val, (unsigned *)0, cfile);
                    821:        } while (token == COMMA);
                    822:        if (token != SEMI) {
                    823:                parse_warn (cfile, "expecting semicolon.");
                    824:                skip_to_semi (cfile);
                    825:                return 0;
                    826:        }
                    827:        /* XXX we can't free the list here, because we may have copied
                    828:           XXX it from an outer config state. */
                    829:        *list = NULL;
                    830:        if (ix) {
                    831:                *list = dmalloc ((ix + 1) * sizeof(struct option *), MDL);
                    832:                if (!*list)
                    833:                        log_error ("no memory for option list.");
                    834:                else {
                    835:                        ix = 0;
                    836:                        for (q = p; q; q = q -> cdr)
                    837:                                option_reference(&(*list)[ix++],
                    838:                                                 (struct option *)q->car, MDL);
                    839:                        (*list)[ix] = NULL;
                    840:                }
                    841:                while (p) {
                    842:                        q = p -> cdr;
                    843:                        free_pair (p, MDL);
                    844:                        p = q;
                    845:                }
                    846:        }
                    847: 
                    848:        return ix;
                    849: }
                    850: 
                    851: /* interface-declaration :==
                    852:        INTERFACE string LBRACE client-declarations RBRACE */
                    853: 
                    854: void parse_interface_declaration (cfile, outer_config, name)
                    855:        struct parse *cfile;
                    856:        struct client_config *outer_config;
                    857:        char *name;
                    858: {
                    859:        int token;
                    860:        const char *val;
                    861:        struct client_state *client, **cp;
                    862:        struct interface_info *ip = (struct interface_info *)0;
                    863: 
                    864:        token = next_token (&val, (unsigned *)0, cfile);
                    865:        if (token != STRING) {
                    866:                parse_warn (cfile, "expecting interface name (in quotes).");
                    867:                skip_to_semi (cfile);
                    868:                return;
                    869:        }
                    870: 
                    871:        if (!interface_or_dummy (&ip, val))
                    872:                log_fatal ("Can't allocate interface %s.", val);
                    873: 
                    874:        /* If we were given a name, this is a pseudo-interface. */
                    875:        if (name) {
                    876:                make_client_state (&client);
                    877:                client -> name = name;
                    878:                client -> interface = ip;
                    879:                for (cp = &ip -> client; *cp; cp = &((*cp) -> next))
                    880:                        ;
                    881:                *cp = client;
                    882:        } else {
                    883:                if (!ip -> client) {
                    884:                        make_client_state (&ip -> client);
                    885:                        ip -> client -> interface = ip;
                    886:                }
                    887:                client = ip -> client;
                    888:        }
                    889: 
                    890:        if (!client -> config)
                    891:                make_client_config (client, outer_config);
                    892: 
                    893:        ip -> flags &= ~INTERFACE_AUTOMATIC;
                    894:        interfaces_requested = 1;
                    895: 
                    896:        token = next_token (&val, (unsigned *)0, cfile);
                    897:        if (token != LBRACE) {
                    898:                parse_warn (cfile, "expecting left brace.");
                    899:                skip_to_semi (cfile);
                    900:                return;
                    901:        }
                    902: 
                    903:        do {
                    904:                token = peek_token (&val, (unsigned *)0, cfile);
                    905:                if (token == END_OF_FILE) {
                    906:                        parse_warn (cfile,
                    907:                                    "unterminated interface declaration.");
                    908:                        return;
                    909:                }
                    910:                if (token == RBRACE)
                    911:                        break;
                    912:                parse_client_statement (cfile, ip, client -> config);
                    913:        } while (1);
                    914:        token = next_token (&val, (unsigned *)0, cfile);
                    915: }
                    916: 
                    917: int interface_or_dummy (struct interface_info **pi, const char *name)
                    918: {
                    919:        struct interface_info *i;
                    920:        struct interface_info *ip = (struct interface_info *)0;
                    921:        isc_result_t status;
                    922: 
                    923:        /* Find the interface (if any) that matches the name. */
                    924:        for (i = interfaces; i; i = i -> next) {
                    925:                if (!strcmp (i -> name, name)) {
                    926:                        interface_reference (&ip, i, MDL);
                    927:                        break;
                    928:                }
                    929:        }
                    930: 
                    931:        /* If it's not a real interface, see if it's on the dummy list. */
                    932:        if (!ip) {
                    933:                for (ip = dummy_interfaces; ip; ip = ip -> next) {
                    934:                        if (!strcmp (ip -> name, name)) {
                    935:                                interface_reference (&ip, i, MDL);
                    936:                                break;
                    937:                        }
                    938:                }
                    939:        }
                    940: 
                    941:        /* If we didn't find an interface, make a dummy interface as
                    942:           a placeholder. */
                    943:        if (!ip) {
                    944:                if ((status = interface_allocate (&ip, MDL)) != ISC_R_SUCCESS)
                    945:                        log_fatal ("Can't record interface %s: %s",
                    946:                                   name, isc_result_totext (status));
                    947: 
                    948:                if (strlen(name) >= sizeof(ip->name)) {
                    949:                        interface_dereference(&ip, MDL);
                    950:                        return 0;
                    951:                }
                    952:                strcpy(ip->name, name);
                    953: 
                    954:                if (dummy_interfaces) {
                    955:                        interface_reference (&ip -> next,
                    956:                                             dummy_interfaces, MDL);
                    957:                        interface_dereference (&dummy_interfaces, MDL);
                    958:                }
                    959:                interface_reference (&dummy_interfaces, ip, MDL);
                    960:        }
                    961:        if (pi)
                    962:                status = interface_reference (pi, ip, MDL);
                    963:        else
                    964:                status = ISC_R_FAILURE;
                    965:        interface_dereference (&ip, MDL);
                    966:        if (status != ISC_R_SUCCESS)
                    967:                return 0;
                    968:        return 1;
                    969: }
                    970: 
                    971: void make_client_state (state)
                    972:        struct client_state **state;
                    973: {
                    974:        *state = ((struct client_state *)dmalloc (sizeof **state, MDL));
                    975:        if (!*state)
                    976:                log_fatal ("no memory for client state\n");
                    977:        memset (*state, 0, sizeof **state);
                    978: }
                    979: 
                    980: void make_client_config (client, config)
                    981:        struct client_state *client;
                    982:        struct client_config *config;
                    983: {
                    984:        client -> config = (((struct client_config *)
                    985:                             dmalloc (sizeof (struct client_config), MDL)));
                    986:        if (!client -> config)
                    987:                log_fatal ("no memory for client config\n");
                    988:        memcpy (client -> config, config, sizeof *config);
                    989:        if (!clone_group (&client -> config -> on_receipt,
                    990:                          config -> on_receipt, MDL) ||
                    991:            !clone_group (&client -> config -> on_transmission,
                    992:                          config -> on_transmission, MDL))
                    993:                log_fatal ("no memory for client state groups.");
                    994: }
                    995: 
                    996: /* client-lease-statement :==
                    997:        LBRACE client-lease-declarations RBRACE
                    998: 
                    999:        client-lease-declarations :==
                   1000:                <nil> |
                   1001:                client-lease-declaration |
                   1002:                client-lease-declarations client-lease-declaration */
                   1003: 
                   1004: 
                   1005: void parse_client_lease_statement (cfile, is_static)
                   1006:        struct parse *cfile;
                   1007:        int is_static;
                   1008: {
                   1009:        struct client_lease *lease, *lp, *pl, *next;
                   1010:        struct interface_info *ip = (struct interface_info *)0;
                   1011:        int token;
                   1012:        const char *val;
                   1013:        struct client_state *client = (struct client_state *)0;
                   1014: 
                   1015:        token = next_token (&val, (unsigned *)0, cfile);
                   1016:        if (token != LBRACE) {
                   1017:                parse_warn (cfile, "expecting left brace.");
                   1018:                skip_to_semi (cfile);
                   1019:                return;
                   1020:        }
                   1021: 
                   1022:        lease = ((struct client_lease *)
                   1023:                 dmalloc (sizeof (struct client_lease), MDL));
                   1024:        if (!lease)
                   1025:                log_fatal ("no memory for lease.\n");
                   1026:        memset (lease, 0, sizeof *lease);
                   1027:        lease -> is_static = is_static;
                   1028:        if (!option_state_allocate (&lease -> options, MDL))
                   1029:                log_fatal ("no memory for lease options.\n");
                   1030: 
                   1031:        do {
                   1032:                token = peek_token (&val, (unsigned *)0, cfile);
                   1033:                if (token == END_OF_FILE) {
                   1034:                        parse_warn (cfile, "unterminated lease declaration.");
                   1035:                        return;
                   1036:                }
                   1037:                if (token == RBRACE)
                   1038:                        break;
                   1039:                parse_client_lease_declaration (cfile, lease, &ip, &client);
                   1040:        } while (1);
                   1041:        token = next_token (&val, (unsigned *)0, cfile);
                   1042: 
                   1043:        /* If the lease declaration didn't include an interface
                   1044:           declaration that we recognized, it's of no use to us. */
                   1045:        if (!ip) {
                   1046:                destroy_client_lease (lease);
                   1047:                return;
                   1048:        }
                   1049: 
                   1050:        /* Make sure there's a client state structure... */
                   1051:        if (!ip -> client) {
                   1052:                make_client_state (&ip -> client);
                   1053:                ip -> client -> interface = ip;
                   1054:        }
                   1055:        if (!client)
                   1056:                client = ip -> client;
                   1057: 
                   1058:        /* If this is an alias lease, it doesn't need to be sorted in. */
                   1059:        if (is_static == 2) {
                   1060:                ip -> client -> alias = lease;
                   1061:                return;
                   1062:        }
                   1063: 
                   1064:        /* The new lease may supersede a lease that's not the
                   1065:           active lease but is still on the lease list, so scan the
                   1066:           lease list looking for a lease with the same address, and
                   1067:           if we find it, toss it. */
                   1068:        pl = (struct client_lease *)0;
                   1069:        for (lp = client -> leases; lp; lp = next) {
                   1070:                next = lp -> next;
                   1071:                if (lp -> address.len == lease -> address.len &&
                   1072:                    !memcmp (lp -> address.iabuf, lease -> address.iabuf,
                   1073:                             lease -> address.len)) {
                   1074:                        if (pl)
                   1075:                                pl -> next = next;
                   1076:                        else
                   1077:                                client -> leases = next;
                   1078:                        destroy_client_lease (lp);
                   1079:                        break;
                   1080:                } else
                   1081:                        pl = lp;
                   1082:        }
                   1083: 
                   1084:        /* If this is a preloaded lease, just put it on the list of recorded
                   1085:           leases - don't make it the active lease. */
                   1086:        if (is_static) {
                   1087:                lease -> next = client -> leases;
                   1088:                client -> leases = lease;
                   1089:                return;
                   1090:        }
                   1091:                
                   1092:        /* The last lease in the lease file on a particular interface is
                   1093:           the active lease for that interface.    Of course, we don't know
                   1094:           what the last lease in the file is until we've parsed the whole
                   1095:           file, so at this point, we assume that the lease we just parsed
                   1096:           is the active lease for its interface.   If there's already
                   1097:           an active lease for the interface, and this lease is for the same
                   1098:           ip address, then we just toss the old active lease and replace
                   1099:           it with this one.   If this lease is for a different address,
                   1100:           then if the old active lease has expired, we dump it; if not,
                   1101:           we put it on the list of leases for this interface which are
                   1102:           still valid but no longer active. */
                   1103:        if (client -> active) {
                   1104:                if (client -> active -> expiry < cur_time)
                   1105:                        destroy_client_lease (client -> active);
                   1106:                else if (client -> active -> address.len ==
                   1107:                         lease -> address.len &&
                   1108:                         !memcmp (client -> active -> address.iabuf,
                   1109:                                  lease -> address.iabuf,
                   1110:                                  lease -> address.len))
                   1111:                        destroy_client_lease (client -> active);
                   1112:                else {
                   1113:                        client -> active -> next = client -> leases;
                   1114:                        client -> leases = client -> active;
                   1115:                }
                   1116:        }
                   1117:        client -> active = lease;
                   1118: 
                   1119:        /* phew. */
                   1120: }
                   1121: 
                   1122: /* client-lease-declaration :==
                   1123:        BOOTP |
                   1124:        INTERFACE string |
                   1125:        FIXED_ADDR ip_address |
                   1126:        FILENAME string |
                   1127:        SERVER_NAME string |
                   1128:        OPTION option-decl |
                   1129:        RENEW time-decl |
                   1130:        REBIND time-decl |
                   1131:        EXPIRE time-decl |
                   1132:        KEY id */
                   1133: 
                   1134: void parse_client_lease_declaration (cfile, lease, ipp, clientp)
                   1135:        struct parse *cfile;
                   1136:        struct client_lease *lease;
                   1137:        struct interface_info **ipp;
                   1138:        struct client_state **clientp;
                   1139: {
                   1140:        int token;
                   1141:        const char *val;
                   1142:        struct interface_info *ip;
                   1143:        struct option_cache *oc;
                   1144:        struct client_state *client = (struct client_state *)0;
                   1145: 
                   1146:        switch (next_token (&val, (unsigned *)0, cfile)) {
                   1147:              case KEY:
                   1148:                token = next_token (&val, (unsigned *)0, cfile);
                   1149:                if (token != STRING && !is_identifier (token)) {
                   1150:                        parse_warn (cfile, "expecting key name.");
                   1151:                        skip_to_semi (cfile);
                   1152:                        break;
                   1153:                }
                   1154:                if (omapi_auth_key_lookup_name (&lease -> key, val) !=
                   1155:                    ISC_R_SUCCESS)
                   1156:                        parse_warn (cfile, "unknown key %s", val);
                   1157:                parse_semi (cfile);
                   1158:                break;
                   1159:              case TOKEN_BOOTP:
                   1160:                lease -> is_bootp = 1;
                   1161:                break;
                   1162: 
                   1163:              case INTERFACE:
                   1164:                token = next_token (&val, (unsigned *)0, cfile);
                   1165:                if (token != STRING) {
                   1166:                        parse_warn (cfile,
                   1167:                                    "expecting interface name (in quotes).");
                   1168:                        skip_to_semi (cfile);
                   1169:                        break;
                   1170:                }
                   1171:                if (!interface_or_dummy (ipp, val))
                   1172:                        log_fatal ("Can't allocate interface %s.", val);
                   1173:                break;
                   1174: 
                   1175:              case NAME:
                   1176:                token = next_token (&val, (unsigned *)0, cfile);
                   1177:                ip = *ipp;
                   1178:                if (!ip) {
                   1179:                        parse_warn (cfile, "state name precedes interface.");
                   1180:                        break;
                   1181:                }
                   1182:                for (client = ip -> client; client; client = client -> next)
                   1183:                        if (client -> name && !strcmp (client -> name, val))
                   1184:                                break;
                   1185:                if (!client)
                   1186:                        parse_warn (cfile,
                   1187:                                    "lease specified for unknown pseudo.");
                   1188:                *clientp = client;
                   1189:                break;
                   1190: 
                   1191:              case FIXED_ADDR:
                   1192:                if (!parse_ip_addr (cfile, &lease -> address))
                   1193:                        return;
                   1194:                break;
                   1195: 
                   1196:              case MEDIUM:
                   1197:                parse_string_list (cfile, &lease -> medium, 0);
                   1198:                return;
                   1199: 
                   1200:              case FILENAME:
                   1201:                parse_string (cfile, &lease -> filename, (unsigned *)0);
                   1202:                return;
                   1203: 
                   1204:              case SERVER_NAME:
                   1205:                parse_string (cfile, &lease -> server_name, (unsigned *)0);
                   1206:                return;
                   1207: 
                   1208:              case RENEW:
                   1209:                lease -> renewal = parse_date (cfile);
                   1210:                return;
                   1211: 
                   1212:              case REBIND:
                   1213:                lease -> rebind = parse_date (cfile);
                   1214:                return;
                   1215: 
                   1216:              case EXPIRE:
                   1217:                lease -> expiry = parse_date (cfile);
                   1218:                return;
                   1219: 
                   1220:              case OPTION:
                   1221:                oc = (struct option_cache *)0;
                   1222:                if (parse_option_decl (&oc, cfile)) {
                   1223:                        save_option(oc->option->universe, lease->options, oc);
                   1224:                        option_cache_dereference (&oc, MDL);
                   1225:                }
                   1226:                return;
                   1227: 
                   1228:              default:
                   1229:                parse_warn (cfile, "expecting lease declaration.");
                   1230:                skip_to_semi (cfile);
                   1231:                break;
                   1232:        }
                   1233:        token = next_token (&val, (unsigned *)0, cfile);
                   1234:        if (token != SEMI) {
                   1235:                parse_warn (cfile, "expecting semicolon.");
                   1236:                skip_to_semi (cfile);
                   1237:        }
                   1238: }
                   1239: 
                   1240: /* Parse a default-duid ""; statement.
                   1241:  */
                   1242: static void
                   1243: parse_client_default_duid(struct parse *cfile)
                   1244: {
                   1245:        struct data_string new_duid;
                   1246:        const char *val = NULL;
                   1247:        unsigned len;
                   1248:        int token;
                   1249: 
                   1250:        memset(&new_duid, 0, sizeof(new_duid));
                   1251: 
                   1252:        token = next_token(&val, &len, cfile);
                   1253:        if (token != STRING) {
                   1254:                parse_warn(cfile, "Expected DUID string.");
                   1255:                skip_to_semi(cfile);
                   1256:                return;
                   1257:        }
                   1258: 
                   1259:        if (len <= 2) {
                   1260:                parse_warn(cfile, "Invalid DUID contents.");
                   1261:                skip_to_semi(cfile);
                   1262:                return;
                   1263:        }
                   1264: 
                   1265:        if (!buffer_allocate(&new_duid.buffer, len, MDL)) {
                   1266:                parse_warn(cfile, "Out of memory parsing default DUID.");
                   1267:                skip_to_semi(cfile);
                   1268:                return;
                   1269:        }
                   1270:        new_duid.data = new_duid.buffer->data;
                   1271:        new_duid.len = len;
                   1272: 
                   1273:        memcpy(new_duid.buffer->data, val, len);
                   1274: 
                   1275:        /* Rotate the last entry into place. */
                   1276:        if (default_duid.buffer != NULL)
                   1277:                data_string_forget(&default_duid, MDL);
                   1278:        data_string_copy(&default_duid, &new_duid, MDL);
                   1279:        data_string_forget(&new_duid, MDL);
                   1280: 
                   1281:        parse_semi(cfile);
                   1282: }
                   1283: 
                   1284: /* Parse a lease6 {} construct.  The v6 client is a little different
                   1285:  * than the v4 client today, in that it only retains one lease, the
                   1286:  * active lease, and discards any less recent information.  It may
                   1287:  * be useful in the future to cache additional information, but it
                   1288:  * is not worth the effort for the moment.
                   1289:  */
                   1290: static void
                   1291: parse_client6_lease_statement(struct parse *cfile)
                   1292: {
                   1293: #if !defined(DHCPv6)
                   1294:        parse_warn(cfile, "No DHCPv6 support.");
                   1295:        skip_to_semi(cfile);
                   1296: #else /* defined(DHCPv6) */
                   1297:        struct option_cache *oc = NULL;
                   1298:        struct dhc6_lease *lease;
                   1299:        struct dhc6_ia **ia;
                   1300:        struct client_state *client = NULL;
                   1301:        struct interface_info *iface = NULL;
                   1302:        struct data_string ds;
                   1303:        const char *val;
                   1304:        unsigned len;
                   1305:        int token, has_ia, no_semi, has_name;
                   1306: 
                   1307:        token = next_token(NULL, NULL, cfile);
                   1308:        if (token != LBRACE) {
                   1309:                parse_warn(cfile, "Expecting open curly brace.");
                   1310:                skip_to_semi(cfile);
                   1311:                return;
                   1312:        }
                   1313: 
                   1314:        lease = dmalloc(sizeof(*lease), MDL);
                   1315:        if (lease == NULL) {
                   1316:                parse_warn(cfile, "Unable to allocate lease state.");
                   1317:                skip_to_rbrace(cfile, 1);
                   1318:                return;
                   1319:        }
                   1320: 
                   1321:        option_state_allocate(&lease->options, MDL);
                   1322:        if (lease->options == NULL) {
                   1323:                parse_warn(cfile, "Unable to allocate option cache.");
                   1324:                skip_to_rbrace(cfile, 1);
                   1325:                dfree(lease, MDL);
                   1326:                return;
                   1327:        }
                   1328: 
                   1329:        has_ia = 0;
                   1330:        has_name = 0;
                   1331:        ia = &lease->bindings;
                   1332:        token = next_token(&val, NULL, cfile);
                   1333:        while (token != RBRACE) {
                   1334:                no_semi = 0;
                   1335: 
                   1336:                switch(token) {
                   1337:                      case IA_NA:
                   1338:                        *ia = parse_client6_ia_na_statement(cfile);
                   1339:                        if (*ia != NULL) {
                   1340:                                ia = &(*ia)->next;
                   1341:                                has_ia = 1;
                   1342:                        }
                   1343: 
                   1344:                        no_semi = 1;
                   1345: 
                   1346:                        break;
                   1347: 
                   1348:                      case IA_TA:
                   1349:                        *ia = parse_client6_ia_ta_statement(cfile);
                   1350:                        if (*ia != NULL) {
                   1351:                                ia = &(*ia)->next;
                   1352:                                has_ia = 1;
                   1353:                        }
                   1354: 
                   1355:                        no_semi = 1;
                   1356: 
                   1357:                        break;
                   1358: 
                   1359:                      case IA_PD:
                   1360:                        *ia = parse_client6_ia_pd_statement(cfile);
                   1361:                        if (*ia != NULL) {
                   1362:                                ia = &(*ia)->next;
                   1363:                                has_ia = 1;
                   1364:                        }
                   1365: 
                   1366:                        no_semi = 1;
                   1367: 
                   1368:                        break;
                   1369: 
                   1370:                      case INTERFACE:
                   1371:                        if (iface != NULL) {
                   1372:                                parse_warn(cfile, "Multiple interface names?");
                   1373:                                skip_to_semi(cfile);
                   1374:                                no_semi = 1;
                   1375:                                break;
                   1376:                        }
                   1377: 
                   1378:                        token = next_token(&val, &len, cfile);
                   1379:                        if (token != STRING) {
                   1380:                              strerror:
                   1381:                                parse_warn(cfile, "Expecting a string.");
                   1382:                                skip_to_semi(cfile);
                   1383:                                no_semi = 1;
                   1384:                                break;
                   1385:                        }
                   1386: 
                   1387:                        for (iface = interfaces ; iface != NULL ;
                   1388:                             iface = iface->next) {
                   1389:                                if (strcmp(iface->name, val) == 0)
                   1390:                                        break;
                   1391:                        }
                   1392: 
                   1393:                        if (iface == NULL) {
                   1394:                                parse_warn(cfile, "Unknown interface.");
                   1395:                                break;
                   1396:                        }
                   1397: 
                   1398:                        break;
                   1399: 
                   1400:                      case NAME:
                   1401:                        has_name = 1;
                   1402: 
                   1403:                        if (client != NULL) {
                   1404:                                parse_warn(cfile, "Multiple state names?");
                   1405:                                skip_to_semi(cfile);
                   1406:                                no_semi = 1;
                   1407:                                break;
                   1408:                        }
                   1409: 
                   1410:                        if (iface == NULL) {
                   1411:                                parse_warn(cfile, "Client name without "
                   1412:                                                  "interface.");
                   1413:                                skip_to_semi(cfile);
                   1414:                                no_semi = 1;
                   1415:                                break;
                   1416:                        }
                   1417: 
                   1418:                        token = next_token(&val, &len, cfile);
                   1419:                        if (token != STRING)
                   1420:                                goto strerror;
                   1421: 
                   1422:                        for (client = iface->client ; client != NULL ;
                   1423:                             client = client->next) {
                   1424:                                if ((client->name != NULL) &&
                   1425:                                    (strcmp(client->name, val) == 0))
                   1426:                                        break;
                   1427:                        }
                   1428: 
                   1429:                        if (client == NULL) {
                   1430:                                parse_warn(cfile, "Unknown client state %s.",
                   1431:                                           val);
                   1432:                                break;
                   1433:                        }
                   1434: 
                   1435:                        break;
                   1436: 
                   1437:                      case OPTION:
                   1438:                        if (parse_option_decl(&oc, cfile)) {
                   1439:                                save_option(oc->option->universe,
                   1440:                                            lease->options, oc);
                   1441:                                option_cache_dereference(&oc, MDL);
                   1442:                        }
                   1443:                        no_semi = 1;
                   1444:                        break;
                   1445: 
                   1446:                      case TOKEN_RELEASED:
                   1447:                      case TOKEN_ABANDONED:
                   1448:                        lease->released = ISC_TRUE;
                   1449:                        break;
                   1450: 
                   1451:                      default:
                   1452:                        parse_warn(cfile, "Unexpected token, %s.", val);
                   1453:                        no_semi = 1;
                   1454:                        skip_to_semi(cfile);
                   1455:                        break;
                   1456:                }
                   1457: 
                   1458:                if (!no_semi)
                   1459:                        parse_semi(cfile);
                   1460: 
                   1461:                token = next_token(&val, NULL, cfile);
                   1462: 
                   1463:                if (token == END_OF_FILE) {
                   1464:                        parse_warn(cfile, "Unexpected end of file.");
                   1465:                        break;
                   1466:                }
                   1467:        }
                   1468: 
                   1469:        if (!has_ia) {
                   1470:                log_debug("Lease with no IA's discarded from lease db.");
                   1471:                dhc6_lease_destroy(&lease, MDL);
                   1472:                return;
                   1473:        }
                   1474: 
                   1475:        if (iface == NULL)
                   1476:                parse_warn(cfile, "Lease has no interface designation.");
                   1477:        else if (!has_name && (client == NULL)) {
                   1478:                for (client = iface->client ; client != NULL ;
                   1479:                     client = client->next) {
                   1480:                        if (client->name == NULL)
                   1481:                                break;
                   1482:                }
                   1483:        }
                   1484: 
                   1485:        if (client == NULL) {
                   1486:                parse_warn(cfile, "No matching client state.");
                   1487:                dhc6_lease_destroy(&lease, MDL);
                   1488:                return;
                   1489:        }
                   1490: 
                   1491:        /* Fetch Preference option from option cache. */
                   1492:        memset(&ds, 0, sizeof(ds));
                   1493:        oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
                   1494:        if ((oc != NULL) &&
                   1495:            evaluate_option_cache(&ds, NULL, NULL, NULL, lease->options,
                   1496:                                  NULL, &global_scope, oc, MDL)) {
                   1497:                if (ds.len != 1) {
                   1498:                        log_error("Invalid length of DHCPv6 Preference option "
                   1499:                                  "(%d != 1)", ds.len);
                   1500:                        data_string_forget(&ds, MDL);
                   1501:                        dhc6_lease_destroy(&lease, MDL);
                   1502:                        return;
                   1503:                } else
                   1504:                        lease->pref = ds.data[0];
                   1505: 
                   1506:                data_string_forget(&ds, MDL);
                   1507:        }
                   1508: 
                   1509:        /* Fetch server-id option from option cache. */
                   1510:        oc = lookup_option(&dhcpv6_universe, lease->options, D6O_SERVERID);
                   1511:        if ((oc == NULL) ||
                   1512:            !evaluate_option_cache(&lease->server_id, NULL, NULL, NULL,
                   1513:                                   lease->options, NULL, &global_scope, oc,
                   1514:                                   MDL) ||
                   1515:            (lease->server_id.len == 0)) {
                   1516:                /* This should be impossible... */
                   1517:                log_error("Invalid SERVERID option cache.");
                   1518:                dhc6_lease_destroy(&lease, MDL);
                   1519:                return;
                   1520:        }
                   1521: 
                   1522:        if (client->active_lease != NULL)
                   1523:                dhc6_lease_destroy(&client->active_lease, MDL);
                   1524: 
                   1525:        client->active_lease = lease;
                   1526: #endif /* defined(DHCPv6) */
                   1527: }
                   1528: 
                   1529: /* Parse an ia_na object from the client lease.
                   1530:  */
                   1531: #ifdef DHCPv6
                   1532: static struct dhc6_ia *
                   1533: parse_client6_ia_na_statement(struct parse *cfile)
                   1534: {
                   1535:        struct option_cache *oc = NULL;
                   1536:        struct dhc6_ia *ia;
                   1537:        struct dhc6_addr **addr;
                   1538:        const char *val;
                   1539:        int token, no_semi, len;
                   1540:        u_int8_t buf[5];
                   1541: 
                   1542:        ia = dmalloc(sizeof(*ia), MDL);
                   1543:        if (ia == NULL) {
                   1544:                parse_warn(cfile, "Out of memory allocating IA_NA state.");
                   1545:                skip_to_semi(cfile);
                   1546:                return NULL;
                   1547:        }
                   1548:        ia->ia_type = D6O_IA_NA;
                   1549: 
                   1550:        /* Get IAID. */
                   1551:        len = parse_X(cfile, buf, 5);
                   1552:        if (len == 4) {
                   1553:                memcpy(ia->iaid, buf, 4);
                   1554:        } else {
                   1555:                parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
                   1556:                skip_to_semi(cfile);
                   1557:                dfree(ia, MDL);
                   1558:                return NULL;
                   1559:        }
                   1560: 
                   1561:        token = next_token(NULL, NULL, cfile);
                   1562:        if (token != LBRACE) {
                   1563:                parse_warn(cfile, "Expecting open curly brace.");
                   1564:                skip_to_semi(cfile);
                   1565:                dfree(ia, MDL);
                   1566:                return NULL;
                   1567:        }
                   1568: 
                   1569:        option_state_allocate(&ia->options, MDL);
                   1570:        if (ia->options == NULL) {
                   1571:                parse_warn(cfile, "Unable to allocate option state.");
                   1572:                skip_to_rbrace(cfile, 1);
                   1573:                dfree(ia, MDL);
                   1574:                return NULL;
                   1575:        }
                   1576: 
                   1577:        addr = &ia->addrs;
                   1578:        token = next_token(&val, NULL, cfile);
                   1579:        while (token != RBRACE) {
                   1580:                no_semi = 0;
                   1581: 
                   1582:                switch (token) {
                   1583:                      case STARTS:
                   1584:                        token = next_token(&val, NULL, cfile);
                   1585:                        if (token == NUMBER) {
                   1586:                                ia->starts = atoi(val);
                   1587:                        } else {
                   1588:                                parse_warn(cfile, "Expecting a number.");
                   1589:                                skip_to_semi(cfile);
                   1590:                                no_semi = 1;
                   1591:                        }
                   1592:                        break;
                   1593: 
                   1594:                      case RENEW:
                   1595:                        token = next_token(&val, NULL, cfile);
                   1596:                        if (token == NUMBER) {
                   1597:                                ia->renew = atoi(val);
                   1598:                        } else {
                   1599:                                parse_warn(cfile, "Expecting a number.");
                   1600:                                skip_to_semi(cfile);
                   1601:                                no_semi = 1;
                   1602:                        }
                   1603:                        break;
                   1604: 
                   1605:                      case REBIND:
                   1606:                        token = next_token(&val, NULL, cfile);
                   1607:                        if (token == NUMBER) {
                   1608:                                ia->rebind = atoi(val);
                   1609:                        } else {
                   1610:                                parse_warn(cfile, "Expecting a number.");
                   1611:                                skip_to_semi(cfile);
                   1612:                                no_semi = 1;
                   1613:                        }
                   1614:                        break;
                   1615: 
                   1616:                      case IAADDR:
                   1617:                        *addr = parse_client6_iaaddr_statement(cfile);
                   1618: 
                   1619:                        if (*addr != NULL)
                   1620:                                addr = &(*addr)->next;
                   1621: 
                   1622:                        no_semi = 1;
                   1623: 
                   1624:                        break;
                   1625: 
                   1626:                      case OPTION:
                   1627:                        if (parse_option_decl(&oc, cfile)) {
                   1628:                                save_option(oc->option->universe,
                   1629:                                            ia->options, oc);
                   1630:                                option_cache_dereference(&oc, MDL);
                   1631:                        }
                   1632:                        no_semi = 1;
                   1633:                        break;
                   1634: 
                   1635:                      default:
                   1636:                        parse_warn(cfile, "Unexpected token.");
                   1637:                        no_semi = 1;
                   1638:                        skip_to_semi(cfile);
                   1639:                        break;
                   1640:                }
                   1641: 
                   1642:                if (!no_semi)
                   1643:                        parse_semi(cfile);
                   1644: 
                   1645:                token = next_token(&val, NULL, cfile);
                   1646: 
                   1647:                if (token == END_OF_FILE) {
                   1648:                        parse_warn(cfile, "Unexpected end of file.");
                   1649:                        break;
                   1650:                }
                   1651:        }
                   1652: 
                   1653:        return ia;
                   1654: }
                   1655: #endif /* DHCPv6 */
                   1656: 
                   1657: /* Parse an ia_ta object from the client lease.
                   1658:  */
                   1659: #ifdef DHCPv6
                   1660: static struct dhc6_ia *
                   1661: parse_client6_ia_ta_statement(struct parse *cfile)
                   1662: {
                   1663:        struct option_cache *oc = NULL;
                   1664:        struct dhc6_ia *ia;
                   1665:        struct dhc6_addr **addr;
                   1666:        const char *val;
                   1667:        int token, no_semi, len;
                   1668:        u_int8_t buf[5];
                   1669: 
                   1670:        ia = dmalloc(sizeof(*ia), MDL);
                   1671:        if (ia == NULL) {
                   1672:                parse_warn(cfile, "Out of memory allocating IA_TA state.");
                   1673:                skip_to_semi(cfile);
                   1674:                return NULL;
                   1675:        }
                   1676:        ia->ia_type = D6O_IA_TA;
                   1677: 
                   1678:        /* Get IAID. */
                   1679:        len = parse_X(cfile, buf, 5);
                   1680:        if (len == 4) {
                   1681:                memcpy(ia->iaid, buf, 4);
                   1682:        } else {
                   1683:                parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
                   1684:                skip_to_semi(cfile);
                   1685:                dfree(ia, MDL);
                   1686:                return NULL;
                   1687:        }
                   1688: 
                   1689:        token = next_token(NULL, NULL, cfile);
                   1690:        if (token != LBRACE) {
                   1691:                parse_warn(cfile, "Expecting open curly brace.");
                   1692:                skip_to_semi(cfile);
                   1693:                dfree(ia, MDL);
                   1694:                return NULL;
                   1695:        }
                   1696: 
                   1697:        option_state_allocate(&ia->options, MDL);
                   1698:        if (ia->options == NULL) {
                   1699:                parse_warn(cfile, "Unable to allocate option state.");
                   1700:                skip_to_rbrace(cfile, 1);
                   1701:                dfree(ia, MDL);
                   1702:                return NULL;
                   1703:        }
                   1704: 
                   1705:        addr = &ia->addrs;
                   1706:        token = next_token(&val, NULL, cfile);
                   1707:        while (token != RBRACE) {
                   1708:                no_semi = 0;
                   1709: 
                   1710:                switch (token) {
                   1711:                      case STARTS:
                   1712:                        token = next_token(&val, NULL, cfile);
                   1713:                        if (token == NUMBER) {
                   1714:                                ia->starts = atoi(val);
                   1715:                        } else {
                   1716:                                parse_warn(cfile, "Expecting a number.");
                   1717:                                skip_to_semi(cfile);
                   1718:                                no_semi = 1;
                   1719:                        }
                   1720:                        break;
                   1721: 
                   1722:                        /* No RENEW or REBIND */
                   1723: 
                   1724:                      case IAADDR:
                   1725:                        *addr = parse_client6_iaaddr_statement(cfile);
                   1726: 
                   1727:                        if (*addr != NULL)
                   1728:                                addr = &(*addr)->next;
                   1729: 
                   1730:                        no_semi = 1;
                   1731: 
                   1732:                        break;
                   1733: 
                   1734:                      case OPTION:
                   1735:                        if (parse_option_decl(&oc, cfile)) {
                   1736:                                save_option(oc->option->universe,
                   1737:                                            ia->options, oc);
                   1738:                                option_cache_dereference(&oc, MDL);
                   1739:                        }
                   1740:                        no_semi = 1;
                   1741:                        break;
                   1742: 
                   1743:                      default:
                   1744:                        parse_warn(cfile, "Unexpected token.");
                   1745:                        no_semi = 1;
                   1746:                        skip_to_semi(cfile);
                   1747:                        break;
                   1748:                }
                   1749: 
                   1750:                if (!no_semi)
                   1751:                        parse_semi(cfile);
                   1752: 
                   1753:                token = next_token(&val, NULL, cfile);
                   1754: 
                   1755:                if (token == END_OF_FILE) {
                   1756:                        parse_warn(cfile, "Unexpected end of file.");
                   1757:                        break;
                   1758:                }
                   1759:        }
                   1760: 
                   1761:        return ia;
                   1762: }
                   1763: #endif /* DHCPv6 */
                   1764: 
                   1765: /* Parse an ia_pd object from the client lease.
                   1766:  */
                   1767: #ifdef DHCPv6
                   1768: static struct dhc6_ia *
                   1769: parse_client6_ia_pd_statement(struct parse *cfile)
                   1770: {
                   1771:        struct option_cache *oc = NULL;
                   1772:        struct dhc6_ia *ia;
                   1773:        struct dhc6_addr **pref;
                   1774:        const char *val;
                   1775:        int token, no_semi, len;
                   1776:        u_int8_t buf[5];
                   1777: 
                   1778:        ia = dmalloc(sizeof(*ia), MDL);
                   1779:        if (ia == NULL) {
                   1780:                parse_warn(cfile, "Out of memory allocating IA_PD state.");
                   1781:                skip_to_semi(cfile);
                   1782:                return NULL;
                   1783:        }
                   1784:        ia->ia_type = D6O_IA_PD;
                   1785: 
                   1786:        /* Get IAID. */
                   1787:        len = parse_X(cfile, buf, 5);
                   1788:        if (len == 4) {
                   1789:                memcpy(ia->iaid, buf, 4);
                   1790:        } else {
                   1791:                parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
                   1792:                skip_to_semi(cfile);
                   1793:                dfree(ia, MDL);
                   1794:                return NULL;
                   1795:        }
                   1796: 
                   1797:        token = next_token(NULL, NULL, cfile);
                   1798:        if (token != LBRACE) {
                   1799:                parse_warn(cfile, "Expecting open curly brace.");
                   1800:                skip_to_semi(cfile);
                   1801:                dfree(ia, MDL);
                   1802:                return NULL;
                   1803:        }
                   1804: 
                   1805:        option_state_allocate(&ia->options, MDL);
                   1806:        if (ia->options == NULL) {
                   1807:                parse_warn(cfile, "Unable to allocate option state.");
                   1808:                skip_to_rbrace(cfile, 1);
                   1809:                dfree(ia, MDL);
                   1810:                return NULL;
                   1811:        }
                   1812: 
                   1813:        pref = &ia->addrs;
                   1814:        token = next_token(&val, NULL, cfile);
                   1815:        while (token != RBRACE) {
                   1816:                no_semi = 0;
                   1817: 
                   1818:                switch (token) {
                   1819:                      case STARTS:
                   1820:                        token = next_token(&val, NULL, cfile);
                   1821:                        if (token == NUMBER) {
                   1822:                                ia->starts = atoi(val);
                   1823:                        } else {
                   1824:                                parse_warn(cfile, "Expecting a number.");
                   1825:                                skip_to_semi(cfile);
                   1826:                                no_semi = 1;
                   1827:                        }
                   1828:                        break;
                   1829: 
                   1830:                      case RENEW:
                   1831:                        token = next_token(&val, NULL, cfile);
                   1832:                        if (token == NUMBER) {
                   1833:                                ia->renew = atoi(val);
                   1834:                        } else {
                   1835:                                parse_warn(cfile, "Expecting a number.");
                   1836:                                skip_to_semi(cfile);
                   1837:                                no_semi = 1;
                   1838:                        }
                   1839:                        break;
                   1840: 
                   1841:                      case REBIND:
                   1842:                        token = next_token(&val, NULL, cfile);
                   1843:                        if (token == NUMBER) {
                   1844:                                ia->rebind = atoi(val);
                   1845:                        } else {
                   1846:                                parse_warn(cfile, "Expecting a number.");
                   1847:                                skip_to_semi(cfile);
                   1848:                                no_semi = 1;
                   1849:                        }
                   1850:                        break;
                   1851: 
                   1852:                      case IAPREFIX:
                   1853:                        *pref = parse_client6_iaprefix_statement(cfile);
                   1854: 
                   1855:                        if (*pref != NULL)
                   1856:                                pref = &(*pref)->next;
                   1857: 
                   1858:                        no_semi = 1;
                   1859: 
                   1860:                        break;
                   1861: 
                   1862:                      case OPTION:
                   1863:                        if (parse_option_decl(&oc, cfile)) {
                   1864:                                save_option(oc->option->universe,
                   1865:                                            ia->options, oc);
                   1866:                                option_cache_dereference(&oc, MDL);
                   1867:                        }
                   1868:                        no_semi = 1;
                   1869:                        break;
                   1870: 
                   1871:                      default:
                   1872:                        parse_warn(cfile, "Unexpected token.");
                   1873:                        no_semi = 1;
                   1874:                        skip_to_semi(cfile);
                   1875:                        break;
                   1876:                }
                   1877: 
                   1878:                if (!no_semi)
                   1879:                        parse_semi(cfile);
                   1880: 
                   1881:                token = next_token(&val, NULL, cfile);
                   1882: 
                   1883:                if (token == END_OF_FILE) {
                   1884:                        parse_warn(cfile, "Unexpected end of file.");
                   1885:                        break;
                   1886:                }
                   1887:        }
                   1888: 
                   1889:        return ia;
                   1890: }
                   1891: #endif /* DHCPv6 */
                   1892: 
                   1893: /* Parse an iaaddr {} structure. */
                   1894: #ifdef DHCPv6
                   1895: static struct dhc6_addr *
                   1896: parse_client6_iaaddr_statement(struct parse *cfile)
                   1897: {
                   1898:        struct option_cache *oc = NULL;
                   1899:        struct dhc6_addr *addr;
                   1900:        const char *val;
                   1901:        int token, no_semi;
                   1902: 
                   1903:        addr = dmalloc(sizeof(*addr), MDL);
                   1904:        if (addr == NULL) {
                   1905:                parse_warn(cfile, "Unable to allocate IAADDR state.");
                   1906:                skip_to_semi(cfile);
                   1907:                return NULL;
                   1908:        }
                   1909: 
                   1910:        /* Get IP address. */
                   1911:        if (!parse_ip6_addr(cfile, &addr->address)) {
                   1912:                skip_to_semi(cfile);
                   1913:                dfree(addr, MDL);
                   1914:                return NULL;
                   1915:        }
                   1916: 
                   1917:        token = next_token(NULL, NULL, cfile);
                   1918:        if (token != LBRACE) {
                   1919:                parse_warn(cfile, "Expecting open curly bracket.");
                   1920:                skip_to_semi(cfile);
                   1921:                dfree(addr, MDL);
                   1922:                return NULL;
                   1923:        }
                   1924: 
                   1925:        option_state_allocate(&addr->options, MDL);
                   1926:        if (addr->options == NULL) {
                   1927:                parse_warn(cfile, "Unable to allocate option state.");
                   1928:                skip_to_semi(cfile);
                   1929:                dfree(addr, MDL);
                   1930:                return NULL;
                   1931:        }
                   1932: 
                   1933:        token = next_token(&val, NULL, cfile);
                   1934:        while (token != RBRACE) {
                   1935:                no_semi = 0;
                   1936: 
                   1937:                switch (token) {
                   1938:                      case STARTS:
                   1939:                        token = next_token(&val, NULL, cfile);
                   1940:                        if (token == NUMBER) {
                   1941:                                addr->starts = atoi(val);
                   1942:                        } else {
                   1943:                                parse_warn(cfile, "Expecting a number.");
                   1944:                                skip_to_semi(cfile);
                   1945:                                no_semi = 1;
                   1946:                        }
                   1947:                        break;
                   1948: 
                   1949:                      case PREFERRED_LIFE:
                   1950:                        token = next_token(&val, NULL, cfile);
                   1951:                        if (token == NUMBER) {
                   1952:                                addr->preferred_life = atoi(val);
                   1953:                        } else {
                   1954:                                parse_warn(cfile, "Expecting a number.");
                   1955:                                skip_to_semi(cfile);
                   1956:                                no_semi = 1;
                   1957:                        }
                   1958:                        break;
                   1959: 
                   1960:                      case MAX_LIFE:
                   1961:                        token = next_token(&val, NULL, cfile);
                   1962:                        if (token == NUMBER) {
                   1963:                                addr->max_life = atoi(val);
                   1964:                        } else {
                   1965:                                parse_warn(cfile, "Expecting a number.");
                   1966:                                skip_to_semi(cfile);
                   1967:                                no_semi = 1;
                   1968:                        }
                   1969:                        break;
                   1970: 
                   1971:                      case OPTION:
                   1972:                        if (parse_option_decl(&oc, cfile)) {
                   1973:                                save_option(oc->option->universe,
                   1974:                                            addr->options, oc);
                   1975:                                option_cache_dereference(&oc, MDL);
                   1976:                        }
                   1977:                        no_semi = 1;
                   1978:                        break;
                   1979: 
                   1980:                      default:
                   1981:                        parse_warn(cfile, "Unexpected token.");
                   1982:                        skip_to_rbrace(cfile, 1);
                   1983:                        no_semi = 1;
                   1984:                        break;
                   1985:                }
                   1986: 
                   1987:                if (!no_semi)
                   1988:                        parse_semi(cfile);
                   1989: 
                   1990:                token = next_token(&val, NULL, cfile);
                   1991:                if (token == END_OF_FILE) {
                   1992:                        parse_warn(cfile, "Unexpected end of file.");
                   1993:                        break;
                   1994:                }
                   1995:        }
                   1996: 
                   1997:        return addr;
                   1998: }
                   1999: #endif /* DHCPv6 */
                   2000: 
                   2001: /* Parse an iaprefix {} structure. */
                   2002: #ifdef DHCPv6
                   2003: static struct dhc6_addr *
                   2004: parse_client6_iaprefix_statement(struct parse *cfile)
                   2005: {
                   2006:        struct option_cache *oc = NULL;
                   2007:        struct dhc6_addr *pref;
                   2008:        const char *val;
                   2009:        int token, no_semi;
                   2010: 
                   2011:        pref = dmalloc(sizeof(*pref), MDL);
                   2012:        if (pref == NULL) {
                   2013:                parse_warn(cfile, "Unable to allocate IAPREFIX state.");
                   2014:                skip_to_semi(cfile);
                   2015:                return NULL;
                   2016:        }
                   2017: 
                   2018:        /* Get IP prefix. */
                   2019:        if (!parse_ip6_prefix(cfile, &pref->address, &pref->plen)) {
                   2020:                skip_to_semi(cfile);
                   2021:                dfree(pref, MDL);
                   2022:                return NULL;
                   2023:        }
                   2024: 
                   2025:        token = next_token(NULL, NULL, cfile);
                   2026:        if (token != LBRACE) {
                   2027:                parse_warn(cfile, "Expecting open curly bracket.");
                   2028:                skip_to_semi(cfile);
                   2029:                dfree(pref, MDL);
                   2030:                return NULL;
                   2031:        }
                   2032: 
                   2033:        option_state_allocate(&pref->options, MDL);
                   2034:        if (pref->options == NULL) {
                   2035:                parse_warn(cfile, "Unable to allocate option state.");
                   2036:                skip_to_semi(cfile);
                   2037:                dfree(pref, MDL);
                   2038:                return NULL;
                   2039:        }
                   2040: 
                   2041:        token = next_token(&val, NULL, cfile);
                   2042:        while (token != RBRACE) {
                   2043:                no_semi = 0;
                   2044: 
                   2045:                switch (token) {
                   2046:                      case STARTS:
                   2047:                        token = next_token(&val, NULL, cfile);
                   2048:                        if (token == NUMBER) {
                   2049:                                pref->starts = atoi(val);
                   2050:                        } else {
                   2051:                                parse_warn(cfile, "Expecting a number.");
                   2052:                                skip_to_semi(cfile);
                   2053:                                no_semi = 1;
                   2054:                        }
                   2055:                        break;
                   2056: 
                   2057:                      case PREFERRED_LIFE:
                   2058:                        token = next_token(&val, NULL, cfile);
                   2059:                        if (token == NUMBER) {
                   2060:                                pref->preferred_life = atoi(val);
                   2061:                        } else {
                   2062:                                parse_warn(cfile, "Expecting a number.");
                   2063:                                skip_to_semi(cfile);
                   2064:                                no_semi = 1;
                   2065:                        }
                   2066:                        break;
                   2067: 
                   2068:                      case MAX_LIFE:
                   2069:                        token = next_token(&val, NULL, cfile);
                   2070:                        if (token == NUMBER) {
                   2071:                                pref->max_life = atoi(val);
                   2072:                        } else {
                   2073:                                parse_warn(cfile, "Expecting a number.");
                   2074:                                skip_to_semi(cfile);
                   2075:                                no_semi = 1;
                   2076:                        }
                   2077:                        break;
                   2078: 
                   2079:                      case OPTION:
                   2080:                        if (parse_option_decl(&oc, cfile)) {
                   2081:                                save_option(oc->option->universe,
                   2082:                                            pref->options, oc);
                   2083:                                option_cache_dereference(&oc, MDL);
                   2084:                        }
                   2085:                        no_semi = 1;
                   2086:                        break;
                   2087: 
                   2088:                      default:
                   2089:                        parse_warn(cfile, "Unexpected token.");
                   2090:                        skip_to_rbrace(cfile, 1);
                   2091:                        no_semi = 1;
                   2092:                        break;
                   2093:                }
                   2094: 
                   2095:                if (!no_semi)
                   2096:                        parse_semi(cfile);
                   2097: 
                   2098:                token = next_token(&val, NULL, cfile);
                   2099:                if (token == END_OF_FILE) {
                   2100:                        parse_warn(cfile, "Unexpected end of file.");
                   2101:                        break;
                   2102:                }
                   2103:        }
                   2104: 
                   2105:        return pref;
                   2106: }
                   2107: #endif /* DHCPv6 */
                   2108: 
                   2109: void parse_string_list (cfile, lp, multiple)
                   2110:        struct parse *cfile;
                   2111:        struct string_list **lp;
                   2112:        int multiple;
                   2113: {
                   2114:        int token;
                   2115:        const char *val;
                   2116:        struct string_list *cur, *tmp;
                   2117: 
                   2118:        /* Find the last medium in the media list. */
                   2119:        if (*lp) {
                   2120:                for (cur = *lp; cur -> next; cur = cur -> next)
                   2121:                        ;
                   2122:        } else {
                   2123:                cur = (struct string_list *)0;
                   2124:        }
                   2125: 
                   2126:        do {
                   2127:                token = next_token (&val, (unsigned *)0, cfile);
                   2128:                if (token != STRING) {
                   2129:                        parse_warn (cfile, "Expecting media options.");
                   2130:                        skip_to_semi (cfile);
                   2131:                        return;
                   2132:                }
                   2133: 
                   2134:                tmp = ((struct string_list *)
                   2135:                       dmalloc (strlen (val) + sizeof (struct string_list),
                   2136:                                MDL));
                   2137:                if (!tmp)
                   2138:                        log_fatal ("no memory for string list entry.");
                   2139: 
                   2140:                strcpy (tmp -> string, val);
                   2141:                tmp -> next = (struct string_list *)0;
                   2142: 
                   2143:                /* Store this medium at the end of the media list. */
                   2144:                if (cur)
                   2145:                        cur -> next = tmp;
                   2146:                else
                   2147:                        *lp = tmp;
                   2148:                cur = tmp;
                   2149: 
                   2150:                token = next_token (&val, (unsigned *)0, cfile);
                   2151:        } while (multiple && token == COMMA);
                   2152: 
                   2153:        if (token != SEMI) {
                   2154:                parse_warn (cfile, "expecting semicolon.");
                   2155:                skip_to_semi (cfile);
                   2156:        }
                   2157: }
                   2158: 
                   2159: void parse_reject_statement (cfile, config)
                   2160:        struct parse *cfile;
                   2161:        struct client_config *config;
                   2162: {
                   2163:        int token;
                   2164:        const char *val;
                   2165:        struct iaddrmatch match;
                   2166:        struct iaddrmatchlist *list;
                   2167:        int i;
                   2168: 
                   2169:        do {
                   2170:                if (!parse_ip_addr_with_subnet (cfile, &match)) {
                   2171:                        /* no warn: parser will have reported what's wrong */
                   2172:                        skip_to_semi (cfile);
                   2173:                        return;
                   2174:                }
                   2175: 
                   2176:                /* check mask is not all zeros (because that would
                   2177:                 * reject EVERY address).  This check could be
                   2178:                 * simplified if we assume that the mask *always*
                   2179:                 * represents a prefix .. but perhaps it might be
                   2180:                 * useful to have a mask which is not a proper prefix
                   2181:                 * (perhaps for ipv6?).  The following is almost as
                   2182:                 * efficient as inspection of match.mask.iabuf[0] when
                   2183:                 * it IS a true prefix, and is more general when it is
                   2184:                 * not.
                   2185:                 */
                   2186: 
                   2187:                for (i=0 ; i < match.mask.len ; i++) {
                   2188:                    if (match.mask.iabuf[i]) {
                   2189:                        break;
                   2190:                    }
                   2191:                }
                   2192: 
                   2193:                if (i == match.mask.len) {
                   2194:                    /* oops we found all zeros */
                   2195:                    parse_warn(cfile, "zero-length prefix is not permitted "
                   2196:                                      "for reject statement");
                   2197:                    skip_to_semi(cfile);
                   2198:                    return;
                   2199:                } 
                   2200: 
                   2201:                list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
                   2202:                if (!list)
                   2203:                        log_fatal ("no memory for reject list!");
                   2204: 
                   2205:                list->match = match;
                   2206:                list->next = config->reject_list;
                   2207:                config->reject_list = list;
                   2208: 
                   2209:                token = next_token (&val, (unsigned *)0, cfile);
                   2210:        } while (token == COMMA);
                   2211: 
                   2212:        if (token != SEMI) {
                   2213:                parse_warn (cfile, "expecting semicolon.");
                   2214:                skip_to_semi (cfile);
                   2215:        }
                   2216: }      
                   2217: 
                   2218: /* allow-deny-keyword :== BOOTP
                   2219:                        | BOOTING
                   2220:                        | DYNAMIC_BOOTP
                   2221:                        | UNKNOWN_CLIENTS */
                   2222: 
                   2223: int parse_allow_deny (oc, cfile, flag)
                   2224:        struct option_cache **oc;
                   2225:        struct parse *cfile;
                   2226:        int flag;
                   2227: {
                   2228:        parse_warn (cfile, "allow/deny/ignore not permitted here.");
                   2229:        skip_to_semi (cfile);
                   2230:        return 0;
                   2231: }

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