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

1.1       misho       1: /* dhclient.c
                      2: 
                      3:    DHCP Client. */
                      4: 
                      5: /*
1.1.1.1 ! misho       6:  * Copyright (c) 2004-2012 by Internet Systems Consortium, Inc. ("ISC")
1.1       misho       7:  * Copyright (c) 1995-2003 by Internet Software Consortium
                      8:  *
                      9:  * Permission to use, copy, modify, and distribute this software for any
                     10:  * purpose with or without fee is hereby granted, provided that the above
                     11:  * copyright notice and this permission notice appear in all copies.
                     12:  *
                     13:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     14:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     15:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     16:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     17:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     18:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     19:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     20:  *
                     21:  *   Internet Systems Consortium, Inc.
                     22:  *   950 Charter Street
                     23:  *   Redwood City, CA 94063
                     24:  *   <info@isc.org>
                     25:  *   https://www.isc.org/
                     26:  *
                     27:  * This code is based on the original client state machine that was
                     28:  * written by Elliot Poger.  The code has been extensively hacked on
                     29:  * by Ted Lemon since then, so any mistakes you find are probably his
                     30:  * fault and not Elliot's.
                     31:  */
                     32: 
                     33: #include "dhcpd.h"
                     34: #include <syslog.h>
                     35: #include <signal.h>
                     36: #include <errno.h>
                     37: #include <sys/time.h>
                     38: #include <sys/wait.h>
                     39: #include <limits.h>
                     40: 
                     41: TIME default_lease_time = 43200; /* 12 hours... */
                     42: TIME max_lease_time = 86400; /* 24 hours... */
                     43: 
                     44: const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
                     45: const char *path_dhclient_db = NULL;
                     46: const char *path_dhclient_pid = NULL;
                     47: static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
                     48: char *path_dhclient_script = path_dhclient_script_array;
                     49: 
                     50: /* False (default) => we write and use a pid file */
                     51: isc_boolean_t no_pid_file = ISC_FALSE;
                     52: 
                     53: int dhcp_max_agent_option_packet_length = 0;
                     54: 
                     55: int interfaces_requested = 0;
                     56: 
                     57: struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
                     58: struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
                     59: struct in_addr inaddr_any;
                     60: struct sockaddr_in sockaddr_broadcast;
                     61: struct in_addr giaddr;
                     62: struct data_string default_duid;
                     63: 
                     64: /* ASSERT_STATE() does nothing now; it used to be
                     65:    assert (state_is == state_shouldbe). */
                     66: #define ASSERT_STATE(state_is, state_shouldbe) {}
                     67: 
                     68: static const char copyright[] = 
1.1.1.1 ! misho      69: "Copyright 2004-2012 Internet Systems Consortium.";
1.1       misho      70: static const char arr [] = "All rights reserved.";
                     71: static const char message [] = "Internet Systems Consortium DHCP Client";
                     72: static const char url [] = 
                     73: "For info, please visit https://www.isc.org/software/dhcp/";
                     74: 
                     75: u_int16_t local_port = 0;
                     76: u_int16_t remote_port = 0;
                     77: int no_daemon = 0;
                     78: struct string_list *client_env = NULL;
                     79: int client_env_count = 0;
                     80: int onetry = 0;
                     81: int quiet = 1;
                     82: int nowait = 0;
                     83: int stateless = 0;
                     84: int wanted_ia_na = -1;         /* the absolute value is the real one. */
                     85: int wanted_ia_ta = 0;
                     86: int wanted_ia_pd = 0;
                     87: char *mockup_relay = NULL;
                     88: 
                     89: void run_stateless(int exit_mode);
                     90: 
                     91: static void usage(void);
                     92: 
                     93: static isc_result_t write_duid(struct data_string *duid);
                     94: static void add_reject(struct packet *packet);
                     95: 
                     96: static int check_domain_name(const char *ptr, size_t len, int dots);
                     97: static int check_domain_name_list(const char *ptr, size_t len, int dots);
                     98: static int check_option_values(struct universe *universe, unsigned int opt,
                     99:                               const char *ptr, size_t len);
                    100: 
                    101: int
                    102: main(int argc, char **argv) {
                    103:        int fd;
                    104:        int i;
                    105:        struct interface_info *ip;
                    106:        struct client_state *client;
                    107:        unsigned seed;
                    108:        char *server = NULL;
                    109:        isc_result_t status;
                    110:        int exit_mode = 0;
                    111:        int release_mode = 0;
                    112:        struct timeval tv;
                    113:        omapi_object_t *listener;
                    114:        isc_result_t result;
                    115:        int persist = 0;
                    116:        int no_dhclient_conf = 0;
                    117:        int no_dhclient_db = 0;
                    118:        int no_dhclient_pid = 0;
                    119:        int no_dhclient_script = 0;
                    120: #ifdef DHCPv6
                    121:        int local_family_set = 0;
                    122: #endif /* DHCPv6 */
                    123:        char *s;
                    124: 
                    125:        /* Initialize client globals. */
                    126:        memset(&default_duid, 0, sizeof(default_duid));
                    127: 
                    128:        /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
                    129:           2 (stderr) are open. To do this, we assume that when we
                    130:           open a file the lowest available file descriptor is used. */
                    131:        fd = open("/dev/null", O_RDWR);
                    132:        if (fd == 0)
                    133:                fd = open("/dev/null", O_RDWR);
                    134:        if (fd == 1)
                    135:                fd = open("/dev/null", O_RDWR);
                    136:        if (fd == 2)
                    137:                log_perror = 0; /* No sense logging to /dev/null. */
                    138:        else if (fd != -1)
                    139:                close(fd);
                    140: 
                    141:        openlog("dhclient", LOG_NDELAY, LOG_DAEMON);
                    142: 
                    143: #if !(defined(DEBUG) || defined(__CYGWIN32__))
                    144:        setlogmask(LOG_UPTO(LOG_INFO));
                    145: #endif
                    146: 
                    147:        /*
                    148:         * Set up the signal handlers, currently we only
                    149:         * have one to ignore sigpipe.
                    150:         */
                    151:        if (dhcp_handle_signal(SIGPIPE, SIG_IGN) != ISC_R_SUCCESS) {
                    152:                log_fatal("Can't set up signal handler");
                    153:        }
                    154: 
                    155:        /* Set up the OMAPI. */
                    156:        status = omapi_init();
                    157:        if (status != ISC_R_SUCCESS)
                    158:                log_fatal("Can't initialize OMAPI: %s",
                    159:                          isc_result_totext(status));
                    160: 
                    161:        /* Set up the OMAPI wrappers for various server database internal
                    162:           objects. */
                    163:        dhcp_common_objects_setup();
                    164: 
                    165:        dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
                    166:        dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
                    167:        dhcp_interface_startup_hook = dhclient_interface_startup_hook;
                    168: 
                    169:        for (i = 1; i < argc; i++) {
                    170:                if (!strcmp(argv[i], "-r")) {
                    171:                        release_mode = 1;
                    172:                        no_daemon = 1;
                    173: #ifdef DHCPv6
                    174:                } else if (!strcmp(argv[i], "-4")) {
                    175:                        if (local_family_set && local_family != AF_INET)
                    176:                                log_fatal("Client can only do v4 or v6, not "
                    177:                                          "both.");
                    178:                        local_family_set = 1;
                    179:                        local_family = AF_INET;
                    180:                } else if (!strcmp(argv[i], "-6")) {
                    181:                        if (local_family_set && local_family != AF_INET6)
                    182:                                log_fatal("Client can only do v4 or v6, not "
                    183:                                          "both.");
                    184:                        local_family_set = 1;
                    185:                        local_family = AF_INET6;
                    186: #endif /* DHCPv6 */
                    187:                } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */
                    188:                        release_mode = 0;
                    189:                        no_daemon = 0;
                    190:                        exit_mode = 1;
                    191:                } else if (!strcmp(argv[i], "-p")) {
                    192:                        if (++i == argc)
                    193:                                usage();
                    194:                        local_port = validate_port(argv[i]);
                    195:                        log_debug("binding to user-specified port %d",
                    196:                                  ntohs(local_port));
                    197:                } else if (!strcmp(argv[i], "-d")) {
                    198:                        no_daemon = 1;
                    199:                        quiet = 0;
                    200:                } else if (!strcmp(argv[i], "-pf")) {
                    201:                        if (++i == argc)
                    202:                                usage();
                    203:                        path_dhclient_pid = argv[i];
                    204:                        no_dhclient_pid = 1;
                    205:                } else if (!strcmp(argv[i], "--no-pid")) {
                    206:                        no_pid_file = ISC_TRUE;
                    207:                } else if (!strcmp(argv[i], "-cf")) {
                    208:                        if (++i == argc)
                    209:                                usage();
                    210:                        path_dhclient_conf = argv[i];
                    211:                        no_dhclient_conf = 1;
                    212:                } else if (!strcmp(argv[i], "-lf")) {
                    213:                        if (++i == argc)
                    214:                                usage();
                    215:                        path_dhclient_db = argv[i];
                    216:                        no_dhclient_db = 1;
                    217:                } else if (!strcmp(argv[i], "-sf")) {
                    218:                        if (++i == argc)
                    219:                                usage();
                    220:                        path_dhclient_script = argv[i];
                    221:                        no_dhclient_script = 1;
                    222:                } else if (!strcmp(argv[i], "-1")) {
                    223:                        onetry = 1;
                    224:                } else if (!strcmp(argv[i], "-q")) {
                    225:                        quiet = 1;
                    226:                } else if (!strcmp(argv[i], "-s")) {
                    227:                        if (++i == argc)
                    228:                                usage();
                    229:                        server = argv[i];
                    230:                } else if (!strcmp(argv[i], "-g")) {
                    231:                        if (++i == argc)
                    232:                                usage();
                    233:                        mockup_relay = argv[i];
                    234:                } else if (!strcmp(argv[i], "-nw")) {
                    235:                        nowait = 1;
                    236:                } else if (!strcmp(argv[i], "-n")) {
                    237:                        /* do not start up any interfaces */
                    238:                        interfaces_requested = -1;
                    239:                } else if (!strcmp(argv[i], "-w")) {
                    240:                        /* do not exit if there are no broadcast interfaces. */
                    241:                        persist = 1;
                    242:                } else if (!strcmp(argv[i], "-e")) {
                    243:                        struct string_list *tmp;
                    244:                        if (++i == argc)
                    245:                                usage();
                    246:                        tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
                    247:                        if (!tmp)
                    248:                                log_fatal("No memory for %s", argv[i]);
                    249:                        strcpy(tmp->string, argv[i]);
                    250:                        tmp->next = client_env;
                    251:                        client_env = tmp;
                    252:                        client_env_count++;
                    253: #ifdef DHCPv6
                    254:                } else if (!strcmp(argv[i], "-S")) {
                    255:                        if (local_family_set && (local_family == AF_INET)) {
                    256:                                usage();
                    257:                        }
                    258:                        local_family_set = 1;
                    259:                        local_family = AF_INET6;
                    260:                        wanted_ia_na = 0;
                    261:                        stateless = 1;
                    262:                } else if (!strcmp(argv[i], "-N")) {
                    263:                        if (local_family_set && (local_family == AF_INET)) {
                    264:                                usage();
                    265:                        }
                    266:                        local_family_set = 1;
                    267:                        local_family = AF_INET6;
                    268:                        if (wanted_ia_na < 0) {
                    269:                                wanted_ia_na = 0;
                    270:                        }
                    271:                        wanted_ia_na++;
                    272:                } else if (!strcmp(argv[i], "-T")) {
                    273:                        if (local_family_set && (local_family == AF_INET)) {
                    274:                                usage();
                    275:                        }
                    276:                        local_family_set = 1;
                    277:                        local_family = AF_INET6;
                    278:                        if (wanted_ia_na < 0) {
                    279:                                wanted_ia_na = 0;
                    280:                        }
                    281:                        wanted_ia_ta++;
                    282:                } else if (!strcmp(argv[i], "-P")) {
                    283:                        if (local_family_set && (local_family == AF_INET)) {
                    284:                                usage();
                    285:                        }
                    286:                        local_family_set = 1;
                    287:                        local_family = AF_INET6;
                    288:                        if (wanted_ia_na < 0) {
                    289:                                wanted_ia_na = 0;
                    290:                        }
                    291:                        wanted_ia_pd++;
                    292: #endif /* DHCPv6 */
                    293:                } else if (!strcmp(argv[i], "-v")) {
                    294:                        quiet = 0;
                    295:                } else if (!strcmp(argv[i], "--version")) {
                    296:                        log_info("isc-dhclient-%s", PACKAGE_VERSION);
                    297:                        exit(0);
                    298:                } else if (argv[i][0] == '-') {
                    299:                    usage();
                    300:                } else if (interfaces_requested < 0) {
                    301:                    usage();
                    302:                } else {
                    303:                    struct interface_info *tmp = NULL;
                    304: 
                    305:                    status = interface_allocate(&tmp, MDL);
                    306:                    if (status != ISC_R_SUCCESS)
                    307:                        log_fatal("Can't record interface %s:%s",
                    308:                                  argv[i], isc_result_totext(status));
                    309:                    if (strlen(argv[i]) >= sizeof(tmp->name))
                    310:                            log_fatal("%s: interface name too long (is %ld)",
                    311:                                      argv[i], (long)strlen(argv[i]));
                    312:                    strcpy(tmp->name, argv[i]);
                    313:                    if (interfaces) {
                    314:                            interface_reference(&tmp->next,
                    315:                                                interfaces, MDL);
                    316:                            interface_dereference(&interfaces, MDL);
                    317:                    }
                    318:                    interface_reference(&interfaces, tmp, MDL);
                    319:                    tmp->flags = INTERFACE_REQUESTED;
                    320:                    interfaces_requested++;
                    321:                }
                    322:        }
                    323: 
                    324:        if (wanted_ia_na < 0) {
                    325:                wanted_ia_na = 1;
                    326:        }
                    327: 
                    328:        /* Support only one (requested) interface for Prefix Delegation. */
                    329:        if (wanted_ia_pd && (interfaces_requested != 1)) {
                    330:                usage();
                    331:        }
                    332: 
                    333:        if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
                    334:                path_dhclient_conf = s;
                    335:        }
                    336:        if (!no_dhclient_db && (s = getenv("PATH_DHCLIENT_DB"))) {
                    337:                path_dhclient_db = s;
                    338:        }
                    339:        if (!no_dhclient_pid && (s = getenv("PATH_DHCLIENT_PID"))) {
                    340:                path_dhclient_pid = s;
                    341:        }
                    342:        if (!no_dhclient_script && (s = getenv("PATH_DHCLIENT_SCRIPT"))) {
                    343:                path_dhclient_script = s;
                    344:        }
                    345: 
                    346:        /* Set up the initial dhcp option universe. */
                    347:        initialize_common_option_spaces();
                    348: 
                    349:        /* Assign v4 or v6 specific running parameters. */
                    350:        if (local_family == AF_INET)
                    351:                dhcpv4_client_assignments();
                    352: #ifdef DHCPv6
                    353:        else if (local_family == AF_INET6)
                    354:                dhcpv6_client_assignments();
                    355: #endif /* DHCPv6 */
                    356:        else
                    357:                log_fatal("Impossible condition at %s:%d.", MDL);
                    358: 
                    359:        /*
                    360:         * convert relative path names to absolute, for files that need
                    361:         * to be reopened after chdir() has been called
                    362:         */
                    363:        if (path_dhclient_db[0] != '/') {
                    364:                char *path = dmalloc(PATH_MAX, MDL);
                    365:                if (path == NULL)
                    366:                        log_fatal("No memory for filename\n");
                    367:                path_dhclient_db = realpath(path_dhclient_db, path);
                    368:                if (path_dhclient_db == NULL)
                    369:                        log_fatal("%s: %s", path, strerror(errno));
                    370:        }
                    371: 
                    372:        if (path_dhclient_script[0] != '/') {
                    373:                char *path = dmalloc(PATH_MAX, MDL);
                    374:                if (path == NULL)
                    375:                        log_fatal("No memory for filename\n");
                    376:                path_dhclient_script = realpath(path_dhclient_script, path);
                    377:                if (path_dhclient_script == NULL)
                    378:                        log_fatal("%s: %s", path, strerror(errno));
                    379:        }
                    380: 
                    381:        /*
                    382:         * See if we should  kill off any currently running client
                    383:         * we don't try to kill it off if the user told us not
                    384:         * to write a pid file - we assume they are controlling
                    385:         * the process in some other fashion.
                    386:         */
                    387:        if ((release_mode || exit_mode) && (no_pid_file == ISC_FALSE)) {
                    388:                FILE *pidfd;
                    389:                pid_t oldpid;
                    390:                long temp;
                    391:                int e;
                    392: 
                    393:                oldpid = 0;
                    394:                if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) {
                    395:                        e = fscanf(pidfd, "%ld\n", &temp);
                    396:                        oldpid = (pid_t)temp;
                    397: 
                    398:                        if (e != 0 && e != EOF) {
                    399:                                if (oldpid)
                    400:                                        kill(oldpid, SIGTERM);
                    401:                        }
                    402:                        fclose(pidfd);
                    403:                }
                    404:        }
                    405: 
                    406:        if (!quiet) {
                    407:                log_info("%s %s", message, PACKAGE_VERSION);
                    408:                log_info(copyright);
                    409:                log_info(arr);
                    410:                log_info(url);
                    411:                log_info("%s", "");
                    412:        } else {
                    413:                log_perror = 0;
                    414:                quiet_interface_discovery = 1;
                    415:        }
                    416: 
                    417:        /* If we're given a relay agent address to insert, for testing
                    418:           purposes, figure out what it is. */
                    419:        if (mockup_relay) {
                    420:                if (!inet_aton(mockup_relay, &giaddr)) {
                    421:                        struct hostent *he;
                    422:                        he = gethostbyname(mockup_relay);
                    423:                        if (he) {
                    424:                                memcpy(&giaddr, he->h_addr_list[0],
                    425:                                       sizeof giaddr);
                    426:                        } else {
                    427:                                log_fatal("%s: no such host", mockup_relay);
                    428:                        }
                    429:                }
                    430:        }
                    431: 
                    432:        /* Get the current time... */
                    433:        gettimeofday(&cur_tv, NULL);
                    434: 
                    435:        sockaddr_broadcast.sin_family = AF_INET;
                    436:        sockaddr_broadcast.sin_port = remote_port;
                    437:        if (server) {
                    438:                if (!inet_aton(server, &sockaddr_broadcast.sin_addr)) {
                    439:                        struct hostent *he;
                    440:                        he = gethostbyname(server);
                    441:                        if (he) {
                    442:                                memcpy(&sockaddr_broadcast.sin_addr,
                    443:                                       he->h_addr_list[0],
                    444:                                       sizeof sockaddr_broadcast.sin_addr);
                    445:                        } else
                    446:                                sockaddr_broadcast.sin_addr.s_addr =
                    447:                                        INADDR_BROADCAST;
                    448:                }
                    449:        } else {
                    450:                sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
                    451:        }
                    452: 
                    453:        inaddr_any.s_addr = INADDR_ANY;
                    454: 
                    455:        /* Stateless special case. */
                    456:        if (stateless) {
                    457:                if (release_mode || (wanted_ia_na > 0) ||
                    458:                    wanted_ia_ta || wanted_ia_pd ||
                    459:                    (interfaces_requested != 1)) {
                    460:                        usage();
                    461:                }
                    462:                run_stateless(exit_mode);
                    463:                return 0;
                    464:        }
                    465: 
                    466:        /* Discover all the network interfaces. */
                    467:        discover_interfaces(DISCOVER_UNCONFIGURED);
                    468: 
                    469:        /* Parse the dhclient.conf file. */
                    470:        read_client_conf();
                    471: 
                    472:        /* Parse the lease database. */
                    473:        read_client_leases();
                    474: 
                    475:        /* Rewrite the lease database... */
                    476:        rewrite_client_leases();
                    477: 
                    478:        /* XXX */
                    479: /*     config_counter(&snd_counter, &rcv_counter); */
                    480: 
                    481:        /*
                    482:         * If no broadcast interfaces were discovered, call the script
                    483:         * and tell it so.
                    484:         */
                    485:        if (!interfaces) {
                    486:                /*
                    487:                 * Call dhclient-script with the NBI flag,
                    488:                 * in case somebody cares.
                    489:                 */
                    490:                script_init(NULL, "NBI", NULL);
                    491:                script_go(NULL);
                    492: 
                    493:                /*
                    494:                 * If we haven't been asked to persist, waiting for new
                    495:                 * interfaces, then just exit.
                    496:                 */
                    497:                if (!persist) {
                    498:                        /* Nothing more to do. */
                    499:                        log_info("No broadcast interfaces found - exiting.");
                    500:                        exit(0);
                    501:                }
                    502:        } else if (!release_mode && !exit_mode) {
                    503:                /* Call the script with the list of interfaces. */
                    504:                for (ip = interfaces; ip; ip = ip->next) {
                    505:                        /*
                    506:                         * If interfaces were specified, don't configure
                    507:                         * interfaces that weren't specified!
                    508:                         */
                    509:                        if ((interfaces_requested > 0) &&
                    510:                            ((ip->flags & (INTERFACE_REQUESTED |
                    511:                                           INTERFACE_AUTOMATIC)) !=
                    512:                             INTERFACE_REQUESTED))
                    513:                                continue;
                    514: 
                    515:                        if (local_family == AF_INET6) {
                    516:                                script_init(ip->client, "PREINIT6", NULL);
                    517:                        } else {
                    518:                                script_init(ip->client, "PREINIT", NULL);
                    519:                                if (ip->client->alias != NULL)
                    520:                                        script_write_params(ip->client,
                    521:                                                            "alias_",
                    522:                                                            ip->client->alias);
                    523:                        }
                    524:                        script_go(ip->client);
                    525:                }
                    526:        }
                    527: 
                    528:        /* At this point, all the interfaces that the script thinks
                    529:           are relevant should be running, so now we once again call
                    530:           discover_interfaces(), and this time ask it to actually set
                    531:           up the interfaces. */
                    532:        discover_interfaces(interfaces_requested != 0
                    533:                            ? DISCOVER_REQUESTED
                    534:                            : DISCOVER_RUNNING);
                    535: 
                    536:        /* Make up a seed for the random number generator from current
                    537:           time plus the sum of the last four bytes of each
                    538:           interface's hardware address interpreted as an integer.
                    539:           Not much entropy, but we're booting, so we're not likely to
                    540:           find anything better. */
                    541:        seed = 0;
                    542:        for (ip = interfaces; ip; ip = ip->next) {
                    543:                int junk;
                    544:                memcpy(&junk,
                    545:                       &ip->hw_address.hbuf[ip->hw_address.hlen -
                    546:                                            sizeof seed], sizeof seed);
                    547:                seed += junk;
                    548:        }
                    549:        srandom(seed + cur_time + (unsigned)getpid());
                    550: 
                    551:        /* Start a configuration state machine for each interface. */
                    552: #ifdef DHCPv6
                    553:        if (local_family == AF_INET6) {
                    554:                /* Establish a default DUID.  This may be moved to the
                    555:                 * DHCPv4 area later.
                    556:                 */
                    557:                if (default_duid.len == 0) {
                    558:                        if (default_duid.buffer != NULL)
                    559:                                data_string_forget(&default_duid, MDL);
                    560: 
                    561:                        form_duid(&default_duid, MDL);
                    562:                        write_duid(&default_duid);
                    563:                }
                    564: 
                    565:                for (ip = interfaces ; ip != NULL ; ip = ip->next) {
                    566:                        for (client = ip->client ; client != NULL ;
                    567:                             client = client->next) {
                    568:                                if (release_mode) {
                    569:                                        start_release6(client);
                    570:                                        continue;
                    571:                                } else if (exit_mode) {
                    572:                                        unconfigure6(client, "STOP6");
                    573:                                        continue;
                    574:                                }
                    575: 
                    576:                                /* If we have a previous binding, Confirm
                    577:                                 * that we can (or can't) still use it.
                    578:                                 */
                    579:                                if ((client->active_lease != NULL) &&
                    580:                                    !client->active_lease->released)
                    581:                                        start_confirm6(client);
                    582:                                else
                    583:                                        start_init6(client);
                    584:                        }
                    585:                }
                    586:        } else
                    587: #endif /* DHCPv6 */
                    588:        {
                    589:                for (ip = interfaces ; ip ; ip = ip->next) {
                    590:                        ip->flags |= INTERFACE_RUNNING;
                    591:                        for (client = ip->client ; client ;
                    592:                             client = client->next) {
                    593:                                if (exit_mode)
                    594:                                        state_stop(client);
                    595:                                else if (release_mode)
                    596:                                        do_release(client);
                    597:                                else {
                    598:                                        client->state = S_INIT;
                    599: 
                    600:                                        if (top_level_config.initial_delay>0)
                    601:                                        {
                    602:                                                tv.tv_sec = 0;
                    603:                                                if (top_level_config.
                    604:                                                    initial_delay>1)
                    605:                                                        tv.tv_sec = cur_time
                    606:                                                        + random()
                    607:                                                        % (top_level_config.
                    608:                                                           initial_delay-1);
                    609:                                                tv.tv_usec = random()
                    610:                                                        % 1000000;
                    611:                                                /*
                    612:                                                 * this gives better
                    613:                                                 * distribution than just
                    614:                                                 *whole seconds
                    615:                                                 */
                    616:                                                add_timeout(&tv, state_reboot,
                    617:                                                            client, 0, 0);
                    618:                                        } else {
                    619:                                                state_reboot(client);
                    620:                                        }
                    621:                                }
                    622:                        }
                    623:                }
                    624:        }
                    625: 
                    626:        if (exit_mode)
                    627:                return 0;
                    628:        if (release_mode) {
                    629: #ifndef DHCPv6
                    630:                return 0;
                    631: #else
                    632:                if (local_family == AF_INET6) {
                    633:                        if (onetry)
                    634:                                return 0;
                    635:                } else
                    636:                        return 0;
                    637: #endif /* DHCPv6 */
                    638:        }
                    639: 
                    640:        /* Start up a listener for the object management API protocol. */
                    641:        if (top_level_config.omapi_port != -1) {
                    642:                listener = NULL;
                    643:                result = omapi_generic_new(&listener, MDL);
                    644:                if (result != ISC_R_SUCCESS)
                    645:                        log_fatal("Can't allocate new generic object: %s\n",
                    646:                                  isc_result_totext(result));
                    647:                result = omapi_protocol_listen(listener,
                    648:                                               (unsigned)
                    649:                                               top_level_config.omapi_port,
                    650:                                               1);
                    651:                if (result != ISC_R_SUCCESS)
                    652:                        log_fatal("Can't start OMAPI protocol: %s",
                    653:                                  isc_result_totext (result));
                    654:        }
                    655: 
                    656:        /* Set up the bootp packet handler... */
                    657:        bootp_packet_handler = do_packet;
                    658: #ifdef DHCPv6
                    659:        dhcpv6_packet_handler = do_packet6;
                    660: #endif /* DHCPv6 */
                    661: 
                    662: #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
                    663:                defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
                    664:        dmalloc_cutoff_generation = dmalloc_generation;
                    665:        dmalloc_longterm = dmalloc_outstanding;
                    666:        dmalloc_outstanding = 0;
                    667: #endif
                    668: 
                    669:        /* If we're not supposed to wait before getting the address,
                    670:           don't. */
                    671:        if (nowait)
                    672:                go_daemon();
                    673: 
                    674:        /* If we're not going to daemonize, write the pid file
                    675:           now. */
                    676:        if (no_daemon || nowait)
                    677:                write_client_pid_file();
                    678: 
                    679:        /* Start dispatching packets and timeouts... */
                    680:        dispatch();
                    681: 
                    682:        /*NOTREACHED*/
                    683:        return 0;
                    684: }
                    685: 
                    686: static void usage()
                    687: {
                    688:        log_info("%s %s", message, PACKAGE_VERSION);
                    689:        log_info(copyright);
                    690:        log_info(arr);
                    691:        log_info(url);
                    692: 
                    693: 
                    694:        log_fatal("Usage: dhclient "
                    695: #ifdef DHCPv6
                    696:                  "[-4|-6] [-SNTP1dvrx] [-nw] [-p <port>]\n"
                    697: #else /* DHCPv6 */
                    698:                  "[-1dvrx] [-nw] [-p <port>]\n"
                    699: #endif /* DHCPv6 */
                    700:                  "                [-s server-addr] [-cf config-file] "
                    701:                  "[-lf lease-file]\n"
                    702:                  "                [-pf pid-file] [--no-pid] [-e VAR=val]\n"
                    703:                  "                [-sf script-file] [interface]");
                    704: }
                    705: 
                    706: void run_stateless(int exit_mode)
                    707: {
                    708: #ifdef DHCPv6
                    709:        struct client_state *client;
                    710:        omapi_object_t *listener;
                    711:        isc_result_t result;
                    712: 
                    713:        /* Discover the network interface. */
                    714:        discover_interfaces(DISCOVER_REQUESTED);
                    715: 
                    716:        if (!interfaces)
                    717:                usage();
                    718: 
                    719:        /* Parse the dhclient.conf file. */
                    720:        read_client_conf();
                    721: 
                    722:        /* Parse the lease database. */
                    723:        read_client_leases();
                    724: 
                    725:        /* Establish a default DUID. */
                    726:        if (default_duid.len == 0) {
                    727:                if (default_duid.buffer != NULL)
                    728:                        data_string_forget(&default_duid, MDL);
                    729: 
                    730:                form_duid(&default_duid, MDL);
                    731:        }
                    732: 
                    733:        /* Start a configuration state machine. */
                    734:        for (client = interfaces->client ;
                    735:             client != NULL ;
                    736:             client = client->next) {
                    737:                if (exit_mode) {
                    738:                        unconfigure6(client, "STOP6");
                    739:                        continue;
                    740:                }
                    741:                start_info_request6(client);
                    742:        }
                    743:        if (exit_mode)
                    744:                return;
                    745: 
                    746:        /* Start up a listener for the object management API protocol. */
                    747:        if (top_level_config.omapi_port != -1) {
                    748:                listener = NULL;
                    749:                result = omapi_generic_new(&listener, MDL);
                    750:                if (result != ISC_R_SUCCESS)
                    751:                        log_fatal("Can't allocate new generic object: %s\n",
                    752:                                  isc_result_totext(result));
                    753:                result = omapi_protocol_listen(listener,
                    754:                                               (unsigned)
                    755:                                               top_level_config.omapi_port,
                    756:                                               1);
                    757:                if (result != ISC_R_SUCCESS)
                    758:                        log_fatal("Can't start OMAPI protocol: %s",
                    759:                                  isc_result_totext(result));
                    760:        }
                    761: 
                    762:        /* Set up the packet handler... */
                    763:        dhcpv6_packet_handler = do_packet6;
                    764: 
                    765: #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
                    766:                defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
                    767:        dmalloc_cutoff_generation = dmalloc_generation;
                    768:        dmalloc_longterm = dmalloc_outstanding;
                    769:        dmalloc_outstanding = 0;
                    770: #endif
                    771: 
                    772:        /* If we're not supposed to wait before getting the address,
                    773:           don't. */
                    774:        if (nowait)
                    775:                go_daemon();
                    776: 
                    777:        /* If we're not going to daemonize, write the pid file
                    778:           now. */
                    779:        if (no_daemon || nowait)
                    780:                write_client_pid_file();
                    781: 
                    782:        /* Start dispatching packets and timeouts... */
                    783:        dispatch();
                    784: 
                    785:        /*NOTREACHED*/
                    786: #endif /* DHCPv6 */
                    787:        return;
                    788: }
                    789: 
                    790: isc_result_t find_class (struct class **c,
                    791:                const char *s, const char *file, int line)
                    792: {
                    793:        return 0;
                    794: }
                    795: 
                    796: int check_collection (packet, lease, collection)
                    797:        struct packet *packet;
                    798:        struct lease *lease;
                    799:        struct collection *collection;
                    800: {
                    801:        return 0;
                    802: }
                    803: 
                    804: void classify (packet, class)
                    805:        struct packet *packet;
                    806:        struct class *class;
                    807: {
                    808: }
                    809: 
                    810: int unbill_class (lease, class)
                    811:        struct lease *lease;
                    812:        struct class *class;
                    813: {
                    814:        return 0;
                    815: }
                    816: 
                    817: int find_subnet (struct subnet **sp,
                    818:                 struct iaddr addr, const char *file, int line)
                    819: {
                    820:        return 0;
                    821: }
                    822: 
                    823: /* Individual States:
                    824:  *
                    825:  * Each routine is called from the dhclient_state_machine() in one of
                    826:  * these conditions:
                    827:  * -> entering INIT state
                    828:  * -> recvpacket_flag == 0: timeout in this state
                    829:  * -> otherwise: received a packet in this state
                    830:  *
                    831:  * Return conditions as handled by dhclient_state_machine():
                    832:  * Returns 1, sendpacket_flag = 1: send packet, reset timer.
                    833:  * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
                    834:  * Returns 0: finish the nap which was interrupted for no good reason.
                    835:  *
                    836:  * Several per-interface variables are used to keep track of the process:
                    837:  *   active_lease: the lease that is being used on the interface
                    838:  *                 (null pointer if not configured yet).
                    839:  *   offered_leases: leases corresponding to DHCPOFFER messages that have
                    840:  *                  been sent to us by DHCP servers.
                    841:  *   acked_leases: leases corresponding to DHCPACK messages that have been
                    842:  *                sent to us by DHCP servers.
                    843:  *   sendpacket: DHCP packet we're trying to send.
                    844:  *   destination: IP address to send sendpacket to
                    845:  * In addition, there are several relevant per-lease variables.
                    846:  *   T1_expiry, T2_expiry, lease_expiry: lease milestones
                    847:  * In the active lease, these control the process of renewing the lease;
                    848:  * In leases on the acked_leases list, this simply determines when we
                    849:  * can no longer legitimately use the lease.
                    850:  */
                    851: 
                    852: void state_reboot (cpp)
                    853:        void *cpp;
                    854: {
                    855:        struct client_state *client = cpp;
                    856: 
                    857:        /* If we don't remember an active lease, go straight to INIT. */
                    858:        if (!client -> active ||
                    859:            client -> active -> is_bootp ||
                    860:            client -> active -> expiry <= cur_time) {
                    861:                state_init (client);
                    862:                return;
                    863:        }
                    864: 
                    865:        /* We are in the rebooting state. */
                    866:        client -> state = S_REBOOTING;
                    867: 
                    868:        /*
                    869:         * make_request doesn't initialize xid because it normally comes
                    870:         * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
                    871:         * so pick an xid now.
                    872:         */
                    873:        client -> xid = random ();
                    874: 
                    875:        /*
                    876:         * Make a DHCPREQUEST packet, and set
                    877:         * appropriate per-interface flags.
                    878:         */
                    879:        make_request (client, client -> active);
                    880:        client -> destination = iaddr_broadcast;
                    881:        client -> first_sending = cur_time;
                    882:        client -> interval = client -> config -> initial_interval;
                    883: 
                    884:        /* Zap the medium list... */
                    885:        client -> medium = NULL;
                    886: 
                    887:        /* Send out the first DHCPREQUEST packet. */
                    888:        send_request (client);
                    889: }
                    890: 
                    891: /* Called when a lease has completely expired and we've been unable to
                    892:    renew it. */
                    893: 
                    894: void state_init (cpp)
                    895:        void *cpp;
                    896: {
                    897:        struct client_state *client = cpp;
                    898: 
                    899:        ASSERT_STATE(state, S_INIT);
                    900: 
                    901:        /* Make a DHCPDISCOVER packet, and set appropriate per-interface
                    902:           flags. */
                    903:        make_discover (client, client -> active);
                    904:        client -> xid = client -> packet.xid;
                    905:        client -> destination = iaddr_broadcast;
                    906:        client -> state = S_SELECTING;
                    907:        client -> first_sending = cur_time;
                    908:        client -> interval = client -> config -> initial_interval;
                    909: 
                    910:        /* Add an immediate timeout to cause the first DHCPDISCOVER packet
                    911:           to go out. */
                    912:        send_discover (client);
                    913: }
                    914: 
                    915: /*
                    916:  * state_selecting is called when one or more DHCPOFFER packets have been
                    917:  * received and a configurable period of time has passed.
                    918:  */
                    919: 
                    920: void state_selecting (cpp)
                    921:        void *cpp;
                    922: {
                    923:        struct client_state *client = cpp;
                    924:        struct client_lease *lp, *next, *picked;
                    925: 
                    926: 
                    927:        ASSERT_STATE(state, S_SELECTING);
                    928: 
                    929:        /*
                    930:         * Cancel state_selecting and send_discover timeouts, since either
                    931:         * one could have got us here.
                    932:         */
                    933:        cancel_timeout (state_selecting, client);
                    934:        cancel_timeout (send_discover, client);
                    935: 
                    936:        /*
                    937:         * We have received one or more DHCPOFFER packets.   Currently,
                    938:         * the only criterion by which we judge leases is whether or
                    939:         * not we get a response when we arp for them.
                    940:         */
                    941:        picked = NULL;
                    942:        for (lp = client -> offered_leases; lp; lp = next) {
                    943:                next = lp -> next;
                    944: 
                    945:                /*
                    946:                 * Check to see if we got an ARPREPLY for the address
                    947:                 * in this particular lease.
                    948:                 */
                    949:                if (!picked) {
                    950:                        picked = lp;
                    951:                        picked -> next = NULL;
                    952:                } else {
                    953:                        destroy_client_lease (lp);
                    954:                }
                    955:        }
                    956:        client -> offered_leases = NULL;
                    957: 
                    958:        /*
                    959:         * If we just tossed all the leases we were offered, go back
                    960:         * to square one.
                    961:         */
                    962:        if (!picked) {
                    963:                client -> state = S_INIT;
                    964:                state_init (client);
                    965:                return;
                    966:        }
                    967: 
                    968:        /* If it was a BOOTREPLY, we can just take the address right now. */
                    969:        if (picked -> is_bootp) {
                    970:                client -> new = picked;
                    971: 
                    972:                /* Make up some lease expiry times
                    973:                   XXX these should be configurable. */
                    974:                client -> new -> expiry = cur_time + 12000;
                    975:                client -> new -> renewal += cur_time + 8000;
                    976:                client -> new -> rebind += cur_time + 10000;
                    977: 
                    978:                client -> state = S_REQUESTING;
                    979: 
                    980:                /* Bind to the address we received. */
                    981:                bind_lease (client);
                    982:                return;
                    983:        }
                    984: 
                    985:        /* Go to the REQUESTING state. */
                    986:        client -> destination = iaddr_broadcast;
                    987:        client -> state = S_REQUESTING;
                    988:        client -> first_sending = cur_time;
                    989:        client -> interval = client -> config -> initial_interval;
                    990: 
                    991:        /* Make a DHCPREQUEST packet from the lease we picked. */
                    992:        make_request (client, picked);
                    993:        client -> xid = client -> packet.xid;
                    994: 
                    995:        /* Toss the lease we picked - we'll get it back in a DHCPACK. */
                    996:        destroy_client_lease (picked);
                    997: 
                    998:        /* Add an immediate timeout to send the first DHCPREQUEST packet. */
                    999:        send_request (client);
                   1000: }
                   1001: 
                   1002: /* state_requesting is called when we receive a DHCPACK message after
                   1003:    having sent out one or more DHCPREQUEST packets. */
                   1004: 
                   1005: void dhcpack (packet)
                   1006:        struct packet *packet;
                   1007: {
                   1008:        struct interface_info *ip = packet -> interface;
                   1009:        struct client_state *client;
                   1010:        struct client_lease *lease;
                   1011:        struct option_cache *oc;
                   1012:        struct data_string ds;
                   1013: 
                   1014:        /* If we're not receptive to an offer right now, or if the offer
                   1015:           has an unrecognizable transaction id, then just drop it. */
                   1016:        for (client = ip -> client; client; client = client -> next) {
                   1017:                if (client -> xid == packet -> raw -> xid)
                   1018:                        break;
                   1019:        }
                   1020:        if (!client ||
                   1021:            (packet -> interface -> hw_address.hlen - 1 !=
                   1022:             packet -> raw -> hlen) ||
                   1023:            (memcmp (&packet -> interface -> hw_address.hbuf [1],
                   1024:                     packet -> raw -> chaddr, packet -> raw -> hlen))) {
                   1025: #if defined (DEBUG)
                   1026:                log_debug ("DHCPACK in wrong transaction.");
                   1027: #endif
                   1028:                return;
                   1029:        }
                   1030: 
                   1031:        if (client -> state != S_REBOOTING &&
                   1032:            client -> state != S_REQUESTING &&
                   1033:            client -> state != S_RENEWING &&
                   1034:            client -> state != S_REBINDING) {
                   1035: #if defined (DEBUG)
                   1036:                log_debug ("DHCPACK in wrong state.");
                   1037: #endif
                   1038:                return;
                   1039:        }
                   1040: 
                   1041:        log_info ("DHCPACK from %s", piaddr (packet -> client_addr));
                   1042: 
                   1043:        lease = packet_to_lease (packet, client);
                   1044:        if (!lease) {
                   1045:                log_info ("packet_to_lease failed.");
                   1046:                return;
                   1047:        }
                   1048: 
                   1049:        client -> new = lease;
                   1050: 
                   1051:        /* Stop resending DHCPREQUEST. */
                   1052:        cancel_timeout (send_request, client);
                   1053: 
                   1054:        /* Figure out the lease time. */
                   1055:        oc = lookup_option (&dhcp_universe, client -> new -> options,
                   1056:                            DHO_DHCP_LEASE_TIME);
                   1057:        memset (&ds, 0, sizeof ds);
                   1058:        if (oc &&
                   1059:            evaluate_option_cache (&ds, packet, (struct lease *)0, client,
                   1060:                                   packet -> options, client -> new -> options,
                   1061:                                   &global_scope, oc, MDL)) {
                   1062:                if (ds.len > 3)
                   1063:                        client -> new -> expiry = getULong (ds.data);
                   1064:                else
                   1065:                        client -> new -> expiry = 0;
                   1066:                data_string_forget (&ds, MDL);
                   1067:        } else
                   1068:                        client -> new -> expiry = 0;
                   1069: 
                   1070:        if (client->new->expiry == 0) {
                   1071:                struct timeval tv;
                   1072: 
                   1073:                log_error ("no expiry time on offered lease.");
                   1074: 
                   1075:                /* Quench this (broken) server.  Return to INIT to reselect. */
                   1076:                add_reject(packet);
                   1077: 
                   1078:                /* 1/2 second delay to restart at INIT. */
                   1079:                tv.tv_sec = cur_tv.tv_sec;
                   1080:                tv.tv_usec = cur_tv.tv_usec + 500000;
                   1081: 
                   1082:                if (tv.tv_usec >= 1000000) {
                   1083:                        tv.tv_sec++;
                   1084:                        tv.tv_usec -= 1000000;
                   1085:                }
                   1086: 
                   1087:                add_timeout(&tv, state_init, client, 0, 0);
                   1088:                return;
                   1089:        }
                   1090: 
                   1091:        /*
                   1092:         * A number that looks negative here is really just very large,
                   1093:         * because the lease expiry offset is unsigned.
                   1094:         */
                   1095:        if (client->new->expiry < 0)
                   1096:                client->new->expiry = TIME_MAX;
                   1097: 
                   1098:        /* Take the server-provided renewal time if there is one. */
                   1099:        oc = lookup_option (&dhcp_universe, client -> new -> options,
                   1100:                            DHO_DHCP_RENEWAL_TIME);
                   1101:        if (oc &&
                   1102:            evaluate_option_cache (&ds, packet, (struct lease *)0, client,
                   1103:                                   packet -> options, client -> new -> options,
                   1104:                                   &global_scope, oc, MDL)) {
                   1105:                if (ds.len > 3)
                   1106:                        client -> new -> renewal = getULong (ds.data);
                   1107:                else
                   1108:                        client -> new -> renewal = 0;
                   1109:                data_string_forget (&ds, MDL);
                   1110:        } else
                   1111:                        client -> new -> renewal = 0;
                   1112: 
                   1113:        /* If it wasn't specified by the server, calculate it. */
                   1114:        if (!client -> new -> renewal)
                   1115:                client -> new -> renewal = client -> new -> expiry / 2 + 1;
                   1116: 
                   1117:        if (client -> new -> renewal <= 0)
                   1118:                client -> new -> renewal = TIME_MAX;
                   1119: 
                   1120:        /* Now introduce some randomness to the renewal time: */
                   1121:        if (client->new->renewal <= ((TIME_MAX / 3) - 3))
                   1122:                client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
                   1123:                                (((random() % client->new->renewal) + 3) / 4);
                   1124: 
                   1125:        /* Same deal with the rebind time. */
                   1126:        oc = lookup_option (&dhcp_universe, client -> new -> options,
                   1127:                            DHO_DHCP_REBINDING_TIME);
                   1128:        if (oc &&
                   1129:            evaluate_option_cache (&ds, packet, (struct lease *)0, client,
                   1130:                                   packet -> options, client -> new -> options,
                   1131:                                   &global_scope, oc, MDL)) {
                   1132:                if (ds.len > 3)
                   1133:                        client -> new -> rebind = getULong (ds.data);
                   1134:                else
                   1135:                        client -> new -> rebind = 0;
                   1136:                data_string_forget (&ds, MDL);
                   1137:        } else
                   1138:                        client -> new -> rebind = 0;
                   1139: 
                   1140:        if (client -> new -> rebind <= 0) {
                   1141:                if (client -> new -> expiry <= TIME_MAX / 7)
                   1142:                        client -> new -> rebind =
                   1143:                                        client -> new -> expiry * 7 / 8;
                   1144:                else
                   1145:                        client -> new -> rebind =
                   1146:                                        client -> new -> expiry / 8 * 7;
                   1147:        }
                   1148: 
                   1149:        /* Make sure our randomness didn't run the renewal time past the
                   1150:           rebind time. */
                   1151:        if (client -> new -> renewal > client -> new -> rebind) {
                   1152:                if (client -> new -> rebind <= TIME_MAX / 3)
                   1153:                        client -> new -> renewal =
                   1154:                                        client -> new -> rebind * 3 / 4;
                   1155:                else
                   1156:                        client -> new -> renewal =
                   1157:                                        client -> new -> rebind / 4 * 3;
                   1158:        }
                   1159: 
                   1160:        client -> new -> expiry += cur_time;
                   1161:        /* Lease lengths can never be negative. */
                   1162:        if (client -> new -> expiry < cur_time)
                   1163:                client -> new -> expiry = TIME_MAX;
                   1164:        client -> new -> renewal += cur_time;
                   1165:        if (client -> new -> renewal < cur_time)
                   1166:                client -> new -> renewal = TIME_MAX;
                   1167:        client -> new -> rebind += cur_time;
                   1168:        if (client -> new -> rebind < cur_time)
                   1169:                client -> new -> rebind = TIME_MAX;
                   1170: 
                   1171:        bind_lease (client);
                   1172: }
                   1173: 
                   1174: void bind_lease (client)
                   1175:        struct client_state *client;
                   1176: {
                   1177:        struct timeval tv;
                   1178: 
                   1179:        /* Remember the medium. */
                   1180:        client -> new -> medium = client -> medium;
                   1181: 
                   1182:        /* Run the client script with the new parameters. */
                   1183:        script_init (client, (client -> state == S_REQUESTING
                   1184:                          ? "BOUND"
                   1185:                          : (client -> state == S_RENEWING
                   1186:                             ? "RENEW"
                   1187:                             : (client -> state == S_REBOOTING
                   1188:                                ? "REBOOT" : "REBIND"))),
                   1189:                     client -> new -> medium);
                   1190:        if (client -> active && client -> state != S_REBOOTING)
                   1191:                script_write_params (client, "old_", client -> active);
                   1192:        script_write_params (client, "new_", client -> new);
                   1193:        if (client -> alias)
                   1194:                script_write_params (client, "alias_", client -> alias);
                   1195: 
                   1196:        /* If the BOUND/RENEW code detects another machine using the
                   1197:           offered address, it exits nonzero.  We need to send a
                   1198:           DHCPDECLINE and toss the lease. */
                   1199:        if (script_go (client)) {
                   1200:                make_decline (client, client -> new);
                   1201:                send_decline (client);
                   1202:                destroy_client_lease (client -> new);
                   1203:                client -> new = (struct client_lease *)0;
                   1204:                state_init (client);
                   1205:                return;
                   1206:        }
                   1207: 
                   1208:        /* Write out the new lease if it has been long enough. */
                   1209:        if (!client->last_write ||
                   1210:            (cur_time - client->last_write) >= MIN_LEASE_WRITE)
                   1211:                write_client_lease(client, client->new, 0, 0);
                   1212: 
                   1213:        /* Replace the old active lease with the new one. */
                   1214:        if (client -> active)
                   1215:                destroy_client_lease (client -> active);
                   1216:        client -> active = client -> new;
                   1217:        client -> new = (struct client_lease *)0;
                   1218: 
                   1219:        /* Set up a timeout to start the renewal process. */
                   1220:        tv.tv_sec = client->active->renewal;
                   1221:        tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ?
                   1222:                        random() % 1000000 : cur_tv.tv_usec;
                   1223:        add_timeout(&tv, state_bound, client, 0, 0);
                   1224: 
                   1225:        log_info ("bound to %s -- renewal in %ld seconds.",
                   1226:              piaddr (client -> active -> address),
                   1227:              (long)(client -> active -> renewal - cur_time));
                   1228:        client -> state = S_BOUND;
                   1229:        reinitialize_interfaces ();
                   1230:        go_daemon ();
                   1231:        if (client->config->do_forward_update)
                   1232:                dhclient_schedule_updates(client, &client->active->address,
                   1233:                                          1);
                   1234: }
                   1235: 
                   1236: /* state_bound is called when we've successfully bound to a particular
                   1237:    lease, but the renewal time on that lease has expired.   We are
                   1238:    expected to unicast a DHCPREQUEST to the server that gave us our
                   1239:    original lease. */
                   1240: 
                   1241: void state_bound (cpp)
                   1242:        void *cpp;
                   1243: {
                   1244:        struct client_state *client = cpp;
                   1245:        struct option_cache *oc;
                   1246:        struct data_string ds;
                   1247: 
                   1248:        ASSERT_STATE(state, S_BOUND);
                   1249: 
                   1250:        /* T1 has expired. */
                   1251:        make_request (client, client -> active);
                   1252:        client -> xid = client -> packet.xid;
                   1253: 
                   1254:        memset (&ds, 0, sizeof ds);
                   1255:        oc = lookup_option (&dhcp_universe, client -> active -> options,
                   1256:                            DHO_DHCP_SERVER_IDENTIFIER);
                   1257:        if (oc &&
                   1258:            evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
                   1259:                                   client, (struct option_state *)0,
                   1260:                                   client -> active -> options,
                   1261:                                   &global_scope, oc, MDL)) {
                   1262:                if (ds.len > 3) {
                   1263:                        memcpy (client -> destination.iabuf, ds.data, 4);
                   1264:                        client -> destination.len = 4;
                   1265:                } else
                   1266:                        client -> destination = iaddr_broadcast;
                   1267: 
                   1268:                data_string_forget (&ds, MDL);
                   1269:        } else
                   1270:                client -> destination = iaddr_broadcast;
                   1271: 
                   1272:        client -> first_sending = cur_time;
                   1273:        client -> interval = client -> config -> initial_interval;
                   1274:        client -> state = S_RENEWING;
                   1275: 
                   1276:        /* Send the first packet immediately. */
                   1277:        send_request (client);
                   1278: }
                   1279: 
                   1280: /* state_stop is called when we've been told to shut down.   We unconfigure
                   1281:    the interfaces, and then stop operating until told otherwise. */
                   1282: 
                   1283: void state_stop (cpp)
                   1284:        void *cpp;
                   1285: {
                   1286:        struct client_state *client = cpp;
                   1287: 
                   1288:        /* Cancel all timeouts. */
                   1289:        cancel_timeout(state_selecting, client);
                   1290:        cancel_timeout(send_discover, client);
                   1291:        cancel_timeout(send_request, client);
                   1292:        cancel_timeout(state_bound, client);
                   1293: 
                   1294:        /* If we have an address, unconfigure it. */
                   1295:        if (client->active) {
                   1296:                script_init(client, "STOP", client->active->medium);
                   1297:                script_write_params(client, "old_", client->active);
                   1298:                if (client->alias)
                   1299:                        script_write_params(client, "alias_", client->alias);
                   1300:                script_go(client);
                   1301:        }
                   1302: }
                   1303: 
                   1304: int commit_leases ()
                   1305: {
                   1306:        return 0;
                   1307: }
                   1308: 
                   1309: int write_lease (lease)
                   1310:        struct lease *lease;
                   1311: {
                   1312:        return 0;
                   1313: }
                   1314: 
                   1315: int write_host (host)
                   1316:        struct host_decl *host;
                   1317: {
                   1318:        return 0;
                   1319: }
                   1320: 
                   1321: void db_startup (testp)
                   1322:        int testp;
                   1323: {
                   1324: }
                   1325: 
                   1326: void bootp (packet)
                   1327:        struct packet *packet;
                   1328: {
                   1329:        struct iaddrmatchlist *ap;
                   1330:        char addrbuf[4*16];
                   1331:        char maskbuf[4*16];
                   1332: 
                   1333:        if (packet -> raw -> op != BOOTREPLY)
                   1334:                return;
                   1335: 
                   1336:        /* If there's a reject list, make sure this packet's sender isn't
                   1337:           on it. */
                   1338:        for (ap = packet -> interface -> client -> config -> reject_list;
                   1339:             ap; ap = ap -> next) {
                   1340:                if (addr_match(&packet->client_addr, &ap->match)) {
                   1341: 
                   1342:                        /* piaddr() returns its result in a static
                   1343:                           buffer sized 4*16 (see common/inet.c). */
                   1344: 
                   1345:                        strcpy(addrbuf, piaddr(ap->match.addr));
                   1346:                        strcpy(maskbuf, piaddr(ap->match.mask));
                   1347: 
                   1348:                        log_info("BOOTREPLY from %s rejected by rule %s "
                   1349:                                 "mask %s.", piaddr(packet->client_addr),
                   1350:                                 addrbuf, maskbuf);
                   1351:                        return;
                   1352:                }
                   1353:        }
                   1354: 
                   1355:        dhcpoffer (packet);
                   1356: 
                   1357: }
                   1358: 
                   1359: void dhcp (packet)
                   1360:        struct packet *packet;
                   1361: {
                   1362:        struct iaddrmatchlist *ap;
                   1363:        void (*handler) (struct packet *);
                   1364:        const char *type;
                   1365:        char addrbuf[4*16];
                   1366:        char maskbuf[4*16];
                   1367: 
                   1368:        switch (packet -> packet_type) {
                   1369:              case DHCPOFFER:
                   1370:                handler = dhcpoffer;
                   1371:                type = "DHCPOFFER";
                   1372:                break;
                   1373: 
                   1374:              case DHCPNAK:
                   1375:                handler = dhcpnak;
                   1376:                type = "DHCPNACK";
                   1377:                break;
                   1378: 
                   1379:              case DHCPACK:
                   1380:                handler = dhcpack;
                   1381:                type = "DHCPACK";
                   1382:                break;
                   1383: 
                   1384:              default:
                   1385:                return;
                   1386:        }
                   1387: 
                   1388:        /* If there's a reject list, make sure this packet's sender isn't
                   1389:           on it. */
                   1390:        for (ap = packet -> interface -> client -> config -> reject_list;
                   1391:             ap; ap = ap -> next) {
                   1392:                if (addr_match(&packet->client_addr, &ap->match)) {
                   1393: 
                   1394:                        /* piaddr() returns its result in a static
                   1395:                           buffer sized 4*16 (see common/inet.c). */
                   1396: 
                   1397:                        strcpy(addrbuf, piaddr(ap->match.addr));
                   1398:                        strcpy(maskbuf, piaddr(ap->match.mask));
                   1399: 
                   1400:                        log_info("%s from %s rejected by rule %s mask %s.",
                   1401:                                 type, piaddr(packet->client_addr),
                   1402:                                 addrbuf, maskbuf);
                   1403:                        return;
                   1404:                }
                   1405:        }
                   1406:        (*handler) (packet);
                   1407: }
                   1408: 
                   1409: #ifdef DHCPv6
                   1410: void
                   1411: dhcpv6(struct packet *packet) {
                   1412:        struct iaddrmatchlist *ap;
                   1413:        struct client_state *client;
                   1414:        char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
                   1415: 
                   1416:        /* Silently drop bogus messages. */
                   1417:        if (packet->dhcpv6_msg_type >= dhcpv6_type_name_max)
                   1418:                return;
                   1419: 
                   1420:        /* Discard, with log, packets from quenched sources. */
                   1421:        for (ap = packet->interface->client->config->reject_list ;
                   1422:             ap ; ap = ap->next) {
                   1423:                if (addr_match(&packet->client_addr, &ap->match)) {
                   1424:                        strcpy(addrbuf, piaddr(packet->client_addr));
                   1425:                        log_info("%s from %s rejected by rule %s",
                   1426:                                 dhcpv6_type_names[packet->dhcpv6_msg_type],
                   1427:                                 addrbuf,
                   1428:                                 piaddrmask(&ap->match.addr, &ap->match.mask));
                   1429:                        return;
                   1430:                }
                   1431:        }
                   1432: 
                   1433:        /* Screen out nonsensical messages. */
                   1434:        switch(packet->dhcpv6_msg_type) {
                   1435:              case DHCPV6_ADVERTISE:
                   1436:              case DHCPV6_RECONFIGURE:
                   1437:                if (stateless)
                   1438:                  return;
                   1439:              /* Falls through */
                   1440:              case DHCPV6_REPLY:
                   1441:                log_info("RCV: %s message on %s from %s.",
                   1442:                         dhcpv6_type_names[packet->dhcpv6_msg_type],
                   1443:                         packet->interface->name, piaddr(packet->client_addr));
                   1444:                break;
                   1445: 
                   1446:              default:
                   1447:                return;
                   1448:        }
                   1449: 
                   1450:        /* Find a client state that matches the incoming XID. */
                   1451:        for (client = packet->interface->client ; client ;
                   1452:             client = client->next) {
                   1453:                if (memcmp(&client->dhcpv6_transaction_id,
                   1454:                           packet->dhcpv6_transaction_id, 3) == 0) {
                   1455:                        client->v6_handler(packet, client);
                   1456:                        return;
                   1457:                }
                   1458:        }
                   1459: 
                   1460:        /* XXX: temporary log for debugging */
                   1461:        log_info("Packet received, but nothing done with it.");
                   1462: }
                   1463: #endif /* DHCPv6 */
                   1464: 
                   1465: void dhcpoffer (packet)
                   1466:        struct packet *packet;
                   1467: {
                   1468:        struct interface_info *ip = packet -> interface;
                   1469:        struct client_state *client;
                   1470:        struct client_lease *lease, *lp;
                   1471:        struct option **req;
                   1472:        int i;
                   1473:        int stop_selecting;
                   1474:        const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
                   1475:        char obuf [1024];
                   1476:        struct timeval tv;
                   1477: 
                   1478: #ifdef DEBUG_PACKET
                   1479:        dump_packet (packet);
                   1480: #endif
                   1481: 
                   1482:        /* Find a client state that matches the xid... */
                   1483:        for (client = ip -> client; client; client = client -> next)
                   1484:                if (client -> xid == packet -> raw -> xid)
                   1485:                        break;
                   1486: 
                   1487:        /* If we're not receptive to an offer right now, or if the offer
                   1488:           has an unrecognizable transaction id, then just drop it. */
                   1489:        if (!client ||
                   1490:            client -> state != S_SELECTING ||
                   1491:            (packet -> interface -> hw_address.hlen - 1 !=
                   1492:             packet -> raw -> hlen) ||
                   1493:            (memcmp (&packet -> interface -> hw_address.hbuf [1],
                   1494:                     packet -> raw -> chaddr, packet -> raw -> hlen))) {
                   1495: #if defined (DEBUG)
                   1496:                log_debug ("%s in wrong transaction.", name);
                   1497: #endif
                   1498:                return;
                   1499:        }
                   1500: 
                   1501:        sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
                   1502: 
                   1503: 
                   1504:        /* If this lease doesn't supply the minimum required DHCPv4 parameters,
                   1505:         * ignore it.
                   1506:         */
                   1507:        req = client->config->required_options;
                   1508:        if (req != NULL) {
                   1509:                for (i = 0 ; req[i] != NULL ; i++) {
                   1510:                        if ((req[i]->universe == &dhcp_universe) &&
                   1511:                            !lookup_option(&dhcp_universe, packet->options,
                   1512:                                           req[i]->code)) {
                   1513:                                struct option *option = NULL;
                   1514:                                unsigned code = req[i]->code;
                   1515: 
                   1516:                                option_code_hash_lookup(&option,
                   1517:                                                        dhcp_universe.code_hash,
                   1518:                                                        &code, 0, MDL);
                   1519: 
                   1520:                                if (option)
                   1521:                                        log_info("%s: no %s option.", obuf,
                   1522:                                                 option->name);
                   1523:                                else
                   1524:                                        log_info("%s: no unknown-%u option.",
                   1525:                                                 obuf, code);
                   1526: 
                   1527:                                option_dereference(&option, MDL);
                   1528: 
                   1529:                                return;
                   1530:                        }
                   1531:                }
                   1532:        }
                   1533: 
                   1534:        /* If we've already seen this lease, don't record it again. */
                   1535:        for (lease = client -> offered_leases; lease; lease = lease -> next) {
                   1536:                if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
                   1537:                    !memcmp (lease -> address.iabuf,
                   1538:                             &packet -> raw -> yiaddr, lease -> address.len)) {
                   1539:                        log_debug ("%s: already seen.", obuf);
                   1540:                        return;
                   1541:                }
                   1542:        }
                   1543: 
                   1544:        lease = packet_to_lease (packet, client);
                   1545:        if (!lease) {
                   1546:                log_info ("%s: packet_to_lease failed.", obuf);
                   1547:                return;
                   1548:        }
                   1549: 
                   1550:        /* If this lease was acquired through a BOOTREPLY, record that
                   1551:           fact. */
                   1552:        if (!packet -> options_valid || !packet -> packet_type)
                   1553:                lease -> is_bootp = 1;
                   1554: 
                   1555:        /* Record the medium under which this lease was offered. */
                   1556:        lease -> medium = client -> medium;
                   1557: 
                   1558:        /* Figure out when we're supposed to stop selecting. */
                   1559:        stop_selecting = (client -> first_sending +
                   1560:                          client -> config -> select_interval);
                   1561: 
                   1562:        /* If this is the lease we asked for, put it at the head of the
                   1563:           list, and don't mess with the arp request timeout. */
                   1564:        if (lease -> address.len == client -> requested_address.len &&
                   1565:            !memcmp (lease -> address.iabuf,
                   1566:                     client -> requested_address.iabuf,
                   1567:                     client -> requested_address.len)) {
                   1568:                lease -> next = client -> offered_leases;
                   1569:                client -> offered_leases = lease;
                   1570:        } else {
                   1571:                /* Put the lease at the end of the list. */
                   1572:                lease -> next = (struct client_lease *)0;
                   1573:                if (!client -> offered_leases)
                   1574:                        client -> offered_leases = lease;
                   1575:                else {
                   1576:                        for (lp = client -> offered_leases; lp -> next;
                   1577:                             lp = lp -> next)
                   1578:                                ;
                   1579:                        lp -> next = lease;
                   1580:                }
                   1581:        }
                   1582: 
                   1583:        /* If the selecting interval has expired, go immediately to
                   1584:           state_selecting().  Otherwise, time out into
                   1585:           state_selecting at the select interval. */
                   1586:        if (stop_selecting <= cur_tv.tv_sec)
                   1587:                state_selecting (client);
                   1588:        else {
                   1589:                tv.tv_sec = stop_selecting;
                   1590:                tv.tv_usec = cur_tv.tv_usec;
                   1591:                add_timeout(&tv, state_selecting, client, 0, 0);
                   1592:                cancel_timeout(send_discover, client);
                   1593:        }
                   1594:        log_info("%s", obuf);
                   1595: }
                   1596: 
                   1597: /* Allocate a client_lease structure and initialize it from the parameters
                   1598:    in the specified packet. */
                   1599: 
                   1600: struct client_lease *packet_to_lease (packet, client)
                   1601:        struct packet *packet;
                   1602:        struct client_state *client;
                   1603: {
                   1604:        struct client_lease *lease;
                   1605:        unsigned i;
                   1606:        struct option_cache *oc;
                   1607:        struct option *option = NULL;
                   1608:        struct data_string data;
                   1609: 
                   1610:        lease = (struct client_lease *)new_client_lease (MDL);
                   1611: 
                   1612:        if (!lease) {
                   1613:                log_error ("packet_to_lease: no memory to record lease.\n");
                   1614:                return (struct client_lease *)0;
                   1615:        }
                   1616: 
                   1617:        memset (lease, 0, sizeof *lease);
                   1618: 
                   1619:        /* Copy the lease options. */
                   1620:        option_state_reference (&lease -> options, packet -> options, MDL);
                   1621: 
                   1622:        lease -> address.len = sizeof (packet -> raw -> yiaddr);
                   1623:        memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
                   1624:                lease -> address.len);
                   1625: 
                   1626:        memset (&data, 0, sizeof data);
                   1627: 
                   1628:        if (client -> config -> vendor_space_name) {
                   1629:                i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
                   1630: 
                   1631:                /* See if there was a vendor encapsulation option. */
                   1632:                oc = lookup_option (&dhcp_universe, lease -> options, i);
                   1633:                if (oc &&
                   1634:                    client -> config -> vendor_space_name &&
                   1635:                    evaluate_option_cache (&data, packet,
                   1636:                                           (struct lease *)0, client,
                   1637:                                           packet -> options, lease -> options,
                   1638:                                           &global_scope, oc, MDL)) {
                   1639:                        if (data.len) {
                   1640:                                if (!option_code_hash_lookup(&option,
                   1641:                                                dhcp_universe.code_hash,
                   1642:                                                &i, 0, MDL))
                   1643:                                        log_fatal("Unable to find VENDOR "
                   1644:                                                  "option (%s:%d).", MDL);
                   1645:                                parse_encapsulated_suboptions
                   1646:                                        (packet -> options, option,
                   1647:                                         data.data, data.len, &dhcp_universe,
                   1648:                                         client -> config -> vendor_space_name
                   1649:                                                );
                   1650: 
                   1651:                                option_dereference(&option, MDL);
                   1652:                        }
                   1653:                        data_string_forget (&data, MDL);
                   1654:                }
                   1655:        } else
                   1656:                i = 0;
                   1657: 
                   1658:        /* Figure out the overload flag. */
                   1659:        oc = lookup_option (&dhcp_universe, lease -> options,
                   1660:                            DHO_DHCP_OPTION_OVERLOAD);
                   1661:        if (oc &&
                   1662:            evaluate_option_cache (&data, packet, (struct lease *)0, client,
                   1663:                                   packet -> options, lease -> options,
                   1664:                                   &global_scope, oc, MDL)) {
                   1665:                if (data.len > 0)
                   1666:                        i = data.data [0];
                   1667:                else
                   1668:                        i = 0;
                   1669:                data_string_forget (&data, MDL);
                   1670:        } else
                   1671:                i = 0;
                   1672: 
                   1673:        /* If the server name was filled out, copy it. */
                   1674:        if (!(i & 2) && packet -> raw -> sname [0]) {
                   1675:                unsigned len;
                   1676:                /* Don't count on the NUL terminator. */
                   1677:                for (len = 0; len < DHCP_SNAME_LEN; len++)
                   1678:                        if (!packet -> raw -> sname [len])
                   1679:                                break;
                   1680:                lease -> server_name = dmalloc (len + 1, MDL);
                   1681:                if (!lease -> server_name) {
                   1682:                        log_error ("dhcpoffer: no memory for server name.\n");
                   1683:                        destroy_client_lease (lease);
                   1684:                        return (struct client_lease *)0;
                   1685:                } else {
                   1686:                        memcpy (lease -> server_name,
                   1687:                                packet -> raw -> sname, len);
                   1688:                        lease -> server_name [len] = 0;
                   1689:                }
                   1690:        }
                   1691: 
                   1692:        /* Ditto for the filename. */
                   1693:        if (!(i & 1) && packet -> raw -> file [0]) {
                   1694:                unsigned len;
                   1695:                /* Don't count on the NUL terminator. */
                   1696:                for (len = 0; len < DHCP_FILE_LEN; len++)
                   1697:                        if (!packet -> raw -> file [len])
                   1698:                                break;
                   1699:                lease -> filename = dmalloc (len + 1, MDL);
                   1700:                if (!lease -> filename) {
                   1701:                        log_error ("dhcpoffer: no memory for filename.\n");
                   1702:                        destroy_client_lease (lease);
                   1703:                        return (struct client_lease *)0;
                   1704:                } else {
                   1705:                        memcpy (lease -> filename,
                   1706:                                packet -> raw -> file, len);
                   1707:                        lease -> filename [len] = 0;
                   1708:                }
                   1709:        }
                   1710: 
                   1711:        execute_statements_in_scope ((struct binding_value **)0,
                   1712:                                     (struct packet *)packet,
                   1713:                                     (struct lease *)0, client,
                   1714:                                     lease -> options, lease -> options,
                   1715:                                     &global_scope,
                   1716:                                     client -> config -> on_receipt,
                   1717:                                     (struct group *)0);
                   1718: 
                   1719:        return lease;
                   1720: }
                   1721: 
                   1722: void dhcpnak (packet)
                   1723:        struct packet *packet;
                   1724: {
                   1725:        struct interface_info *ip = packet -> interface;
                   1726:        struct client_state *client;
                   1727: 
                   1728:        /* Find a client state that matches the xid... */
                   1729:        for (client = ip -> client; client; client = client -> next)
                   1730:                if (client -> xid == packet -> raw -> xid)
                   1731:                        break;
                   1732: 
                   1733:        /* If we're not receptive to an offer right now, or if the offer
                   1734:           has an unrecognizable transaction id, then just drop it. */
                   1735:        if (!client ||
                   1736:            (packet -> interface -> hw_address.hlen - 1 !=
                   1737:             packet -> raw -> hlen) ||
                   1738:            (memcmp (&packet -> interface -> hw_address.hbuf [1],
                   1739:                     packet -> raw -> chaddr, packet -> raw -> hlen))) {
                   1740: #if defined (DEBUG)
                   1741:                log_debug ("DHCPNAK in wrong transaction.");
                   1742: #endif
                   1743:                return;
                   1744:        }
                   1745: 
                   1746:        if (client -> state != S_REBOOTING &&
                   1747:            client -> state != S_REQUESTING &&
                   1748:            client -> state != S_RENEWING &&
                   1749:            client -> state != S_REBINDING) {
                   1750: #if defined (DEBUG)
                   1751:                log_debug ("DHCPNAK in wrong state.");
                   1752: #endif
                   1753:                return;
                   1754:        }
                   1755: 
                   1756:        log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
                   1757: 
                   1758:        if (!client -> active) {
                   1759: #if defined (DEBUG)
                   1760:                log_info ("DHCPNAK with no active lease.\n");
                   1761: #endif
                   1762:                return;
                   1763:        }
                   1764: 
                   1765:        /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
                   1766:         * to indicate that we want all old bindings to be removed.  (It
                   1767:         * is possible that we may get a NAK while in the RENEW state,
                   1768:         * so we might have bindings active at that time)
                   1769:         */
                   1770:        script_init(client, "EXPIRE", NULL);
                   1771:        script_write_params(client, "old_", client->active);
                   1772:        if (client->alias)
                   1773:                script_write_params(client, "alias_", client->alias);
                   1774:        script_go(client);
                   1775: 
                   1776:        destroy_client_lease (client -> active);
                   1777:        client -> active = (struct client_lease *)0;
                   1778: 
                   1779:        /* Stop sending DHCPREQUEST packets... */
                   1780:        cancel_timeout (send_request, client);
                   1781: 
                   1782:        /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
                   1783:         * down (this expunges any routes and arp cache).  This makes the
                   1784:         * interface unusable by state_init(), which we call next.  So, we
                   1785:         * need to 'PREINIT' the interface to bring it back up.
                   1786:         */
                   1787:        script_init(client, "PREINIT", NULL);
                   1788:        if (client->alias)
                   1789:                script_write_params(client, "alias_", client->alias);
                   1790:        script_go(client);
                   1791: 
                   1792:        client -> state = S_INIT;
                   1793:        state_init (client);
                   1794: }
                   1795: 
                   1796: /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
                   1797:    one after the right interval has expired.  If we don't get an offer by
                   1798:    the time we reach the panic interval, call the panic function. */
                   1799: 
                   1800: void send_discover (cpp)
                   1801:        void *cpp;
                   1802: {
                   1803:        struct client_state *client = cpp;
                   1804: 
                   1805:        int result;
                   1806:        int interval;
                   1807:        int increase = 1;
                   1808:        struct timeval tv;
                   1809: 
                   1810:        /* Figure out how long it's been since we started transmitting. */
                   1811:        interval = cur_time - client -> first_sending;
                   1812: 
                   1813:        /* If we're past the panic timeout, call the script and tell it
                   1814:           we haven't found anything for this interface yet. */
                   1815:        if (interval > client -> config -> timeout) {
                   1816:                state_panic (client);
                   1817:                return;
                   1818:        }
                   1819: 
                   1820:        /* If we're selecting media, try the whole list before doing
                   1821:           the exponential backoff, but if we've already received an
                   1822:           offer, stop looping, because we obviously have it right. */
                   1823:        if (!client -> offered_leases &&
                   1824:            client -> config -> media) {
                   1825:                int fail = 0;
                   1826:              again:
                   1827:                if (client -> medium) {
                   1828:                        client -> medium = client -> medium -> next;
                   1829:                        increase = 0;
                   1830:                }
                   1831:                if (!client -> medium) {
                   1832:                        if (fail)
                   1833:                                log_fatal ("No valid media types for %s!",
                   1834:                                       client -> interface -> name);
                   1835:                        client -> medium =
                   1836:                                client -> config -> media;
                   1837:                        increase = 1;
                   1838:                }
                   1839: 
                   1840:                log_info ("Trying medium \"%s\" %d",
                   1841:                          client -> medium -> string, increase);
                   1842:                script_init (client, "MEDIUM", client -> medium);
                   1843:                if (script_go (client)) {
                   1844:                        fail = 1;
                   1845:                        goto again;
                   1846:                }
                   1847:        }
                   1848: 
                   1849:        /* If we're supposed to increase the interval, do so.  If it's
                   1850:           currently zero (i.e., we haven't sent any packets yet), set
                   1851:           it to initial_interval; otherwise, add to it a random number
                   1852:           between zero and two times itself.  On average, this means
                   1853:           that it will double with every transmission. */
                   1854:        if (increase) {
                   1855:                if (!client->interval)
                   1856:                        client->interval = client->config->initial_interval;
                   1857:                else
                   1858:                        client->interval += random() % (2 * client->interval);
                   1859: 
                   1860:                /* Don't backoff past cutoff. */
                   1861:                if (client->interval > client->config->backoff_cutoff)
                   1862:                        client->interval = (client->config->backoff_cutoff / 2)
                   1863:                                 + (random() % client->config->backoff_cutoff);
                   1864:        } else if (!client->interval)
                   1865:                client->interval = client->config->initial_interval;
                   1866: 
                   1867:        /* If the backoff would take us to the panic timeout, just use that
                   1868:           as the interval. */
                   1869:        if (cur_time + client -> interval >
                   1870:            client -> first_sending + client -> config -> timeout)
                   1871:                client -> interval =
                   1872:                        (client -> first_sending +
                   1873:                         client -> config -> timeout) - cur_time + 1;
                   1874: 
                   1875:        /* Record the number of seconds since we started sending. */
                   1876:        if (interval < 65536)
                   1877:                client -> packet.secs = htons (interval);
                   1878:        else
                   1879:                client -> packet.secs = htons (65535);
                   1880:        client -> secs = client -> packet.secs;
                   1881: 
                   1882:        log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
                   1883:              client -> name ? client -> name : client -> interface -> name,
                   1884:              inet_ntoa (sockaddr_broadcast.sin_addr),
                   1885:              ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
                   1886: 
                   1887:        /* Send out a packet. */
1.1.1.1 ! misho    1888:        result = send_packet(client->interface, NULL, &client->packet,
        !          1889:                             client->packet_length, inaddr_any,
        !          1890:                              &sockaddr_broadcast, NULL);
        !          1891:         if (result < 0) {
        !          1892:                log_error("%s:%d: Failed to send %d byte long packet over %s "
        !          1893:                          "interface.", MDL, client->packet_length,
        !          1894:                          client->interface->name);
        !          1895:        }
1.1       misho    1896: 
                   1897:        /*
                   1898:         * If we used 0 microseconds here, and there were other clients on the
                   1899:         * same network with a synchronized local clock (ntp), and a similar
                   1900:         * zero-microsecond-scheduler behavior, then we could be participating
                   1901:         * in a sub-second DOS ttck.
                   1902:         */
                   1903:        tv.tv_sec = cur_tv.tv_sec + client->interval;
                   1904:        tv.tv_usec = client->interval > 1 ? random() % 1000000 : cur_tv.tv_usec;
                   1905:        add_timeout(&tv, send_discover, client, 0, 0);
                   1906: }
                   1907: 
                   1908: /* state_panic gets called if we haven't received any offers in a preset
                   1909:    amount of time.   When this happens, we try to use existing leases that
                   1910:    haven't yet expired, and failing that, we call the client script and
                   1911:    hope it can do something. */
                   1912: 
                   1913: void state_panic (cpp)
                   1914:        void *cpp;
                   1915: {
                   1916:        struct client_state *client = cpp;
                   1917:        struct client_lease *loop;
                   1918:        struct client_lease *lp;
                   1919:        struct timeval tv;
                   1920: 
                   1921:        loop = lp = client -> active;
                   1922: 
                   1923:        log_info ("No DHCPOFFERS received.");
                   1924: 
                   1925:        /* We may not have an active lease, but we may have some
                   1926:           predefined leases that we can try. */
                   1927:        if (!client -> active && client -> leases)
                   1928:                goto activate_next;
                   1929: 
                   1930:        /* Run through the list of leases and see if one can be used. */
                   1931:        while (client -> active) {
                   1932:                if (client -> active -> expiry > cur_time) {
                   1933:                        log_info ("Trying recorded lease %s",
                   1934:                              piaddr (client -> active -> address));
                   1935:                        /* Run the client script with the existing
                   1936:                           parameters. */
                   1937:                        script_init (client, "TIMEOUT",
                   1938:                                     client -> active -> medium);
                   1939:                        script_write_params (client, "new_", client -> active);
                   1940:                        if (client -> alias)
                   1941:                                script_write_params (client, "alias_",
                   1942:                                                     client -> alias);
                   1943: 
                   1944:                        /* If the old lease is still good and doesn't
                   1945:                           yet need renewal, go into BOUND state and
                   1946:                           timeout at the renewal time. */
                   1947:                        if (!script_go (client)) {
                   1948:                            if (cur_time < client -> active -> renewal) {
                   1949:                                client -> state = S_BOUND;
                   1950:                                log_info ("bound: renewal in %ld %s.",
                   1951:                                          (long)(client -> active -> renewal -
                   1952:                                                 cur_time), "seconds");
                   1953:                                tv.tv_sec = client->active->renewal;
                   1954:                                tv.tv_usec = ((client->active->renewal -
                   1955:                                                    cur_time) > 1) ?
                   1956:                                                random() % 1000000 :
                   1957:                                                cur_tv.tv_usec;
                   1958:                                add_timeout(&tv, state_bound, client, 0, 0);
                   1959:                            } else {
                   1960:                                client -> state = S_BOUND;
                   1961:                                log_info ("bound: immediate renewal.");
                   1962:                                state_bound (client);
                   1963:                            }
                   1964:                            reinitialize_interfaces ();
                   1965:                            go_daemon ();
                   1966:                            return;
                   1967:                        }
                   1968:                }
                   1969: 
                   1970:                /* If there are no other leases, give up. */
                   1971:                if (!client -> leases) {
                   1972:                        client -> leases = client -> active;
                   1973:                        client -> active = (struct client_lease *)0;
                   1974:                        break;
                   1975:                }
                   1976: 
                   1977:        activate_next:
                   1978:                /* Otherwise, put the active lease at the end of the
                   1979:                   lease list, and try another lease.. */
                   1980:                for (lp = client -> leases; lp -> next; lp = lp -> next)
                   1981:                        ;
                   1982:                lp -> next = client -> active;
                   1983:                if (lp -> next) {
                   1984:                        lp -> next -> next = (struct client_lease *)0;
                   1985:                }
                   1986:                client -> active = client -> leases;
                   1987:                client -> leases = client -> leases -> next;
                   1988: 
                   1989:                /* If we already tried this lease, we've exhausted the
                   1990:                   set of leases, so we might as well give up for
                   1991:                   now. */
                   1992:                if (client -> active == loop)
                   1993:                        break;
                   1994:                else if (!loop)
                   1995:                        loop = client -> active;
                   1996:        }
                   1997: 
                   1998:        /* No leases were available, or what was available didn't work, so
                   1999:           tell the shell script that we failed to allocate an address,
                   2000:           and try again later. */
                   2001:        if (onetry) {
                   2002:                if (!quiet)
                   2003:                        log_info ("Unable to obtain a lease on first try.%s",
                   2004:                                  "  Exiting.");
                   2005:                exit (2);
                   2006:        }
                   2007: 
                   2008:        log_info ("No working leases in persistent database - sleeping.");
                   2009:        script_init (client, "FAIL", (struct string_list *)0);
                   2010:        if (client -> alias)
                   2011:                script_write_params (client, "alias_", client -> alias);
                   2012:        script_go (client);
                   2013:        client -> state = S_INIT;
                   2014:        tv.tv_sec = cur_tv.tv_sec + ((client->config->retry_interval + 1) / 2 +
                   2015:                    (random() % client->config->retry_interval));
                   2016:        tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
                   2017:                        random() % 1000000 : cur_tv.tv_usec;
                   2018:        add_timeout(&tv, state_init, client, 0, 0);
                   2019:        go_daemon ();
                   2020: }
                   2021: 
                   2022: void send_request (cpp)
                   2023:        void *cpp;
                   2024: {
                   2025:        struct client_state *client = cpp;
                   2026: 
                   2027:        int result;
                   2028:        int interval;
                   2029:        struct sockaddr_in destination;
                   2030:        struct in_addr from;
                   2031:        struct timeval tv;
                   2032: 
                   2033:        /* Figure out how long it's been since we started transmitting. */
                   2034:        interval = cur_time - client -> first_sending;
                   2035: 
                   2036:        /* If we're in the INIT-REBOOT or REQUESTING state and we're
                   2037:           past the reboot timeout, go to INIT and see if we can
                   2038:           DISCOVER an address... */
                   2039:        /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
                   2040:           means either that we're on a network with no DHCP server,
                   2041:           or that our server is down.  In the latter case, assuming
                   2042:           that there is a backup DHCP server, DHCPDISCOVER will get
                   2043:           us a new address, but we could also have successfully
                   2044:           reused our old address.  In the former case, we're hosed
                   2045:           anyway.  This is not a win-prone situation. */
                   2046:        if ((client -> state == S_REBOOTING ||
                   2047:             client -> state == S_REQUESTING) &&
                   2048:            interval > client -> config -> reboot_timeout) {
                   2049:        cancel:
                   2050:                client -> state = S_INIT;
                   2051:                cancel_timeout (send_request, client);
                   2052:                state_init (client);
                   2053:                return;
                   2054:        }
                   2055: 
                   2056:        /* If we're in the reboot state, make sure the media is set up
                   2057:           correctly. */
                   2058:        if (client -> state == S_REBOOTING &&
                   2059:            !client -> medium &&
                   2060:            client -> active -> medium ) {
                   2061:                script_init (client, "MEDIUM", client -> active -> medium);
                   2062: 
                   2063:                /* If the medium we chose won't fly, go to INIT state. */
                   2064:                if (script_go (client))
                   2065:                        goto cancel;
                   2066: 
                   2067:                /* Record the medium. */
                   2068:                client -> medium = client -> active -> medium;
                   2069:        }
                   2070: 
                   2071:        /* If the lease has expired, relinquish the address and go back
                   2072:           to the INIT state. */
                   2073:        if (client -> state != S_REQUESTING &&
                   2074:            cur_time > client -> active -> expiry) {
                   2075:                /* Run the client script with the new parameters. */
                   2076:                script_init (client, "EXPIRE", (struct string_list *)0);
                   2077:                script_write_params (client, "old_", client -> active);
                   2078:                if (client -> alias)
                   2079:                        script_write_params (client, "alias_",
                   2080:                                             client -> alias);
                   2081:                script_go (client);
                   2082: 
                   2083:                /* Now do a preinit on the interface so that we can
                   2084:                   discover a new address. */
                   2085:                script_init (client, "PREINIT", (struct string_list *)0);
                   2086:                if (client -> alias)
                   2087:                        script_write_params (client, "alias_",
                   2088:                                             client -> alias);
                   2089:                script_go (client);
                   2090: 
                   2091:                client -> state = S_INIT;
                   2092:                state_init (client);
                   2093:                return;
                   2094:        }
                   2095: 
                   2096:        /* Do the exponential backoff... */
                   2097:        if (!client -> interval)
                   2098:                client -> interval = client -> config -> initial_interval;
                   2099:        else {
                   2100:                client -> interval += ((random () >> 2) %
                   2101:                                       (2 * client -> interval));
                   2102:        }
                   2103: 
                   2104:        /* Don't backoff past cutoff. */
                   2105:        if (client -> interval >
                   2106:            client -> config -> backoff_cutoff)
                   2107:                client -> interval =
                   2108:                        ((client -> config -> backoff_cutoff / 2)
                   2109:                         + ((random () >> 2) %
                   2110:                                        client -> config -> backoff_cutoff));
                   2111: 
                   2112:        /* If the backoff would take us to the expiry time, just set the
                   2113:           timeout to the expiry time. */
                   2114:        if (client -> state != S_REQUESTING &&
                   2115:            cur_time + client -> interval > client -> active -> expiry)
                   2116:                client -> interval =
                   2117:                        client -> active -> expiry - cur_time + 1;
                   2118: 
                   2119:        /* If the lease T2 time has elapsed, or if we're not yet bound,
                   2120:           broadcast the DHCPREQUEST rather than unicasting. */
                   2121:        if (client -> state == S_REQUESTING ||
                   2122:            client -> state == S_REBOOTING ||
                   2123:            cur_time > client -> active -> rebind)
                   2124:                destination.sin_addr = sockaddr_broadcast.sin_addr;
                   2125:        else
                   2126:                memcpy (&destination.sin_addr.s_addr,
                   2127:                        client -> destination.iabuf,
                   2128:                        sizeof destination.sin_addr.s_addr);
                   2129:        destination.sin_port = remote_port;
                   2130:        destination.sin_family = AF_INET;
                   2131: #ifdef HAVE_SA_LEN
                   2132:        destination.sin_len = sizeof destination;
                   2133: #endif
                   2134: 
                   2135:        if (client -> state == S_RENEWING ||
                   2136:            client -> state == S_REBINDING)
                   2137:                memcpy (&from, client -> active -> address.iabuf,
                   2138:                        sizeof from);
                   2139:        else
                   2140:                from.s_addr = INADDR_ANY;
                   2141: 
                   2142:        /* Record the number of seconds since we started sending. */
                   2143:        if (client -> state == S_REQUESTING)
                   2144:                client -> packet.secs = client -> secs;
                   2145:        else {
                   2146:                if (interval < 65536)
                   2147:                        client -> packet.secs = htons (interval);
                   2148:                else
                   2149:                        client -> packet.secs = htons (65535);
                   2150:        }
                   2151: 
                   2152:        log_info ("DHCPREQUEST on %s to %s port %d",
                   2153:              client -> name ? client -> name : client -> interface -> name,
                   2154:              inet_ntoa (destination.sin_addr),
                   2155:              ntohs (destination.sin_port));
                   2156: 
                   2157:        if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
1.1.1.1 ! misho    2158:            fallback_interface) {
        !          2159:                result = send_packet(fallback_interface, NULL, &client->packet,
        !          2160:                                     client->packet_length, from, &destination,
        !          2161:                                     NULL);
        !          2162:                if (result < 0) {
        !          2163:                        log_error("%s:%d: Failed to send %d byte long packet "
        !          2164:                                  "over %s interface.", MDL,
        !          2165:                                  client->packet_length,
        !          2166:                                  fallback_interface->name);
        !          2167:                }
        !          2168:         }
        !          2169:        else {
1.1       misho    2170:                /* Send out a packet. */
1.1.1.1 ! misho    2171:                result = send_packet(client->interface, NULL, &client->packet,
        !          2172:                                     client->packet_length, from, &destination,
        !          2173:                                     NULL);
        !          2174:                if (result < 0) {
        !          2175:                        log_error("%s:%d: Failed to send %d byte long packet"
        !          2176:                                  " over %s interface.", MDL,
        !          2177:                                  client->packet_length,
        !          2178:                                  client->interface->name);
        !          2179:                }
        !          2180:         }
1.1       misho    2181: 
                   2182:        tv.tv_sec = cur_tv.tv_sec + client->interval;
                   2183:        tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
                   2184:                        random() % 1000000 : cur_tv.tv_usec;
                   2185:        add_timeout(&tv, send_request, client, 0, 0);
                   2186: }
                   2187: 
                   2188: void send_decline (cpp)
                   2189:        void *cpp;
                   2190: {
                   2191:        struct client_state *client = cpp;
                   2192: 
                   2193:        int result;
                   2194: 
                   2195:        log_info ("DHCPDECLINE on %s to %s port %d",
1.1.1.1 ! misho    2196:              client->name ? client->name : client->interface->name,
        !          2197:              inet_ntoa(sockaddr_broadcast.sin_addr),
        !          2198:              ntohs(sockaddr_broadcast.sin_port));
1.1       misho    2199: 
                   2200:        /* Send out a packet. */
1.1.1.1 ! misho    2201:        result = send_packet(client->interface, NULL, &client->packet,
        !          2202:                             client->packet_length, inaddr_any,
        !          2203:                             &sockaddr_broadcast, NULL);
        !          2204:        if (result < 0) {
        !          2205:                log_error("%s:%d: Failed to send %d byte long packet over %s"
        !          2206:                          " interface.", MDL, client->packet_length,
        !          2207:                          client->interface->name);
        !          2208:        }
1.1       misho    2209: }
                   2210: 
                   2211: void send_release (cpp)
                   2212:        void *cpp;
                   2213: {
                   2214:        struct client_state *client = cpp;
                   2215: 
                   2216:        int result;
                   2217:        struct sockaddr_in destination;
                   2218:        struct in_addr from;
                   2219: 
                   2220:        memcpy (&from, client -> active -> address.iabuf,
                   2221:                sizeof from);
                   2222:        memcpy (&destination.sin_addr.s_addr,
                   2223:                client -> destination.iabuf,
                   2224:                sizeof destination.sin_addr.s_addr);
                   2225:        destination.sin_port = remote_port;
                   2226:        destination.sin_family = AF_INET;
                   2227: #ifdef HAVE_SA_LEN
                   2228:        destination.sin_len = sizeof destination;
                   2229: #endif
                   2230: 
                   2231:        /* Set the lease to end now, so that we don't accidentally
                   2232:           reuse it if we restart before the old expiry time. */
                   2233:        client -> active -> expiry =
                   2234:                client -> active -> renewal =
                   2235:                client -> active -> rebind = cur_time;
                   2236:        if (!write_client_lease (client, client -> active, 1, 1)) {
                   2237:                log_error ("Can't release lease: lease write failed.");
                   2238:                return;
                   2239:        }
                   2240: 
                   2241:        log_info ("DHCPRELEASE on %s to %s port %d",
                   2242:              client -> name ? client -> name : client -> interface -> name,
                   2243:              inet_ntoa (destination.sin_addr),
                   2244:              ntohs (destination.sin_port));
                   2245: 
1.1.1.1 ! misho    2246:        if (fallback_interface) {
        !          2247:                result = send_packet(fallback_interface, NULL, &client->packet,
        !          2248:                                      client->packet_length, from, &destination,
        !          2249:                                      NULL);
        !          2250:                if (result < 0) {
        !          2251:                        log_error("%s:%d: Failed to send %d byte long packet"
        !          2252:                                  " over %s interface.", MDL,
        !          2253:                                  client->packet_length,
        !          2254:                                  fallback_interface->name);
        !          2255:                }
        !          2256:         } else {
1.1       misho    2257:                /* Send out a packet. */
1.1.1.1 ! misho    2258:                result = send_packet(client->interface, NULL, &client->packet,
        !          2259:                                      client->packet_length, from, &destination,
        !          2260:                                      NULL);
        !          2261:                if (result < 0) {
        !          2262:                        log_error ("%s:%d: Failed to send %d byte long packet"
        !          2263:                                   " over %s interface.", MDL,
        !          2264:                                   client->packet_length,
        !          2265:                                   client->interface->name);
        !          2266:                }
        !          2267: 
        !          2268:         }
1.1       misho    2269: }
                   2270: 
                   2271: void
                   2272: make_client_options(struct client_state *client, struct client_lease *lease,
                   2273:                    u_int8_t *type, struct option_cache *sid,
                   2274:                    struct iaddr *rip, struct option **prl,
                   2275:                    struct option_state **op)
                   2276: {
                   2277:        unsigned i;
                   2278:        struct option_cache *oc;
                   2279:        struct option *option = NULL;
                   2280:        struct buffer *bp = (struct buffer *)0;
                   2281: 
                   2282:        /* If there are any leftover options, get rid of them. */
                   2283:        if (*op)
                   2284:                option_state_dereference (op, MDL);
                   2285: 
                   2286:        /* Allocate space for options. */
                   2287:        option_state_allocate (op, MDL);
                   2288: 
                   2289:        /* Send the server identifier if provided. */
                   2290:        if (sid)
                   2291:                save_option (&dhcp_universe, *op, sid);
                   2292: 
                   2293:        oc = (struct option_cache *)0;
                   2294: 
                   2295:        /* Send the requested address if provided. */
                   2296:        if (rip) {
                   2297:                client -> requested_address = *rip;
                   2298:                i = DHO_DHCP_REQUESTED_ADDRESS;
                   2299:                if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
                   2300:                                              &i, 0, MDL) &&
                   2301:                      make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
                   2302:                                              option, MDL)))
                   2303:                        log_error ("can't make requested address cache.");
                   2304:                else {
                   2305:                        save_option (&dhcp_universe, *op, oc);
                   2306:                        option_cache_dereference (&oc, MDL);
                   2307:                }
                   2308:                option_dereference(&option, MDL);
                   2309:        } else {
                   2310:                client -> requested_address.len = 0;
                   2311:        }
                   2312: 
                   2313:        i = DHO_DHCP_MESSAGE_TYPE;
                   2314:        if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
                   2315:                                      MDL) &&
                   2316:              make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
                   2317:                log_error ("can't make message type.");
                   2318:        else {
                   2319:                save_option (&dhcp_universe, *op, oc);
                   2320:                option_cache_dereference (&oc, MDL);
                   2321:        }
                   2322:        option_dereference(&option, MDL);
                   2323: 
                   2324:        if (prl) {
                   2325:                int len;
                   2326: 
                   2327:                /* Probe the length of the list. */
                   2328:                len = 0;
                   2329:                for (i = 0 ; prl[i] != NULL ; i++)
                   2330:                        if (prl[i]->universe == &dhcp_universe)
                   2331:                                len++;
                   2332: 
                   2333:                if (!buffer_allocate (&bp, len, MDL))
                   2334:                        log_error ("can't make parameter list buffer.");
                   2335:                else {
                   2336:                        unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
                   2337: 
                   2338:                        len = 0;
                   2339:                        for (i = 0 ; prl[i] != NULL ; i++)
                   2340:                                if (prl[i]->universe == &dhcp_universe)
                   2341:                                        bp->data[len++] = prl[i]->code;
                   2342: 
                   2343:                        if (!(option_code_hash_lookup(&option,
                   2344:                                                      dhcp_universe.code_hash,
                   2345:                                                      &code, 0, MDL) &&
                   2346:                              make_const_option_cache(&oc, &bp, NULL, len,
                   2347:                                                      option, MDL)))
                   2348:                                log_error ("can't make option cache");
                   2349:                        else {
                   2350:                                save_option (&dhcp_universe, *op, oc);
                   2351:                                option_cache_dereference (&oc, MDL);
                   2352:                        }
                   2353:                        option_dereference(&option, MDL);
                   2354:                }
                   2355:        }
                   2356: 
                   2357:        /* Run statements that need to be run on transmission. */
                   2358:        if (client -> config -> on_transmission)
                   2359:                execute_statements_in_scope
                   2360:                        ((struct binding_value **)0,
                   2361:                         (struct packet *)0, (struct lease *)0, client,
                   2362:                         (lease ? lease -> options : (struct option_state *)0),
                   2363:                         *op, &global_scope,
                   2364:                         client -> config -> on_transmission,
                   2365:                         (struct group *)0);
                   2366: }
                   2367: 
                   2368: void make_discover (client, lease)
                   2369:        struct client_state *client;
                   2370:        struct client_lease *lease;
                   2371: {
                   2372:        unsigned char discover = DHCPDISCOVER;
                   2373:        struct option_state *options = (struct option_state *)0;
                   2374: 
                   2375:        memset (&client -> packet, 0, sizeof (client -> packet));
                   2376: 
                   2377:        make_client_options (client,
                   2378:                             lease, &discover, (struct option_cache *)0,
                   2379:                             lease ? &lease -> address : (struct iaddr *)0,
                   2380:                             client -> config -> requested_options,
                   2381:                             &options);
                   2382: 
                   2383:        /* Set up the option buffer... */
                   2384:        client -> packet_length =
                   2385:                cons_options ((struct packet *)0, &client -> packet,
                   2386:                              (struct lease *)0, client,
                   2387:                              /* maximum packet size */1500,
                   2388:                              (struct option_state *)0,
                   2389:                              options,
                   2390:                              /* scope */ &global_scope,
                   2391:                              /* overload */ 0,
                   2392:                              /* terminate */0,
                   2393:                              /* bootpp    */0,
                   2394:                              (struct data_string *)0,
                   2395:                              client -> config -> vendor_space_name);
                   2396: 
                   2397:        option_state_dereference (&options, MDL);
                   2398:        if (client -> packet_length < BOOTP_MIN_LEN)
                   2399:                client -> packet_length = BOOTP_MIN_LEN;
                   2400: 
                   2401:        client -> packet.op = BOOTREQUEST;
                   2402:        client -> packet.htype = client -> interface -> hw_address.hbuf [0];
                   2403:        client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
                   2404:        client -> packet.hops = 0;
                   2405:        client -> packet.xid = random ();
                   2406:        client -> packet.secs = 0; /* filled in by send_discover. */
                   2407: 
                   2408:        if (can_receive_unicast_unconfigured (client -> interface))
                   2409:                client -> packet.flags = 0;
                   2410:        else
                   2411:                client -> packet.flags = htons (BOOTP_BROADCAST);
                   2412: 
                   2413:        memset (&(client -> packet.ciaddr),
                   2414:                0, sizeof client -> packet.ciaddr);
                   2415:        memset (&(client -> packet.yiaddr),
                   2416:                0, sizeof client -> packet.yiaddr);
                   2417:        memset (&(client -> packet.siaddr),
                   2418:                0, sizeof client -> packet.siaddr);
                   2419:        client -> packet.giaddr = giaddr;
                   2420:        if (client -> interface -> hw_address.hlen > 0)
                   2421:            memcpy (client -> packet.chaddr,
                   2422:                    &client -> interface -> hw_address.hbuf [1],
                   2423:                    (unsigned)(client -> interface -> hw_address.hlen - 1));
                   2424: 
                   2425: #ifdef DEBUG_PACKET
                   2426:        dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
                   2427: #endif
                   2428: }
                   2429: 
                   2430: 
                   2431: void make_request (client, lease)
                   2432:        struct client_state *client;
                   2433:        struct client_lease *lease;
                   2434: {
                   2435:        unsigned char request = DHCPREQUEST;
                   2436:        struct option_cache *oc;
                   2437: 
                   2438:        memset (&client -> packet, 0, sizeof (client -> packet));
                   2439: 
                   2440:        if (client -> state == S_REQUESTING)
                   2441:                oc = lookup_option (&dhcp_universe, lease -> options,
                   2442:                                    DHO_DHCP_SERVER_IDENTIFIER);
                   2443:        else
                   2444:                oc = (struct option_cache *)0;
                   2445: 
                   2446:        if (client -> sent_options)
                   2447:                option_state_dereference (&client -> sent_options, MDL);
                   2448: 
                   2449:        make_client_options (client, lease, &request, oc,
                   2450:                             ((client -> state == S_REQUESTING ||
                   2451:                               client -> state == S_REBOOTING)
                   2452:                              ? &lease -> address
                   2453:                              : (struct iaddr *)0),
                   2454:                             client -> config -> requested_options,
                   2455:                             &client -> sent_options);
                   2456: 
                   2457:        /* Set up the option buffer... */
                   2458:        client -> packet_length =
                   2459:                cons_options ((struct packet *)0, &client -> packet,
                   2460:                              (struct lease *)0, client,
                   2461:                              /* maximum packet size */1500,
                   2462:                              (struct option_state *)0,
                   2463:                              client -> sent_options,
                   2464:                              /* scope */ &global_scope,
                   2465:                              /* overload */ 0,
                   2466:                              /* terminate */0,
                   2467:                              /* bootpp    */0,
                   2468:                              (struct data_string *)0,
                   2469:                              client -> config -> vendor_space_name);
                   2470: 
                   2471:        if (client -> packet_length < BOOTP_MIN_LEN)
                   2472:                client -> packet_length = BOOTP_MIN_LEN;
                   2473: 
                   2474:        client -> packet.op = BOOTREQUEST;
                   2475:        client -> packet.htype = client -> interface -> hw_address.hbuf [0];
                   2476:        client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
                   2477:        client -> packet.hops = 0;
                   2478:        client -> packet.xid = client -> xid;
                   2479:        client -> packet.secs = 0; /* Filled in by send_request. */
                   2480: 
                   2481:        /* If we own the address we're requesting, put it in ciaddr;
                   2482:           otherwise set ciaddr to zero. */
                   2483:        if (client -> state == S_BOUND ||
                   2484:            client -> state == S_RENEWING ||
                   2485:            client -> state == S_REBINDING) {
                   2486:                memcpy (&client -> packet.ciaddr,
                   2487:                        lease -> address.iabuf, lease -> address.len);
                   2488:                client -> packet.flags = 0;
                   2489:        } else {
                   2490:                memset (&client -> packet.ciaddr, 0,
                   2491:                        sizeof client -> packet.ciaddr);
                   2492:                if (can_receive_unicast_unconfigured (client -> interface))
                   2493:                        client -> packet.flags = 0;
                   2494:                else
                   2495:                        client -> packet.flags = htons (BOOTP_BROADCAST);
                   2496:        }
                   2497: 
                   2498:        memset (&client -> packet.yiaddr, 0,
                   2499:                sizeof client -> packet.yiaddr);
                   2500:        memset (&client -> packet.siaddr, 0,
                   2501:                sizeof client -> packet.siaddr);
                   2502:        if (client -> state != S_BOUND &&
                   2503:            client -> state != S_RENEWING)
                   2504:                client -> packet.giaddr = giaddr;
                   2505:        else
                   2506:                memset (&client -> packet.giaddr, 0,
                   2507:                        sizeof client -> packet.giaddr);
                   2508:        if (client -> interface -> hw_address.hlen > 0)
                   2509:            memcpy (client -> packet.chaddr,
                   2510:                    &client -> interface -> hw_address.hbuf [1],
                   2511:                    (unsigned)(client -> interface -> hw_address.hlen - 1));
                   2512: 
                   2513: #ifdef DEBUG_PACKET
                   2514:        dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
                   2515: #endif
                   2516: }
                   2517: 
                   2518: void make_decline (client, lease)
                   2519:        struct client_state *client;
                   2520:        struct client_lease *lease;
                   2521: {
                   2522:        unsigned char decline = DHCPDECLINE;
                   2523:        struct option_cache *oc;
                   2524: 
                   2525:        struct option_state *options = (struct option_state *)0;
                   2526: 
                   2527:        /* Create the options cache. */
                   2528:        oc = lookup_option (&dhcp_universe, lease -> options,
                   2529:                            DHO_DHCP_SERVER_IDENTIFIER);
                   2530:        make_client_options(client, lease, &decline, oc, &lease->address,
                   2531:                            NULL, &options);
                   2532: 
                   2533:        /* Consume the options cache into the option buffer. */
                   2534:        memset (&client -> packet, 0, sizeof (client -> packet));
                   2535:        client -> packet_length =
                   2536:                cons_options ((struct packet *)0, &client -> packet,
                   2537:                              (struct lease *)0, client, 0,
                   2538:                              (struct option_state *)0, options,
                   2539:                              &global_scope, 0, 0, 0, (struct data_string *)0,
                   2540:                              client -> config -> vendor_space_name);
                   2541: 
                   2542:        /* Destroy the options cache. */
                   2543:        option_state_dereference (&options, MDL);
                   2544: 
                   2545:        if (client -> packet_length < BOOTP_MIN_LEN)
                   2546:                client -> packet_length = BOOTP_MIN_LEN;
                   2547: 
                   2548:        client -> packet.op = BOOTREQUEST;
                   2549:        client -> packet.htype = client -> interface -> hw_address.hbuf [0];
                   2550:        client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
                   2551:        client -> packet.hops = 0;
                   2552:        client -> packet.xid = client -> xid;
                   2553:        client -> packet.secs = 0; /* Filled in by send_request. */
                   2554:        if (can_receive_unicast_unconfigured (client -> interface))
                   2555:                client -> packet.flags = 0;
                   2556:        else
                   2557:                client -> packet.flags = htons (BOOTP_BROADCAST);
                   2558: 
                   2559:        /* ciaddr must always be zero. */
                   2560:        memset (&client -> packet.ciaddr, 0,
                   2561:                sizeof client -> packet.ciaddr);
                   2562:        memset (&client -> packet.yiaddr, 0,
                   2563:                sizeof client -> packet.yiaddr);
                   2564:        memset (&client -> packet.siaddr, 0,
                   2565:                sizeof client -> packet.siaddr);
                   2566:        client -> packet.giaddr = giaddr;
                   2567:        memcpy (client -> packet.chaddr,
                   2568:                &client -> interface -> hw_address.hbuf [1],
                   2569:                client -> interface -> hw_address.hlen);
                   2570: 
                   2571: #ifdef DEBUG_PACKET
                   2572:        dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
                   2573: #endif
                   2574: }
                   2575: 
                   2576: void make_release (client, lease)
                   2577:        struct client_state *client;
                   2578:        struct client_lease *lease;
                   2579: {
                   2580:        unsigned char request = DHCPRELEASE;
                   2581:        struct option_cache *oc;
                   2582: 
                   2583:        struct option_state *options = (struct option_state *)0;
                   2584: 
                   2585:        memset (&client -> packet, 0, sizeof (client -> packet));
                   2586: 
                   2587:        oc = lookup_option (&dhcp_universe, lease -> options,
                   2588:                            DHO_DHCP_SERVER_IDENTIFIER);
                   2589:        make_client_options(client, lease, &request, oc, NULL, NULL, &options);
                   2590: 
                   2591:        /* Set up the option buffer... */
                   2592:        client -> packet_length =
                   2593:                cons_options ((struct packet *)0, &client -> packet,
                   2594:                              (struct lease *)0, client,
                   2595:                              /* maximum packet size */1500,
                   2596:                              (struct option_state *)0,
                   2597:                              options,
                   2598:                              /* scope */ &global_scope,
                   2599:                              /* overload */ 0,
                   2600:                              /* terminate */0,
                   2601:                              /* bootpp    */0,
                   2602:                              (struct data_string *)0,
                   2603:                              client -> config -> vendor_space_name);
                   2604: 
                   2605:        if (client -> packet_length < BOOTP_MIN_LEN)
                   2606:                client -> packet_length = BOOTP_MIN_LEN;
                   2607:        option_state_dereference (&options, MDL);
                   2608: 
                   2609:        client -> packet.op = BOOTREQUEST;
                   2610:        client -> packet.htype = client -> interface -> hw_address.hbuf [0];
                   2611:        client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
                   2612:        client -> packet.hops = 0;
                   2613:        client -> packet.xid = random ();
                   2614:        client -> packet.secs = 0;
                   2615:        client -> packet.flags = 0;
                   2616:        memcpy (&client -> packet.ciaddr,
                   2617:                lease -> address.iabuf, lease -> address.len);
                   2618:        memset (&client -> packet.yiaddr, 0,
                   2619:                sizeof client -> packet.yiaddr);
                   2620:        memset (&client -> packet.siaddr, 0,
                   2621:                sizeof client -> packet.siaddr);
                   2622:        client -> packet.giaddr = giaddr;
                   2623:        memcpy (client -> packet.chaddr,
                   2624:                &client -> interface -> hw_address.hbuf [1],
                   2625:                client -> interface -> hw_address.hlen);
                   2626: 
                   2627: #ifdef DEBUG_PACKET
                   2628:        dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
                   2629: #endif
                   2630: }
                   2631: 
                   2632: void destroy_client_lease (lease)
                   2633:        struct client_lease *lease;
                   2634: {
                   2635:        if (lease -> server_name)
                   2636:                dfree (lease -> server_name, MDL);
                   2637:        if (lease -> filename)
                   2638:                dfree (lease -> filename, MDL);
                   2639:        option_state_dereference (&lease -> options, MDL);
                   2640:        free_client_lease (lease, MDL);
                   2641: }
                   2642: 
                   2643: FILE *leaseFile = NULL;
                   2644: int leases_written = 0;
                   2645: 
                   2646: void rewrite_client_leases ()
                   2647: {
                   2648:        struct interface_info *ip;
                   2649:        struct client_state *client;
                   2650:        struct client_lease *lp;
                   2651: 
                   2652:        if (leaseFile != NULL)
                   2653:                fclose (leaseFile);
                   2654:        leaseFile = fopen (path_dhclient_db, "w");
                   2655:        if (leaseFile == NULL) {
                   2656:                log_error ("can't create %s: %m", path_dhclient_db);
                   2657:                return;
                   2658:        }
                   2659: 
                   2660:        /* If there is a default duid, write it out. */
                   2661:        if (default_duid.len != 0)
                   2662:                write_duid(&default_duid);
                   2663: 
                   2664:        /* Write out all the leases attached to configured interfaces that
                   2665:           we know about. */
                   2666:        for (ip = interfaces; ip; ip = ip -> next) {
                   2667:                for (client = ip -> client; client; client = client -> next) {
                   2668:                        for (lp = client -> leases; lp; lp = lp -> next) {
                   2669:                                write_client_lease (client, lp, 1, 0);
                   2670:                        }
                   2671:                        if (client -> active)
                   2672:                                write_client_lease (client,
                   2673:                                                    client -> active, 1, 0);
                   2674: 
                   2675:                        if (client->active_lease != NULL)
                   2676:                                write_client6_lease(client,
                   2677:                                                    client->active_lease,
                   2678:                                                    1, 0);
                   2679: 
                   2680:                        /* Reset last_write after rewrites. */
                   2681:                        client->last_write = 0;
                   2682:                }
                   2683:        }
                   2684: 
                   2685:        /* Write out any leases that are attached to interfaces that aren't
                   2686:           currently configured. */
                   2687:        for (ip = dummy_interfaces; ip; ip = ip -> next) {
                   2688:                for (client = ip -> client; client; client = client -> next) {
                   2689:                        for (lp = client -> leases; lp; lp = lp -> next) {
                   2690:                                write_client_lease (client, lp, 1, 0);
                   2691:                        }
                   2692:                        if (client -> active)
                   2693:                                write_client_lease (client,
                   2694:                                                    client -> active, 1, 0);
                   2695: 
                   2696:                        if (client->active_lease != NULL)
                   2697:                                write_client6_lease(client,
                   2698:                                                    client->active_lease,
                   2699:                                                    1, 0);
                   2700: 
                   2701:                        /* Reset last_write after rewrites. */
                   2702:                        client->last_write = 0;
                   2703:                }
                   2704:        }
                   2705:        fflush (leaseFile);
                   2706: }
                   2707: 
                   2708: void write_lease_option (struct option_cache *oc,
                   2709:                         struct packet *packet, struct lease *lease,
                   2710:                         struct client_state *client_state,
                   2711:                         struct option_state *in_options,
                   2712:                         struct option_state *cfg_options,
                   2713:                         struct binding_scope **scope,
                   2714:                         struct universe *u, void *stuff)
                   2715: {
                   2716:        const char *name, *dot;
                   2717:        struct data_string ds;
                   2718:        char *preamble = stuff;
                   2719: 
                   2720:        memset (&ds, 0, sizeof ds);
                   2721: 
                   2722:        if (u != &dhcp_universe) {
                   2723:                name = u -> name;
                   2724:                dot = ".";
                   2725:        } else {
                   2726:                name = "";
                   2727:                dot = "";
                   2728:        }
                   2729:        if (evaluate_option_cache (&ds, packet, lease, client_state,
                   2730:                                   in_options, cfg_options, scope, oc, MDL)) {
1.1.1.1 ! misho    2731:                /* The option name */
        !          2732:                fprintf(leaseFile, "%soption %s%s%s", preamble,
        !          2733:                        name, dot, oc->option->name);
        !          2734: 
        !          2735:                /* The option value if there is one */
        !          2736:                if ((oc->option->format == NULL) ||
        !          2737:                    (oc->option->format[0] != 'Z')) {
        !          2738:                        fprintf(leaseFile, " %s",
        !          2739:                                pretty_print_option(oc->option, ds.data,
        !          2740:                                                    ds.len, 1, 1));
        !          2741:                }
        !          2742: 
        !          2743:                /* The closing semi-colon and newline */
        !          2744:                fprintf(leaseFile, ";\n");
        !          2745: 
1.1       misho    2746:                data_string_forget (&ds, MDL);
                   2747:        }
                   2748: }
                   2749: 
                   2750: /* Write an option cache to the lease store. */
                   2751: static void
                   2752: write_options(struct client_state *client, struct option_state *options,
                   2753:              const char *preamble)
                   2754: {
                   2755:        int i;
                   2756: 
                   2757:        for (i = 0; i < options->universe_count; i++) {
                   2758:                option_space_foreach(NULL, NULL, client, NULL, options,
                   2759:                                     &global_scope, universes[i],
                   2760:                                     (char *)preamble, write_lease_option);
                   2761:        }
                   2762: }
                   2763: 
                   2764: /* Write the default DUID to the lease store. */
                   2765: static isc_result_t
                   2766: write_duid(struct data_string *duid)
                   2767: {
                   2768:        char *str;
                   2769:        int stat;
                   2770: 
                   2771:        if ((duid == NULL) || (duid->len <= 2))
                   2772:                return ISC_R_INVALIDARG;
                   2773: 
                   2774:        if (leaseFile == NULL) {        /* XXX? */
                   2775:                leaseFile = fopen(path_dhclient_db, "w");
                   2776:                if (leaseFile == NULL) {
                   2777:                        log_error("can't create %s: %m", path_dhclient_db);
                   2778:                        return ISC_R_IOERROR;
                   2779:                }
                   2780:        }
                   2781: 
                   2782:        /* It would make more sense to write this as a hex string,
                   2783:         * but our function to do that (print_hex_n) uses a fixed
                   2784:         * length buffer...and we can't guarantee a duid would be
                   2785:         * less than the fixed length.
                   2786:         */
                   2787:        str = quotify_buf(duid->data, duid->len, MDL);
                   2788:        if (str == NULL)
                   2789:                return ISC_R_NOMEMORY;
                   2790: 
                   2791:        stat = fprintf(leaseFile, "default-duid \"%s\";\n", str);
                   2792:        dfree(str, MDL);
                   2793:        if (stat <= 0)
                   2794:                return ISC_R_IOERROR;
                   2795: 
                   2796:        if (fflush(leaseFile) != 0)
                   2797:                return ISC_R_IOERROR;
                   2798: 
                   2799:        return ISC_R_SUCCESS;
                   2800: }
                   2801: 
                   2802: /* Write a DHCPv6 lease to the store. */
                   2803: isc_result_t
                   2804: write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
                   2805:                    int rewrite, int sync)
                   2806: {
                   2807:        struct dhc6_ia *ia;
                   2808:        struct dhc6_addr *addr;
                   2809:        int stat;
                   2810:        const char *ianame;
                   2811: 
                   2812:        /* This should include the current lease. */
                   2813:        if (!rewrite && (leases_written++ > 20)) {
                   2814:                rewrite_client_leases();
                   2815:                leases_written = 0;
                   2816:                return ISC_R_SUCCESS;
                   2817:        }
                   2818: 
                   2819:        if (client == NULL || lease == NULL)
                   2820:                return ISC_R_INVALIDARG;
                   2821: 
                   2822:        if (leaseFile == NULL) {        /* XXX? */
                   2823:                leaseFile = fopen(path_dhclient_db, "w");
                   2824:                if (leaseFile == NULL) {
                   2825:                        log_error("can't create %s: %m", path_dhclient_db);
                   2826:                        return ISC_R_IOERROR;
                   2827:                }
                   2828:        }
                   2829: 
                   2830:        stat = fprintf(leaseFile, "lease6 {\n");
                   2831:        if (stat <= 0)
                   2832:                return ISC_R_IOERROR;
                   2833: 
                   2834:        stat = fprintf(leaseFile, "  interface \"%s\";\n",
                   2835:                       client->interface->name);
                   2836:        if (stat <= 0)
                   2837:                return ISC_R_IOERROR;
                   2838: 
                   2839:        for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
                   2840:                switch (ia->ia_type) {
                   2841:                        case D6O_IA_NA:
                   2842:                        default:
                   2843:                                ianame = "ia-na";
                   2844:                                break;
                   2845:                        case D6O_IA_TA:
                   2846:                                ianame = "ia-ta";
                   2847:                                break;
                   2848:                        case D6O_IA_PD:
                   2849:                                ianame = "ia-pd";
                   2850:                                break;
                   2851:                }
                   2852:                stat = fprintf(leaseFile, "  %s %s {\n",
                   2853:                               ianame, print_hex_1(4, ia->iaid, 12));
                   2854:                if (stat <= 0)
                   2855:                        return ISC_R_IOERROR;
                   2856: 
                   2857:                if (ia->ia_type != D6O_IA_TA)
                   2858:                        stat = fprintf(leaseFile, "    starts %d;\n"
                   2859:                                                  "    renew %u;\n"
                   2860:                                                  "    rebind %u;\n",
                   2861:                                       (int)ia->starts, ia->renew, ia->rebind);
                   2862:                else
                   2863:                        stat = fprintf(leaseFile, "    starts %d;\n",
                   2864:                                       (int)ia->starts);
                   2865:                if (stat <= 0)
                   2866:                        return ISC_R_IOERROR;
                   2867: 
                   2868:                for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
                   2869:                        if (ia->ia_type != D6O_IA_PD)
                   2870:                                stat = fprintf(leaseFile,
                   2871:                                               "    iaaddr %s {\n",
                   2872:                                               piaddr(addr->address));
                   2873:                        else
                   2874:                                stat = fprintf(leaseFile,
                   2875:                                               "    iaprefix %s/%d {\n",
                   2876:                                               piaddr(addr->address),
                   2877:                                               (int)addr->plen);
                   2878:                        if (stat <= 0)
                   2879:                                return ISC_R_IOERROR;
                   2880: 
                   2881:                        stat = fprintf(leaseFile, "      starts %d;\n"
                   2882:                                                  "      preferred-life %u;\n"
                   2883:                                                  "      max-life %u;\n",
                   2884:                                       (int)addr->starts, addr->preferred_life,
                   2885:                                       addr->max_life);
                   2886:                        if (stat <= 0)
                   2887:                                return ISC_R_IOERROR;
                   2888: 
                   2889:                        if (addr->options != NULL)
                   2890:                                write_options(client, addr->options, "      ");
                   2891: 
                   2892:                        stat = fprintf(leaseFile, "    }\n");
                   2893:                        if (stat <= 0)
                   2894:                                return ISC_R_IOERROR;
                   2895:                }
                   2896: 
                   2897:                if (ia->options != NULL)
                   2898:                        write_options(client, ia->options, "    ");
                   2899: 
                   2900:                stat = fprintf(leaseFile, "  }\n");
                   2901:                if (stat <= 0)
                   2902:                        return ISC_R_IOERROR;
                   2903:        }
                   2904: 
                   2905:        if (lease->released) {
                   2906:                stat = fprintf(leaseFile, "  released;\n");
                   2907:                if (stat <= 0)
                   2908:                        return ISC_R_IOERROR;
                   2909:        }
                   2910: 
                   2911:        if (lease->options != NULL)
                   2912:                write_options(client, lease->options, "  ");
                   2913: 
                   2914:        stat = fprintf(leaseFile, "}\n");
                   2915:        if (stat <= 0)
                   2916:                return ISC_R_IOERROR;
                   2917: 
                   2918:        if (fflush(leaseFile) != 0)
                   2919:                return ISC_R_IOERROR;
                   2920: 
                   2921:        if (sync) {
                   2922:                if (fsync(fileno(leaseFile)) < 0) {
                   2923:                        log_error("write_client_lease: fsync(): %m");
                   2924:                        return ISC_R_IOERROR;
                   2925:                }
                   2926:        }
                   2927: 
                   2928:        return ISC_R_SUCCESS;
                   2929: }
                   2930: 
                   2931: int write_client_lease (client, lease, rewrite, makesure)
                   2932:        struct client_state *client;
                   2933:        struct client_lease *lease;
                   2934:        int rewrite;
                   2935:        int makesure;
                   2936: {
                   2937:        struct data_string ds;
                   2938:        int errors = 0;
                   2939:        char *s;
                   2940:        const char *tval;
                   2941: 
                   2942:        if (!rewrite) {
                   2943:                if (leases_written++ > 20) {
                   2944:                        rewrite_client_leases ();
                   2945:                        leases_written = 0;
                   2946:                }
                   2947:        }
                   2948: 
                   2949:        /* If the lease came from the config file, we don't need to stash
                   2950:           a copy in the lease database. */
                   2951:        if (lease -> is_static)
                   2952:                return 1;
                   2953: 
                   2954:        if (leaseFile == NULL) {        /* XXX */
                   2955:                leaseFile = fopen (path_dhclient_db, "w");
                   2956:                if (leaseFile == NULL) {
                   2957:                        log_error ("can't create %s: %m", path_dhclient_db);
                   2958:                        return 0;
                   2959:                }
                   2960:        }
                   2961: 
                   2962:        errno = 0;
                   2963:        fprintf (leaseFile, "lease {\n");
                   2964:        if (lease -> is_bootp) {
                   2965:                fprintf (leaseFile, "  bootp;\n");
                   2966:                if (errno) {
                   2967:                        ++errors;
                   2968:                        errno = 0;
                   2969:                }
                   2970:        }
                   2971:        fprintf (leaseFile, "  interface \"%s\";\n",
                   2972:                 client -> interface -> name);
                   2973:        if (errno) {
                   2974:                ++errors;
                   2975:                errno = 0;
                   2976:        }
                   2977:        if (client -> name) {
                   2978:                fprintf (leaseFile, "  name \"%s\";\n", client -> name);
                   2979:                if (errno) {
                   2980:                        ++errors;
                   2981:                        errno = 0;
                   2982:                }
                   2983:        }
                   2984:        fprintf (leaseFile, "  fixed-address %s;\n",
                   2985:                 piaddr (lease -> address));
                   2986:        if (errno) {
                   2987:                ++errors;
                   2988:                errno = 0;
                   2989:        }
                   2990:        if (lease -> filename) {
                   2991:                s = quotify_string (lease -> filename, MDL);
                   2992:                if (s) {
                   2993:                        fprintf (leaseFile, "  filename \"%s\";\n", s);
                   2994:                        if (errno) {
                   2995:                                ++errors;
                   2996:                                errno = 0;
                   2997:                        }
                   2998:                        dfree (s, MDL);
                   2999:                } else
                   3000:                        errors++;
                   3001: 
                   3002:        }
                   3003:        if (lease->server_name != NULL) {
                   3004:                s = quotify_string(lease->server_name, MDL);
                   3005:                if (s != NULL) {
                   3006:                        fprintf(leaseFile, "  server-name \"%s\";\n", s);
                   3007:                        if (errno) {
                   3008:                                ++errors;
                   3009:                                errno = 0;
                   3010:                        }
                   3011:                        dfree(s, MDL);
                   3012:                } else
                   3013:                        ++errors;
                   3014:        }
                   3015:        if (lease -> medium) {
                   3016:                s = quotify_string (lease -> medium -> string, MDL);
                   3017:                if (s) {
                   3018:                        fprintf (leaseFile, "  medium \"%s\";\n", s);
                   3019:                        if (errno) {
                   3020:                                ++errors;
                   3021:                                errno = 0;
                   3022:                        }
                   3023:                        dfree (s, MDL);
                   3024:                } else
                   3025:                        errors++;
                   3026:        }
                   3027:        if (errno != 0) {
                   3028:                errors++;
                   3029:                errno = 0;
                   3030:        }
                   3031: 
                   3032:        memset (&ds, 0, sizeof ds);
                   3033: 
                   3034:        write_options(client, lease->options, "  ");
                   3035: 
                   3036:        tval = print_time(lease->renewal);
                   3037:        if (tval == NULL ||
                   3038:            fprintf(leaseFile, "  renew %s\n", tval) < 0)
                   3039:                errors++;
                   3040: 
                   3041:        tval = print_time(lease->rebind);
                   3042:        if (tval == NULL ||
                   3043:            fprintf(leaseFile, "  rebind %s\n", tval) < 0)
                   3044:                errors++;
                   3045: 
                   3046:        tval = print_time(lease->expiry);
                   3047:        if (tval == NULL ||
                   3048:            fprintf(leaseFile, "  expire %s\n", tval) < 0)
                   3049:                errors++;
                   3050: 
                   3051:        if (fprintf(leaseFile, "}\n") < 0)
                   3052:                errors++;
                   3053: 
                   3054:        if (fflush(leaseFile) != 0)
                   3055:                errors++;
                   3056: 
                   3057:        client->last_write = cur_time;
                   3058: 
                   3059:        if (!errors && makesure) {
                   3060:                if (fsync (fileno (leaseFile)) < 0) {
                   3061:                        log_info ("write_client_lease: %m");
                   3062:                        return 0;
                   3063:                }
                   3064:        }
                   3065: 
                   3066:        return errors ? 0 : 1;
                   3067: }
                   3068: 
                   3069: /* Variables holding name of script and file pointer for writing to
                   3070:    script.   Needless to say, this is not reentrant - only one script
                   3071:    can be invoked at a time. */
                   3072: char scriptName [256];
                   3073: FILE *scriptFile;
                   3074: 
                   3075: void script_init (client, reason, medium)
                   3076:        struct client_state *client;
                   3077:        const char *reason;
                   3078:        struct string_list *medium;
                   3079: {
                   3080:        struct string_list *sl, *next;
                   3081: 
                   3082:        if (client) {
                   3083:                for (sl = client -> env; sl; sl = next) {
                   3084:                        next = sl -> next;
                   3085:                        dfree (sl, MDL);
                   3086:                }
                   3087:                client -> env = (struct string_list *)0;
                   3088:                client -> envc = 0;
                   3089: 
                   3090:                if (client -> interface) {
                   3091:                        client_envadd (client, "", "interface", "%s",
                   3092:                                       client -> interface -> name);
                   3093:                }
                   3094:                if (client -> name)
                   3095:                        client_envadd (client,
                   3096:                                       "", "client", "%s", client -> name);
                   3097:                if (medium)
                   3098:                        client_envadd (client,
                   3099:                                       "", "medium", "%s", medium -> string);
                   3100: 
                   3101:                client_envadd (client, "", "reason", "%s", reason);
                   3102:                client_envadd (client, "", "pid", "%ld", (long int)getpid ());
                   3103:        }
                   3104: }
                   3105: 
                   3106: void client_option_envadd (struct option_cache *oc,
                   3107:                           struct packet *packet, struct lease *lease,
                   3108:                           struct client_state *client_state,
                   3109:                           struct option_state *in_options,
                   3110:                           struct option_state *cfg_options,
                   3111:                           struct binding_scope **scope,
                   3112:                           struct universe *u, void *stuff)
                   3113: {
                   3114:        struct envadd_state *es = stuff;
                   3115:        struct data_string data;
                   3116:        memset (&data, 0, sizeof data);
                   3117: 
                   3118:        if (evaluate_option_cache (&data, packet, lease, client_state,
                   3119:                                   in_options, cfg_options, scope, oc, MDL)) {
                   3120:                if (data.len) {
                   3121:                        char name [256];
                   3122:                        if (dhcp_option_ev_name (name, sizeof name,
                   3123:                                                 oc->option)) {
                   3124:                                const char *value;
                   3125:                                value = pretty_print_option(oc->option,
                   3126:                                                            data.data,
                   3127:                                                            data.len, 0, 0);
                   3128:                                size_t length = strlen(value);
                   3129: 
                   3130:                                if (check_option_values(oc->option->universe,
                   3131:                                                        oc->option->code,
                   3132:                                                        value, length) == 0) {
                   3133:                                        client_envadd(es->client, es->prefix,
                   3134:                                                      name, "%s", value);
                   3135:                                } else {
                   3136:                                        log_error("suspect value in %s "
                   3137:                                                  "option - discarded",
                   3138:                                                  name);
                   3139:                                }
                   3140:                                data_string_forget (&data, MDL);
                   3141:                        }
                   3142:                }
                   3143:        }
                   3144: }
                   3145: 
                   3146: void script_write_params (client, prefix, lease)
                   3147:        struct client_state *client;
                   3148:        const char *prefix;
                   3149:        struct client_lease *lease;
                   3150: {
                   3151:        int i;
                   3152:        struct data_string data;
                   3153:        struct option_cache *oc;
                   3154:        struct envadd_state es;
                   3155: 
                   3156:        es.client = client;
                   3157:        es.prefix = prefix;
                   3158: 
                   3159:        client_envadd (client,
                   3160:                       prefix, "ip_address", "%s", piaddr (lease -> address));
                   3161: 
                   3162:        /* For the benefit of Linux (and operating systems which may
                   3163:           have similar needs), compute the network address based on
                   3164:           the supplied ip address and netmask, if provided.  Also
                   3165:           compute the broadcast address (the host address all ones
                   3166:           broadcast address, not the host address all zeroes
                   3167:           broadcast address). */
                   3168: 
                   3169:        memset (&data, 0, sizeof data);
                   3170:        oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
                   3171:        if (oc && evaluate_option_cache (&data, (struct packet *)0,
                   3172:                                         (struct lease *)0, client,
                   3173:                                         (struct option_state *)0,
                   3174:                                         lease -> options,
                   3175:                                         &global_scope, oc, MDL)) {
                   3176:                if (data.len > 3) {
                   3177:                        struct iaddr netmask, subnet, broadcast;
                   3178: 
                   3179:                        /*
                   3180:                         * No matter the length of the subnet-mask option,
                   3181:                         * use only the first four octets.  Note that
                   3182:                         * subnet-mask options longer than 4 octets are not
                   3183:                         * in conformance with RFC 2132, but servers with this
                   3184:                         * flaw do exist.
                   3185:                         */
                   3186:                        memcpy(netmask.iabuf, data.data, 4);
                   3187:                        netmask.len = 4;
                   3188:                        data_string_forget (&data, MDL);
                   3189: 
                   3190:                        subnet = subnet_number (lease -> address, netmask);
                   3191:                        if (subnet.len) {
                   3192:                            client_envadd (client, prefix, "network_number",
                   3193:                                           "%s", piaddr (subnet));
                   3194: 
                   3195:                            oc = lookup_option (&dhcp_universe,
                   3196:                                                lease -> options,
                   3197:                                                DHO_BROADCAST_ADDRESS);
                   3198:                            if (!oc ||
                   3199:                                !(evaluate_option_cache
                   3200:                                  (&data, (struct packet *)0,
                   3201:                                   (struct lease *)0, client,
                   3202:                                   (struct option_state *)0,
                   3203:                                   lease -> options,
                   3204:                                   &global_scope, oc, MDL))) {
                   3205:                                broadcast = broadcast_addr (subnet, netmask);
                   3206:                                if (broadcast.len) {
                   3207:                                    client_envadd (client,
                   3208:                                                   prefix, "broadcast_address",
                   3209:                                                   "%s", piaddr (broadcast));
                   3210:                                }
                   3211:                            }
                   3212:                        }
                   3213:                }
                   3214:                data_string_forget (&data, MDL);
                   3215:        }
                   3216: 
                   3217:        if (lease->filename) {
                   3218:                if (check_option_values(NULL, DHO_ROOT_PATH,
                   3219:                                        lease->filename,
                   3220:                                        strlen(lease->filename)) == 0) {
                   3221:                        client_envadd(client, prefix, "filename",
                   3222:                                      "%s", lease->filename);
                   3223:                } else {
                   3224:                        log_error("suspect value in %s "
                   3225:                                  "option - discarded",
                   3226:                                  lease->filename);
                   3227:                }
                   3228:        }
                   3229: 
                   3230:        if (lease->server_name) {
                   3231:                if (check_option_values(NULL, DHO_HOST_NAME,
                   3232:                                        lease->server_name,
                   3233:                                        strlen(lease->server_name)) == 0 ) {
                   3234:                        client_envadd (client, prefix, "server_name",
                   3235:                                       "%s", lease->server_name);
                   3236:                } else {
                   3237:                        log_error("suspect value in %s "
                   3238:                                  "option - discarded",
                   3239:                                  lease->server_name);
                   3240:                }
                   3241:        }
                   3242: 
                   3243:        for (i = 0; i < lease -> options -> universe_count; i++) {
                   3244:                option_space_foreach ((struct packet *)0, (struct lease *)0,
                   3245:                                      client, (struct option_state *)0,
                   3246:                                      lease -> options, &global_scope,
                   3247:                                      universes [i],
                   3248:                                      &es, client_option_envadd);
                   3249:        }
                   3250:        client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
                   3251: }
                   3252: 
                   3253: int script_go (client)
                   3254:        struct client_state *client;
                   3255: {
                   3256:        char *scriptName;
                   3257:        char *argv [2];
                   3258:        char **envp;
                   3259:        char reason [] = "REASON=NBI";
                   3260:        static char client_path [] = CLIENT_PATH;
                   3261:        int i;
                   3262:        struct string_list *sp, *next;
                   3263:        int pid, wpid, wstatus;
                   3264: 
                   3265:        if (client)
                   3266:                scriptName = client -> config -> script_name;
                   3267:        else
                   3268:                scriptName = top_level_config.script_name;
                   3269: 
                   3270:        envp = dmalloc (((client ? client -> envc : 2) +
                   3271:                         client_env_count + 2) * sizeof (char *), MDL);
                   3272:        if (!envp) {
                   3273:                log_error ("No memory for client script environment.");
                   3274:                return 0;
                   3275:        }
                   3276:        i = 0;
                   3277:        /* Copy out the environment specified on the command line,
                   3278:           if any. */
                   3279:        for (sp = client_env; sp; sp = sp -> next) {
                   3280:                envp [i++] = sp -> string;
                   3281:        }
                   3282:        /* Copy out the environment specified by dhclient. */
                   3283:        if (client) {
                   3284:                for (sp = client -> env; sp; sp = sp -> next) {
                   3285:                        envp [i++] = sp -> string;
                   3286:                }
                   3287:        } else {
                   3288:                envp [i++] = reason;
                   3289:        }
                   3290:        /* Set $PATH. */
                   3291:        envp [i++] = client_path;
                   3292:        envp [i] = (char *)0;
                   3293: 
                   3294:        argv [0] = scriptName;
                   3295:        argv [1] = (char *)0;
                   3296: 
                   3297:        pid = fork ();
                   3298:        if (pid < 0) {
                   3299:                log_error ("fork: %m");
                   3300:                wstatus = 0;
                   3301:        } else if (pid) {
                   3302:                do {
                   3303:                        wpid = wait (&wstatus);
                   3304:                } while (wpid != pid && wpid > 0);
                   3305:                if (wpid < 0) {
                   3306:                        log_error ("wait: %m");
                   3307:                        wstatus = 0;
                   3308:                }
                   3309:        } else {
                   3310:                /* We don't want to pass an open file descriptor for
                   3311:                 * dhclient.leases when executing dhclient-script.
                   3312:                 */
                   3313:                if (leaseFile != NULL)
                   3314:                        fclose(leaseFile);
                   3315:                execve (scriptName, argv, envp);
                   3316:                log_error ("execve (%s, ...): %m", scriptName);
                   3317:                exit (0);
                   3318:        }
                   3319: 
                   3320:        if (client) {
                   3321:                for (sp = client -> env; sp; sp = next) {
                   3322:                        next = sp -> next;
                   3323:                        dfree (sp, MDL);
                   3324:                }
                   3325:                client -> env = (struct string_list *)0;
                   3326:                client -> envc = 0;
                   3327:        }
                   3328:        dfree (envp, MDL);
                   3329:        gettimeofday(&cur_tv, NULL);
                   3330:        return (WIFEXITED (wstatus) ?
                   3331:                WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
                   3332: }
                   3333: 
                   3334: void client_envadd (struct client_state *client,
                   3335:                    const char *prefix, const char *name, const char *fmt, ...)
                   3336: {
                   3337:        char spbuf [1024];
                   3338:        char *s;
                   3339:        unsigned len;
                   3340:        struct string_list *val;
                   3341:        va_list list;
                   3342: 
                   3343:        va_start (list, fmt);
                   3344:        len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
                   3345:        va_end (list);
                   3346: 
                   3347:        val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
                   3348:                       len + sizeof *val, MDL);
                   3349:        if (!val)
                   3350:                return;
                   3351:        s = val -> string;
                   3352:        strcpy (s, prefix);
                   3353:        strcat (s, name);
                   3354:        s += strlen (s);
                   3355:        *s++ = '=';
                   3356:        if (len >= sizeof spbuf) {
                   3357:                va_start (list, fmt);
                   3358:                vsnprintf (s, len + 1, fmt, list);
                   3359:                va_end (list);
                   3360:        } else
                   3361:                strcpy (s, spbuf);
                   3362:        val -> next = client -> env;
                   3363:        client -> env = val;
                   3364:        client -> envc++;
                   3365: }
                   3366: 
                   3367: int dhcp_option_ev_name (buf, buflen, option)
                   3368:        char *buf;
                   3369:        size_t buflen;
                   3370:        struct option *option;
                   3371: {
                   3372:        int i, j;
                   3373:        const char *s;
                   3374: 
                   3375:        j = 0;
                   3376:        if (option -> universe != &dhcp_universe) {
                   3377:                s = option -> universe -> name;
                   3378:                i = 0;
                   3379:        } else {
                   3380:                s = option -> name;
                   3381:                i = 1;
                   3382:        }
                   3383: 
                   3384:        do {
                   3385:                while (*s) {
                   3386:                        if (j + 1 == buflen)
                   3387:                                return 0;
                   3388:                        if (*s == '-')
                   3389:                                buf [j++] = '_';
                   3390:                        else
                   3391:                                buf [j++] = *s;
                   3392:                        ++s;
                   3393:                }
                   3394:                if (!i) {
                   3395:                        s = option -> name;
                   3396:                        if (j + 1 == buflen)
                   3397:                                return 0;
                   3398:                        buf [j++] = '_';
                   3399:                }
                   3400:                ++i;
                   3401:        } while (i != 2);
                   3402: 
                   3403:        buf [j] = 0;
                   3404:        return 1;
                   3405: }
                   3406: 
                   3407: void go_daemon ()
                   3408: {
                   3409:        static int state = 0;
                   3410:        int pid;
                   3411: 
                   3412:        /* Don't become a daemon if the user requested otherwise. */
                   3413:        if (no_daemon) {
                   3414:                write_client_pid_file ();
                   3415:                return;
                   3416:        }
                   3417: 
                   3418:        /* Only do it once. */
                   3419:        if (state)
                   3420:                return;
                   3421:        state = 1;
                   3422: 
                   3423:        /* Stop logging to stderr... */
                   3424:        log_perror = 0;
                   3425: 
                   3426:        /* Become a daemon... */
                   3427:        if ((pid = fork ()) < 0)
                   3428:                log_fatal ("Can't fork daemon: %m");
                   3429:        else if (pid)
                   3430:                exit (0);
                   3431:        /* Become session leader and get pid... */
                   3432:        pid = setsid ();
                   3433: 
                   3434:        /* Close standard I/O descriptors. */
                   3435:        close(0);
                   3436:        close(1);
                   3437:        close(2);
                   3438: 
                   3439:        /* Reopen them on /dev/null. */
                   3440:        open("/dev/null", O_RDWR);
                   3441:        open("/dev/null", O_RDWR);
                   3442:        open("/dev/null", O_RDWR);
                   3443: 
                   3444:        write_client_pid_file ();
                   3445: 
                   3446:        IGNORE_RET (chdir("/"));
                   3447: }
                   3448: 
                   3449: void write_client_pid_file ()
                   3450: {
                   3451:        FILE *pf;
                   3452:        int pfdesc;
                   3453: 
                   3454:        /* nothing to do if the user doesn't want a pid file */
                   3455:        if (no_pid_file == ISC_TRUE) {
                   3456:                return;
                   3457:        }
                   3458: 
                   3459:        pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
                   3460: 
                   3461:        if (pfdesc < 0) {
                   3462:                log_error ("Can't create %s: %m", path_dhclient_pid);
                   3463:                return;
                   3464:        }
                   3465: 
                   3466:        pf = fdopen (pfdesc, "w");
                   3467:        if (!pf) {
                   3468:                close(pfdesc);
                   3469:                log_error ("Can't fdopen %s: %m", path_dhclient_pid);
                   3470:        } else {
                   3471:                fprintf (pf, "%ld\n", (long)getpid ());
                   3472:                fclose (pf);
                   3473:        }
                   3474: }
                   3475: 
                   3476: void client_location_changed ()
                   3477: {
                   3478:        struct interface_info *ip;
                   3479:        struct client_state *client;
                   3480: 
                   3481:        for (ip = interfaces; ip; ip = ip -> next) {
                   3482:                for (client = ip -> client; client; client = client -> next) {
                   3483:                        switch (client -> state) {
                   3484:                              case S_SELECTING:
                   3485:                                cancel_timeout (send_discover, client);
                   3486:                                break;
                   3487: 
                   3488:                              case S_BOUND:
                   3489:                                cancel_timeout (state_bound, client);
                   3490:                                break;
                   3491: 
                   3492:                              case S_REBOOTING:
                   3493:                              case S_REQUESTING:
                   3494:                              case S_RENEWING:
                   3495:                                cancel_timeout (send_request, client);
                   3496:                                break;
                   3497: 
                   3498:                              case S_INIT:
                   3499:                              case S_REBINDING:
                   3500:                              case S_STOPPED:
                   3501:                                break;
                   3502:                        }
                   3503:                        client -> state = S_INIT;
                   3504:                        state_reboot (client);
                   3505:                }
                   3506:        }
                   3507: }
                   3508: 
                   3509: void do_release(client)
                   3510:        struct client_state *client;
                   3511: {
                   3512:        struct data_string ds;
                   3513:        struct option_cache *oc;
                   3514: 
                   3515:        /* Pick a random xid. */
                   3516:        client -> xid = random ();
                   3517: 
                   3518:        /* is there even a lease to release? */
                   3519:        if (client -> active) {
                   3520:                /* Make a DHCPRELEASE packet, and set appropriate per-interface
                   3521:                   flags. */
                   3522:                make_release (client, client -> active);
                   3523: 
                   3524:                memset (&ds, 0, sizeof ds);
                   3525:                oc = lookup_option (&dhcp_universe,
                   3526:                                    client -> active -> options,
                   3527:                                    DHO_DHCP_SERVER_IDENTIFIER);
                   3528:                if (oc &&
                   3529:                    evaluate_option_cache (&ds, (struct packet *)0,
                   3530:                                           (struct lease *)0, client,
                   3531:                                           (struct option_state *)0,
                   3532:                                           client -> active -> options,
                   3533:                                           &global_scope, oc, MDL)) {
                   3534:                        if (ds.len > 3) {
                   3535:                                memcpy (client -> destination.iabuf,
                   3536:                                        ds.data, 4);
                   3537:                                client -> destination.len = 4;
                   3538:                        } else
                   3539:                                client -> destination = iaddr_broadcast;
                   3540: 
                   3541:                        data_string_forget (&ds, MDL);
                   3542:                } else
                   3543:                        client -> destination = iaddr_broadcast;
                   3544:                client -> first_sending = cur_time;
                   3545:                client -> interval = client -> config -> initial_interval;
                   3546: 
                   3547:                /* Zap the medium list... */
                   3548:                client -> medium = (struct string_list *)0;
                   3549: 
                   3550:                /* Send out the first and only DHCPRELEASE packet. */
                   3551:                send_release (client);
                   3552: 
                   3553:                /* Do the client script RELEASE operation. */
                   3554:                script_init (client,
                   3555:                             "RELEASE", (struct string_list *)0);
                   3556:                if (client -> alias)
                   3557:                        script_write_params (client, "alias_",
                   3558:                                             client -> alias);
                   3559:                script_write_params (client, "old_", client -> active);
                   3560:                script_go (client);
                   3561:        }
                   3562: 
                   3563:        /* Cancel any timeouts. */
                   3564:        cancel_timeout (state_bound, client);
                   3565:        cancel_timeout (send_discover, client);
                   3566:        cancel_timeout (state_init, client);
                   3567:        cancel_timeout (send_request, client);
                   3568:        cancel_timeout (state_reboot, client);
                   3569:        client -> state = S_STOPPED;
                   3570: }
                   3571: 
                   3572: int dhclient_interface_shutdown_hook (struct interface_info *interface)
                   3573: {
                   3574:        do_release (interface -> client);
                   3575: 
                   3576:        return 1;
                   3577: }
                   3578: 
                   3579: int dhclient_interface_discovery_hook (struct interface_info *tmp)
                   3580: {
                   3581:        struct interface_info *last, *ip;
                   3582:        /* See if we can find the client from dummy_interfaces */
                   3583:        last = 0;
                   3584:        for (ip = dummy_interfaces; ip; ip = ip -> next) {
                   3585:                if (!strcmp (ip -> name, tmp -> name)) {
                   3586:                        /* Remove from dummy_interfaces */
                   3587:                        if (last) {
                   3588:                                ip = (struct interface_info *)0;
                   3589:                                interface_reference (&ip, last -> next, MDL);
                   3590:                                interface_dereference (&last -> next, MDL);
                   3591:                                if (ip -> next) {
                   3592:                                        interface_reference (&last -> next,
                   3593:                                                             ip -> next, MDL);
                   3594:                                        interface_dereference (&ip -> next,
                   3595:                                                               MDL);
                   3596:                                }
                   3597:                        } else {
                   3598:                                ip = (struct interface_info *)0;
                   3599:                                interface_reference (&ip,
                   3600:                                                     dummy_interfaces, MDL);
                   3601:                                interface_dereference (&dummy_interfaces, MDL);
                   3602:                                if (ip -> next) {
                   3603:                                        interface_reference (&dummy_interfaces,
                   3604:                                                             ip -> next, MDL);
                   3605:                                        interface_dereference (&ip -> next,
                   3606:                                                               MDL);
                   3607:                                }
                   3608:                        }
                   3609:                        /* Copy "client" to tmp */
                   3610:                        if (ip -> client) {
                   3611:                                tmp -> client = ip -> client;
                   3612:                                tmp -> client -> interface = tmp;
                   3613:                        }
                   3614:                        interface_dereference (&ip, MDL);
                   3615:                        break;
                   3616:                }
                   3617:                last = ip;
                   3618:        }
                   3619:        return 1;
                   3620: }
                   3621: 
                   3622: isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
                   3623: {
                   3624:        struct interface_info *ip;
                   3625:        struct client_state *client;
                   3626: 
                   3627:        /* This code needs some rethinking.   It doesn't test against
                   3628:           a signal name, and it just kind of bulls into doing something
                   3629:           that may or may not be appropriate. */
                   3630: 
                   3631:        if (interfaces) {
                   3632:                interface_reference (&interface -> next, interfaces, MDL);
                   3633:                interface_dereference (&interfaces, MDL);
                   3634:        }
                   3635:        interface_reference (&interfaces, interface, MDL);
                   3636: 
                   3637:        discover_interfaces (DISCOVER_UNCONFIGURED);
                   3638: 
                   3639:        for (ip = interfaces; ip; ip = ip -> next) {
                   3640:                /* If interfaces were specified, don't configure
                   3641:                   interfaces that weren't specified! */
                   3642:                if (ip -> flags & INTERFACE_RUNNING ||
                   3643:                   (ip -> flags & (INTERFACE_REQUESTED |
                   3644:                                     INTERFACE_AUTOMATIC)) !=
                   3645:                     INTERFACE_REQUESTED)
                   3646:                        continue;
                   3647:                script_init (ip -> client,
                   3648:                             "PREINIT", (struct string_list *)0);
                   3649:                if (ip -> client -> alias)
                   3650:                        script_write_params (ip -> client, "alias_",
                   3651:                                             ip -> client -> alias);
                   3652:                script_go (ip -> client);
                   3653:        }
                   3654: 
                   3655:        discover_interfaces (interfaces_requested != 0
                   3656:                             ? DISCOVER_REQUESTED
                   3657:                             : DISCOVER_RUNNING);
                   3658: 
                   3659:        for (ip = interfaces; ip; ip = ip -> next) {
                   3660:                if (ip -> flags & INTERFACE_RUNNING)
                   3661:                        continue;
                   3662:                ip -> flags |= INTERFACE_RUNNING;
                   3663:                for (client = ip->client ; client ; client = client->next) {
                   3664:                        client->state = S_INIT;
                   3665:                        state_reboot(client);
                   3666:                }
                   3667:        }
                   3668:        return ISC_R_SUCCESS;
                   3669: }
                   3670: 
                   3671: /* The client should never receive a relay agent information option,
                   3672:    so if it does, log it and discard it. */
                   3673: 
                   3674: int parse_agent_information_option (packet, len, data)
                   3675:        struct packet *packet;
                   3676:        int len;
                   3677:        u_int8_t *data;
                   3678: {
                   3679:        return 1;
                   3680: }
                   3681: 
                   3682: /* The client never sends relay agent information options. */
                   3683: 
                   3684: unsigned cons_agent_information_options (cfg_options, outpacket,
                   3685:                                         agentix, length)
                   3686:        struct option_state *cfg_options;
                   3687:        struct dhcp_packet *outpacket;
                   3688:        unsigned agentix;
                   3689:        unsigned length;
                   3690: {
                   3691:        return length;
                   3692: }
                   3693: 
                   3694: static void shutdown_exit (void *foo)
                   3695: {
                   3696:        exit (0);
                   3697: }
                   3698: 
                   3699: isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
                   3700:                                     control_object_state_t newstate)
                   3701: {
                   3702:        struct interface_info *ip;
                   3703:        struct client_state *client;
                   3704:        struct timeval tv;
                   3705: 
                   3706:        /* Do the right thing for each interface. */
                   3707:        for (ip = interfaces; ip; ip = ip -> next) {
                   3708:            for (client = ip -> client; client; client = client -> next) {
                   3709:                switch (newstate) {
                   3710:                  case server_startup:
                   3711:                    return ISC_R_SUCCESS;
                   3712: 
                   3713:                  case server_running:
                   3714:                    return ISC_R_SUCCESS;
                   3715: 
                   3716:                  case server_shutdown:
                   3717:                    if (client -> active &&
                   3718:                        client -> active -> expiry > cur_time) {
                   3719:                            if (client -> config -> do_forward_update)
                   3720:                                    client_dns_update(client, 0, 0,
                   3721:                                                    &client->active->address);
                   3722:                            do_release (client);
                   3723:                    }
                   3724:                    break;
                   3725: 
                   3726:                  case server_hibernate:
                   3727:                    state_stop (client);
                   3728:                    break;
                   3729: 
                   3730:                  case server_awaken:
                   3731:                    state_reboot (client);
                   3732:                    break;
                   3733:                }
                   3734:            }
                   3735:        }
                   3736: 
                   3737:        if (newstate == server_shutdown) {
                   3738:                tv.tv_sec = cur_tv.tv_sec;
                   3739:                tv.tv_usec = cur_tv.tv_usec + 1;
                   3740:                add_timeout(&tv, shutdown_exit, 0, 0, 0);
                   3741:        }
                   3742:        return ISC_R_SUCCESS;
                   3743: }
                   3744: 
                   3745: /* Schedule updates to retry occasionally until it no longer times out.
                   3746:  */
                   3747: void
                   3748: dhclient_schedule_updates(struct client_state *client, struct iaddr *addr,
                   3749:                          int offset)
                   3750: {
                   3751:        struct dns_update_state *ustate;
                   3752:        struct timeval tv;
                   3753: 
                   3754:        if (!client->config->do_forward_update)
                   3755:                return;
                   3756: 
                   3757:        ustate = dmalloc(sizeof(*ustate), MDL);
                   3758: 
                   3759:        if (ustate != NULL) {
                   3760:                ustate->client = client;
                   3761:                ustate->address = *addr;
                   3762:                ustate->dns_update_timeout = 1;
                   3763: 
                   3764:                tv.tv_sec = cur_tv.tv_sec + offset;
                   3765:                tv.tv_usec = cur_tv.tv_usec;
                   3766:                add_timeout(&tv, client_dns_update_timeout,
                   3767:                            ustate, NULL, NULL);
                   3768:        } else {
                   3769:                log_error("Unable to allocate dns update state for %s.",
                   3770:                          piaddr(*addr));
                   3771:        }
                   3772: }
                   3773: 
                   3774: /* Called after a timeout if the DNS update failed on the previous try.
                   3775:    Retries the update, and if it times out, schedules a retry after
                   3776:    ten times as long of a wait. */
                   3777: 
                   3778: void client_dns_update_timeout (void *cp)
                   3779: {
                   3780:        struct dns_update_state *ustate = cp;
                   3781:        isc_result_t status = ISC_R_FAILURE;
                   3782:        struct timeval tv;
                   3783: 
                   3784:        /* XXX: DNS TTL is a problem we need to solve properly.  Until
                   3785:         * that time, 300 is a placeholder default for something that is
                   3786:         * less insane than a value scaled by lease timeout.
                   3787:         */
                   3788:        if ((ustate->client->active != NULL) ||
                   3789:            (ustate->client->active_lease != NULL))
                   3790:                status = client_dns_update(ustate->client, 1, 300,
                   3791:                                           &ustate->address);
                   3792: 
                   3793:        if (status == ISC_R_TIMEDOUT) {
                   3794:                if (ustate->dns_update_timeout < 3600)
                   3795:                        ustate->dns_update_timeout *= 10;
                   3796:                tv.tv_sec = cur_tv.tv_sec + ustate->dns_update_timeout;
                   3797:                tv.tv_usec = cur_tv.tv_usec;
                   3798:                add_timeout(&tv, client_dns_update_timeout,
                   3799:                            ustate, NULL, NULL);
                   3800:        } else
                   3801:                dfree(ustate, MDL);
                   3802: }
                   3803: 
                   3804: /* See if we should do a DNS update, and if so, do it. */
                   3805: 
                   3806: isc_result_t client_dns_update (struct client_state *client, int addp,
                   3807:                                int ttl, struct iaddr *address)
                   3808: {
                   3809:        struct data_string ddns_fwd_name, ddns_dhcid, client_identifier;
                   3810:        struct option_cache *oc;
                   3811:        int ignorep;
                   3812:        int result;
                   3813:        isc_result_t rcode;
                   3814: 
                   3815:        /* If we didn't send an FQDN option, we certainly aren't going to
                   3816:           be doing an update. */
                   3817:        if (!client -> sent_options)
                   3818:                return ISC_R_SUCCESS;
                   3819: 
                   3820:        /* If we don't have a lease, we can't do an update. */
                   3821:        if ((client->active == NULL) && (client->active_lease == NULL))
                   3822:                return ISC_R_SUCCESS;
                   3823: 
                   3824:        /* If we set the no client update flag, don't do the update. */
                   3825:        if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
                   3826:                                  FQDN_NO_CLIENT_UPDATE)) &&
                   3827:            evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
                   3828:                                           (struct lease *)0, client,
                   3829:                                           client -> sent_options,
                   3830:                                           (struct option_state *)0,
                   3831:                                           &global_scope, oc, MDL))
                   3832:                return ISC_R_SUCCESS;
                   3833: 
                   3834:        /* If we set the "server, please update" flag, or didn't set it
                   3835:           to false, don't do the update. */
                   3836:        if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
                   3837:                                  FQDN_SERVER_UPDATE)) ||
                   3838:            evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
                   3839:                                           (struct lease *)0, client,
                   3840:                                           client -> sent_options,
                   3841:                                           (struct option_state *)0,
                   3842:                                           &global_scope, oc, MDL))
                   3843:                return ISC_R_SUCCESS;
                   3844: 
                   3845:        /* If no FQDN option was supplied, don't do the update. */
                   3846:        memset (&ddns_fwd_name, 0, sizeof ddns_fwd_name);
                   3847:        if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
                   3848:                                  FQDN_FQDN)) ||
                   3849:            !evaluate_option_cache (&ddns_fwd_name, (struct packet *)0,
                   3850:                                    (struct lease *)0, client,
                   3851:                                    client -> sent_options,
                   3852:                                    (struct option_state *)0,
                   3853:                                    &global_scope, oc, MDL))
                   3854:                return ISC_R_SUCCESS;
                   3855: 
                   3856:        /* If this is a DHCPv6 client update, make a dhcid string out of
                   3857:         * the DUID.  If this is a DHCPv4 client update, choose either
                   3858:         * the client identifier, if there is one, or the interface's
                   3859:         * MAC address.
                   3860:         */
                   3861:        memset (&ddns_dhcid, 0, sizeof ddns_dhcid);
                   3862: 
                   3863:        result = 0;
                   3864:        memset(&client_identifier, 0, sizeof(client_identifier));
                   3865:        if (client->active_lease != NULL) {
                   3866:                if (((oc =
                   3867:                      lookup_option(&dhcpv6_universe, client->sent_options,
                   3868:                                    D6O_CLIENTID)) != NULL) &&
                   3869:                    evaluate_option_cache(&client_identifier, NULL, NULL,
                   3870:                                          client, client->sent_options, NULL,
                   3871:                                          &global_scope, oc, MDL)) {
                   3872:                        /* RFC4701 defines type '2' as being for the DUID
                   3873:                         * field.  We aren't using RFC4701 DHCID RR's yet,
                   3874:                         * but this is as good a value as any.
                   3875:                         */
                   3876:                        result = get_dhcid(&ddns_dhcid, 2,
                   3877:                                           client_identifier.data,
                   3878:                                           client_identifier.len);
                   3879:                        data_string_forget(&client_identifier, MDL);
                   3880:                } else
                   3881:                        log_fatal("Impossible condition at %s:%d.", MDL);
                   3882:        } else {
                   3883:                if (((oc =
                   3884:                      lookup_option(&dhcp_universe, client->sent_options,
                   3885:                                    DHO_DHCP_CLIENT_IDENTIFIER)) != NULL) &&
                   3886:                    evaluate_option_cache(&client_identifier, NULL, NULL,
                   3887:                                          client, client->sent_options, NULL,
                   3888:                                          &global_scope, oc, MDL)) {
                   3889:                        result = get_dhcid(&ddns_dhcid,
                   3890:                                           DHO_DHCP_CLIENT_IDENTIFIER,
                   3891:                                           client_identifier.data,
                   3892:                                           client_identifier.len);
                   3893:                        data_string_forget(&client_identifier, MDL);
                   3894:                } else
                   3895:                        result = get_dhcid(&ddns_dhcid, 0,
                   3896:                                           client->interface->hw_address.hbuf,
                   3897:                                           client->interface->hw_address.hlen);
                   3898:        }
                   3899:        if (!result) {
                   3900:                data_string_forget(&ddns_fwd_name, MDL);
                   3901:                return ISC_R_SUCCESS;
                   3902:        }
                   3903: 
                   3904:        /* Start the resolver, if necessary. */
                   3905:        if (!resolver_inited) {
                   3906:                minires_ninit (&resolver_state);
                   3907:                resolver_inited = 1;
                   3908:                resolver_state.retrans = 1;
                   3909:                resolver_state.retry = 1;
                   3910:        }
                   3911: 
                   3912:        /*
                   3913:         * Perform updates.
                   3914:         */
                   3915:        if (ddns_fwd_name.len && ddns_dhcid.len) {
                   3916:                if (addp)
                   3917:                        rcode = ddns_update_fwd(&ddns_fwd_name, *address,
                   3918:                                                &ddns_dhcid, ttl, 1, 1);
                   3919:                else
                   3920:                        rcode = ddns_remove_fwd(&ddns_fwd_name, *address,
                   3921:                                                &ddns_dhcid);
                   3922:        } else
                   3923:                rcode = ISC_R_FAILURE;
                   3924: 
                   3925:        data_string_forget (&ddns_fwd_name, MDL);
                   3926:        data_string_forget (&ddns_dhcid, MDL);
                   3927:        return rcode;
                   3928: }
                   3929: 
                   3930: void
                   3931: dhcpv4_client_assignments(void)
                   3932: {
                   3933:        struct servent *ent;
                   3934: 
                   3935:        if (path_dhclient_pid == NULL)
                   3936:                path_dhclient_pid = _PATH_DHCLIENT_PID;
                   3937:        if (path_dhclient_db == NULL)
                   3938:                path_dhclient_db = _PATH_DHCLIENT_DB;
                   3939: 
                   3940:        /* Default to the DHCP/BOOTP port. */
                   3941:        if (!local_port) {
                   3942:                /* If we're faking a relay agent, and we're not using loopback,
                   3943:                   use the server port, not the client port. */
                   3944:                if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
                   3945:                        local_port = htons(67);
                   3946:                } else {
                   3947:                        ent = getservbyname ("dhcpc", "udp");
                   3948:                        if (!ent)
                   3949:                                local_port = htons (68);
                   3950:                        else
                   3951:                                local_port = ent -> s_port;
                   3952: #ifndef __CYGWIN32__
                   3953:                        endservent ();
                   3954: #endif
                   3955:                }
                   3956:        }
                   3957: 
                   3958:        /* If we're faking a relay agent, and we're not using loopback,
                   3959:           we're using the server port, not the client port. */
                   3960:        if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
                   3961:                remote_port = local_port;
                   3962:        } else
                   3963:                remote_port = htons (ntohs (local_port) - 1);   /* XXX */
                   3964: }
                   3965: 
                   3966: /*
                   3967:  * The following routines are used to check that certain
                   3968:  * strings are reasonable before we pass them to the scripts.
                   3969:  * This avoids some problems with scripts treating the strings
                   3970:  * as commands - see ticket 23722
                   3971:  * The domain checking code should be done as part of assembling
                   3972:  * the string but we are doing it here for now due to time
                   3973:  * constraints.
                   3974:  */
                   3975: 
                   3976: static int check_domain_name(const char *ptr, size_t len, int dots)
                   3977: {
                   3978:        const char *p;
                   3979: 
                   3980:        /* not empty or complete length not over 255 characters   */
                   3981:        if ((len == 0) || (len > 256))
                   3982:                return(-1);
                   3983: 
                   3984:        /* consists of [[:alnum:]-]+ labels separated by [.]      */
                   3985:        /* a [_] is against RFC but seems to be "widely used"...  */
                   3986:        for (p=ptr; (*p != 0) && (len-- > 0); p++) {
                   3987:                if ((*p == '-') || (*p == '_')) {
                   3988:                        /* not allowed at begin or end of a label */
                   3989:                        if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
                   3990:                                return(-1);
                   3991:                } else if (*p == '.') {
                   3992:                        /* each label has to be 1-63 characters;
                   3993:                           we allow [.] at the end ('foo.bar.')   */
                   3994:                        size_t d = p - ptr;
                   3995:                        if ((d <= 0) || (d >= 64))
                   3996:                                return(-1);
                   3997:                        ptr = p + 1; /* jump to the next label    */
                   3998:                        if ((dots > 0) && (len > 0))
                   3999:                                dots--;
                   4000:                } else if (isalnum((unsigned char)*p) == 0) {
                   4001:                        /* also numbers at the begin are fine     */
                   4002:                        return(-1);
                   4003:                }
                   4004:        }
                   4005:        return(dots ? -1 : 0);
                   4006: }
                   4007: 
                   4008: static int check_domain_name_list(const char *ptr, size_t len, int dots)
                   4009: {
                   4010:        const char *p;
                   4011:        int ret = -1; /* at least one needed */
                   4012: 
                   4013:        if ((ptr == NULL) || (len == 0))
                   4014:                return(-1);
                   4015: 
                   4016:        for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
                   4017:                if (*p != ' ')
                   4018:                        continue;
                   4019:                if (p > ptr) {
                   4020:                        if (check_domain_name(ptr, p - ptr, dots) != 0)
                   4021:                                return(-1);
                   4022:                        ret = 0;
                   4023:                }
                   4024:                ptr = p + 1;
                   4025:        }
                   4026:        if (p > ptr)
                   4027:                return(check_domain_name(ptr, p - ptr, dots));
                   4028:        else
                   4029:                return(ret);
                   4030: }
                   4031: 
                   4032: static int check_option_values(struct universe *universe,
                   4033:                               unsigned int opt,
                   4034:                               const char *ptr,
                   4035:                               size_t len)
                   4036: {
                   4037:        if (ptr == NULL)
                   4038:                return(-1);
                   4039: 
                   4040:        /* just reject options we want to protect, will be escaped anyway */
                   4041:        if ((universe == NULL) || (universe == &dhcp_universe)) {
                   4042:                switch(opt) {
                   4043:                      case DHO_DOMAIN_NAME:
                   4044: #ifdef ACCEPT_LIST_IN_DOMAIN_NAME
                   4045:                              return check_domain_name_list(ptr, len, 0);
                   4046: #else
                   4047:                              return check_domain_name(ptr, len, 0);
                   4048: #endif
                   4049:                      case DHO_HOST_NAME:
                   4050:                      case DHO_NIS_DOMAIN:
                   4051:                      case DHO_NETBIOS_SCOPE:
                   4052:                        return check_domain_name(ptr, len, 0);
                   4053:                        break;
                   4054:                      case DHO_DOMAIN_SEARCH:
                   4055:                        return check_domain_name_list(ptr, len, 0);
                   4056:                        break;
                   4057:                      case DHO_ROOT_PATH:
                   4058:                        if (len == 0)
                   4059:                                return(-1);
                   4060:                        for (; (*ptr != 0) && (len-- > 0); ptr++) {
                   4061:                                if(!(isalnum((unsigned char)*ptr) ||
                   4062:                                     *ptr == '#'  || *ptr == '%' ||
                   4063:                                     *ptr == '+'  || *ptr == '-' ||
                   4064:                                     *ptr == '_'  || *ptr == ':' ||
                   4065:                                     *ptr == '.'  || *ptr == ',' ||
                   4066:                                     *ptr == '@'  || *ptr == '~' ||
                   4067:                                     *ptr == '\\' || *ptr == '/' ||
                   4068:                                     *ptr == '['  || *ptr == ']' ||
                   4069:                                     *ptr == '='  || *ptr == ' '))
                   4070:                                        return(-1);
                   4071:                        }
                   4072:                        return(0);
                   4073:                        break;
                   4074:                }
                   4075:        }
                   4076: 
                   4077: #ifdef DHCPv6
                   4078:        if (universe == &dhcpv6_universe) {
                   4079:                switch(opt) {
                   4080:                      case D6O_SIP_SERVERS_DNS:
                   4081:                      case D6O_DOMAIN_SEARCH:
                   4082:                      case D6O_NIS_DOMAIN_NAME:
                   4083:                      case D6O_NISP_DOMAIN_NAME:
                   4084:                        return check_domain_name_list(ptr, len, 0);
                   4085:                        break;
                   4086:                }
                   4087:        }
                   4088: #endif
                   4089: 
                   4090:        return(0);
                   4091: }
                   4092: 
                   4093: static void
                   4094: add_reject(struct packet *packet) {
                   4095:        struct iaddrmatchlist *list;
                   4096:        
                   4097:        list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
                   4098:        if (!list)
                   4099:                log_fatal ("no memory for reject list!");
                   4100: 
                   4101:        /*
                   4102:         * client_addr is misleading - it is set to source address in common
                   4103:         * code.
                   4104:         */
                   4105:        list->match.addr = packet->client_addr;
                   4106:        /* Set mask to indicate host address. */
                   4107:        list->match.mask.len = list->match.addr.len;
                   4108:        memset(list->match.mask.iabuf, 0xff, sizeof(list->match.mask.iabuf));
                   4109: 
                   4110:        /* Append to reject list for the source interface. */
                   4111:        list->next = packet->interface->client->config->reject_list;
                   4112:        packet->interface->client->config->reject_list = list;
                   4113: 
                   4114:        /*
                   4115:         * We should inform user that we won't be accepting this server
                   4116:         * anymore.
                   4117:         */
                   4118:        log_info("Server added to list of rejected servers.");
                   4119: }

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