"Fossies" - the Fresh Open Source Software Archive

Member "dhcp-4.4.3-P1/client/dhclient.c" (28 Sep 2022, 162309 Bytes) of package /linux/misc/dhcp-4.4.3-P1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dhclient.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 4.4.2-P1_vs_4.4.3.

    1 /* dhclient.c
    2 
    3    DHCP Client. */
    4 
    5 /*
    6  * Copyright (c) 2004-2022 by Internet Systems Consortium, Inc. ("ISC")
    7  * Copyright (c) 1995-2003 by Internet Software Consortium
    8  *
    9  * This Source Code Form is subject to the terms of the Mozilla Public
   10  * License, v. 2.0. If a copy of the MPL was not distributed with this
   11  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
   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  *   PO Box 360
   23  *   Newmarket, NH 03857 USA
   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 <isc/util.h>
   35 #include <isc/file.h>
   36 #include <dns/result.h>
   37 #include <syslog.h>
   38 #include <signal.h>
   39 #include <errno.h>
   40 #include <sys/time.h>
   41 #include <sys/wait.h>
   42 #include <limits.h>
   43 
   44 TIME default_lease_time = 43200; /* 12 hours... */
   45 TIME max_lease_time = 86400; /* 24 hours... */
   46 
   47 const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
   48 const char *path_dhclient_db = NULL;
   49 const char *path_dhclient_pid = NULL;
   50 static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
   51 char *path_dhclient_script = path_dhclient_script_array;
   52 const char *path_dhclient_duid = NULL;
   53 
   54 static void add_to_tail(struct client_lease** lease_list, struct client_lease* lease);
   55 
   56 /* False (default) => we write and use a pid file */
   57 isc_boolean_t no_pid_file = ISC_FALSE;
   58 
   59 int dhcp_max_agent_option_packet_length = 0;
   60 
   61 int interfaces_requested = 0;
   62 
   63 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
   64 struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
   65 struct in_addr inaddr_any;
   66 struct sockaddr_in sockaddr_broadcast;
   67 struct in_addr giaddr;
   68 struct data_string default_duid;
   69 int duid_type = 0;
   70 int duid_v4 = 0;
   71 int std_dhcid = 0;
   72 
   73 int decline_wait_time = 10; /* Default to 10 secs per, RFC 2131, 3.1.5 */
   74 
   75 /* ASSERT_STATE() does nothing now; it used to be
   76    assert (state_is == state_shouldbe). */
   77 #define ASSERT_STATE(state_is, state_shouldbe) {}
   78 
   79 #ifndef UNIT_TEST
   80 static const char copyright[] = "Copyright 2004-2022 Internet Systems Consortium.";
   81 static const char arr [] = "All rights reserved.";
   82 static const char message [] = "Internet Systems Consortium DHCP Client";
   83 static const char url [] = "For info, please visit https://www.isc.org/software/dhcp/";
   84 #endif /* UNIT_TEST */
   85 
   86 extern u_int16_t local_port;
   87 extern u_int16_t remote_port;
   88 
   89 #if defined(DHCPv6) && defined(DHCP4o6)
   90 int dhcp4o6_state = -1; /* -1 = stopped, 0 = polling, 1 = started */
   91 #endif
   92 int no_daemon = 0;
   93 int dfd[2] = { -1, -1 };
   94 struct string_list *client_env = NULL;
   95 int client_env_count = 0;
   96 int onetry = 0;
   97 int quiet = 1;
   98 int nowait = 0;
   99 int stateless = 0;
  100 int wanted_ia_na = -1;      /* the absolute value is the real one. */
  101 int wanted_ia_ta = 0;
  102 int wanted_ia_pd = 0;
  103 int require_all_ias = 0;    /* If the user requires all of the IAs to
  104                    be available before accepting a lease
  105                    0 = no, 1 = requries */
  106 #if defined(DHCPv6)
  107 int dad_wait_time = 0;
  108 int prefix_len_hint = 0;
  109 #endif
  110 
  111 int address_prefix_len = DHCLIENT_DEFAULT_PREFIX_LEN;
  112 char *mockup_relay = NULL;
  113 
  114 char *progname = NULL;
  115 
  116 void run_stateless(int exit_mode, u_int16_t port);
  117 
  118 static isc_result_t write_duid(struct data_string *duid);
  119 static void add_reject(struct packet *packet);
  120 
  121 static int check_domain_name(const char *ptr, size_t len, int dots);
  122 static int check_domain_name_list(const char *ptr, size_t len, int dots);
  123 static int check_option_values(struct universe *universe, unsigned int opt,
  124                    const char *ptr, size_t len);
  125 
  126 #if defined(NSUPDATE)
  127 static void dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb,
  128                                    char* file, int line);
  129 #endif /* defined NSUPDATE */
  130 
  131 
  132 /*!
  133  *
  134  * \brief Print the generic usage message
  135  *
  136  * If the user has provided an incorrect command line print out
  137  * the description of the command line.  The arguments provide
  138  * a way for the caller to request more specific information about
  139  * the error be printed as well.  Mostly this will be that some
  140  * command doesn't include its argument.
  141  *
  142  * \param sfmt - The basic string and format for the specific error
  143  * \param sarg - Generally the offending argument from the command line.
  144  *
  145  * \return Nothing
  146  */
  147 
  148 #if defined(DHCPv6) && defined(DHCP4o6)
  149 static void dhcp4o6_poll(void *dummy);
  150 static void dhcp4o6_resume(void);
  151 static void recv_dhcpv4_response(struct data_string *raw);
  152 static int send_dhcpv4_query(struct client_state *client, int broadcast);
  153 
  154 static void dhcp4o6_stop(void);
  155 static void forw_dhcpv4_response(struct packet *packet);
  156 static void forw_dhcpv4_query(struct data_string *raw);
  157 #endif
  158 
  159 #ifndef UNIT_TEST
  160 /* These are only used when we call usage() from the main routine
  161  * which isn't compiled when building for unit tests
  162  */
  163 static const char use_noarg[] = "No argument for command: %s";
  164 #ifdef DHCPv6
  165 static const char use_v6command[] = "Command not used for DHCPv4: %s";
  166 #endif
  167 
  168 #ifdef DHCPv6
  169 #ifdef DHCP4o6
  170 #define DHCLIENT_USAGE0 \
  171 "[-4|-6] [-SNTPRI1dvrxi] [-nw] -4o6 <port>] [-p <port>] [-D LL|LLT]\n" \
  172 "                [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
  173 "                [--decline-wait-time <seconds>]\n" \
  174 "                [--address-prefix-len <length>]\n"
  175 #else /* DHCP4o6 */
  176 #define DHCLIENT_USAGE0 \
  177 "[-4|-6] [-SNTPRI1dvrxi] [-nw] [-p <port>] [-D LL|LLT]\n" \
  178 "                [--dad-wait-time <seconds>] [--prefix-len-hint <length>]\n" \
  179 "                [--decline-wait-time <seconds>]\n" \
  180 "                [--address-prefix-len <length>]\n"
  181 #endif
  182 #else /* DHCPv6 */
  183 #define DHCLIENT_USAGE0 \
  184 "[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n" \
  185 "                [--decline-wait-time <seconds>]\n"
  186 #endif
  187 
  188 #define DHCLIENT_USAGEC \
  189 "                [-s server-addr] [-cf config-file]\n" \
  190 "                [-df duid-file] [-lf lease-file]\n" \
  191 "                [-pf pid-file] [--no-pid] [-e VAR=val]\n" \
  192 "                [-sf script-file] [interface]*"
  193 
  194 #define DHCLIENT_USAGEH "{--version|--help|-h}"
  195 
  196 static void
  197 usage(const char *sfmt, const char *sarg)
  198 {
  199     log_info("%s %s", message, PACKAGE_VERSION);
  200     log_info(copyright);
  201     log_info(arr);
  202     log_info(url);
  203 
  204     /* If desired print out the specific error message */
  205 #ifdef PRINT_SPECIFIC_CL_ERRORS
  206     if (sfmt != NULL)
  207         log_error(sfmt, sarg);
  208 #endif
  209 
  210     log_fatal("Usage: %s %s%s\n       %s %s",
  211           isc_file_basename(progname),
  212           DHCLIENT_USAGE0,
  213           DHCLIENT_USAGEC,
  214           isc_file_basename(progname),
  215           DHCLIENT_USAGEH);
  216 }
  217 
  218 extern void initialize_client_option_spaces();
  219 
  220 int
  221 main(int argc, char **argv) {
  222     int fd;
  223     int i;
  224     struct interface_info *ip;
  225     struct client_state *client;
  226     unsigned seed;
  227     char *server = NULL;
  228     isc_result_t status;
  229     int exit_mode = 0;
  230     int release_mode = 0;
  231     struct timeval tv;
  232     omapi_object_t *listener;
  233     isc_result_t result;
  234     int persist = 0;
  235     int no_dhclient_conf = 0;
  236     int no_dhclient_db = 0;
  237     int no_dhclient_pid = 0;
  238     int no_dhclient_script = 0;
  239 #ifdef DHCPv6
  240     int local_family_set = 0;
  241 #ifdef DHCP4o6
  242     u_int16_t dhcp4o6_port = 0;
  243 #endif /* DHCP4o6 */
  244 #endif /* DHCPv6 */
  245     char *s;
  246 
  247 #ifdef OLD_LOG_NAME
  248     progname = "dhclient";
  249 #else
  250     progname = argv[0];
  251 #endif
  252     /* Initialize client globals. */
  253     memset(&default_duid, 0, sizeof(default_duid));
  254 
  255     /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
  256        2 (stderr) are open. To do this, we assume that when we
  257        open a file the lowest available file descriptor is used. */
  258     fd = open("/dev/null", O_RDWR);
  259     if (fd == 0)
  260         fd = open("/dev/null", O_RDWR);
  261     if (fd == 1)
  262         fd = open("/dev/null", O_RDWR);
  263     if (fd == 2)
  264         log_perror = 0; /* No sense logging to /dev/null. */
  265     else if (fd != -1)
  266         close(fd);
  267 
  268     openlog(isc_file_basename(progname), DHCP_LOG_OPTIONS, LOG_DAEMON);
  269 
  270 #if !(defined(DEBUG) || defined(__CYGWIN32__))
  271     setlogmask(LOG_UPTO(LOG_INFO));
  272 #endif
  273 
  274     /* Parse arguments changing no_daemon */
  275     for (i = 1; i < argc; i++) {
  276         if (!strcmp(argv[i], "-r")) {
  277             no_daemon = 1;
  278         } else if (!strcmp(argv[i], "-x")) {
  279             no_daemon = 0;
  280         } else if (!strcmp(argv[i], "-d")) {
  281             no_daemon = 1;
  282         } else if (!strcmp(argv[i], "--version")) {
  283             const char vstring[] = "isc-dhclient-";
  284             IGNORE_RET(write(STDERR_FILENO, vstring,
  285                      strlen(vstring)));
  286             IGNORE_RET(write(STDERR_FILENO,
  287                      PACKAGE_VERSION,
  288                      strlen(PACKAGE_VERSION)));
  289             IGNORE_RET(write(STDERR_FILENO, "\n", 1));
  290             exit(0);
  291         } else if (!strcmp(argv[i], "--help") ||
  292                !strcmp(argv[i], "-h")) {
  293             const char *pname = isc_file_basename(progname);
  294             IGNORE_RET(write(STDERR_FILENO, "Usage: ", 7));
  295             IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname)));
  296             IGNORE_RET(write(STDERR_FILENO, " ", 1));
  297             IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGE0,
  298                      strlen(DHCLIENT_USAGE0)));
  299             IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGEC,
  300                      strlen(DHCLIENT_USAGEC)));
  301             IGNORE_RET(write(STDERR_FILENO, "\n", 1));
  302             IGNORE_RET(write(STDERR_FILENO, "       ", 7));
  303             IGNORE_RET(write(STDERR_FILENO, pname, strlen(pname)));
  304             IGNORE_RET(write(STDERR_FILENO, " ", 1));
  305             IGNORE_RET(write(STDERR_FILENO, DHCLIENT_USAGEH,
  306                      strlen(DHCLIENT_USAGEH)));
  307             IGNORE_RET(write(STDERR_FILENO, "\n", 1));
  308             exit(0);
  309         }
  310     }
  311     /* When not forbidden prepare to become a daemon */
  312     if (!no_daemon) {
  313         int pid;
  314 
  315         if (pipe(dfd) == -1)
  316             log_fatal("Can't get pipe: %m");
  317         if ((pid = fork ()) < 0)
  318             log_fatal("Can't fork daemon: %m");
  319         if (pid != 0) {
  320             /* Parent: wait for the child to start */
  321             int n;
  322 
  323             (void) close(dfd[1]);
  324             do {
  325                 char buf;
  326 
  327                 n = read(dfd[0], &buf, 1);
  328                 if (n == 1)
  329                     _exit((int)buf);
  330             } while (n == -1 && errno == EINTR);
  331             _exit(1);
  332         }
  333         /* Child */
  334         (void) close(dfd[0]);
  335     }
  336 
  337     /* Set up the isc and dns library managers */
  338     status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB
  339                      | DHCP_DNS_CLIENT_LAZY_INIT, NULL, NULL);
  340     if (status != ISC_R_SUCCESS)
  341         log_fatal("Can't initialize context: %s",
  342               isc_result_totext(status));
  343 
  344     /* Set up the OMAPI. */
  345     status = omapi_init();
  346     if (status != ISC_R_SUCCESS)
  347         log_fatal("Can't initialize OMAPI: %s",
  348               isc_result_totext(status));
  349 
  350     /* Set up the OMAPI wrappers for various server database internal
  351        objects. */
  352     dhcp_common_objects_setup();
  353 
  354     dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
  355     dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
  356     dhcp_interface_startup_hook = dhclient_interface_startup_hook;
  357 
  358     for (i = 1; i < argc; i++) {
  359         if (!strcmp(argv[i], "-r")) {
  360             release_mode = 1;
  361             /* no_daemon = 1; */
  362 #ifdef DHCPv6
  363         } else if (!strcmp(argv[i], "-4")) {
  364             if (local_family_set && local_family != AF_INET)
  365                 log_fatal("Client can only do v4 or v6, not "
  366                       "both.");
  367             local_family_set = 1;
  368             local_family = AF_INET;
  369         } else if (!strcmp(argv[i], "-6")) {
  370             if (local_family_set && local_family != AF_INET6)
  371                 log_fatal("Client can only do v4 or v6, not "
  372                       "both.");
  373             local_family_set = 1;
  374             local_family = AF_INET6;
  375 #ifdef DHCP4o6
  376         } else if (!strcmp(argv[i], "-4o6")) {
  377             if (++i == argc)
  378                 usage(use_noarg, argv[i-1]);
  379             dhcp4o6_port = validate_port_pair(argv[i]);
  380 
  381             log_debug("DHCPv4 over DHCPv6 over ::1 port %d and %d",
  382                   ntohs(dhcp4o6_port),
  383                   ntohs(dhcp4o6_port) + 1);
  384             dhcpv4_over_dhcpv6 = 1;
  385 #endif /* DHCP4o6 */
  386 #endif /* DHCPv6 */
  387         } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */
  388             release_mode = 0;
  389             /* no_daemon = 0; */
  390             exit_mode = 1;
  391         } else if (!strcmp(argv[i], "-p")) {
  392             if (++i == argc)
  393                 usage(use_noarg, argv[i-1]);
  394             local_port = validate_port(argv[i]);
  395             log_debug("binding to user-specified port %d",
  396                   ntohs(local_port));
  397         } else if (!strcmp(argv[i], "-d")) {
  398             /* no_daemon = 1; */
  399             quiet = 0;
  400         } else if (!strcmp(argv[i], "-pf")) {
  401             if (++i == argc)
  402                 usage(use_noarg, argv[i-1]);
  403             path_dhclient_pid = argv[i];
  404             no_dhclient_pid = 1;
  405         } else if (!strcmp(argv[i], "--no-pid")) {
  406             no_pid_file = ISC_TRUE;
  407         } else if (!strcmp(argv[i], "-cf")) {
  408             if (++i == argc)
  409                 usage(use_noarg, argv[i-1]);
  410             path_dhclient_conf = argv[i];
  411             no_dhclient_conf = 1;
  412         } else if (!strcmp(argv[i], "-df")) {
  413             if (++i == argc)
  414                 usage(use_noarg, argv[i-1]);
  415             path_dhclient_duid = argv[i];
  416         } else if (!strcmp(argv[i], "-lf")) {
  417             if (++i == argc)
  418                 usage(use_noarg, argv[i-1]);
  419             path_dhclient_db = argv[i];
  420             no_dhclient_db = 1;
  421         } else if (!strcmp(argv[i], "-sf")) {
  422             if (++i == argc)
  423                 usage(use_noarg, argv[i-1]);
  424             path_dhclient_script = argv[i];
  425             no_dhclient_script = 1;
  426         } else if (!strcmp(argv[i], "-1")) {
  427             onetry = 1;
  428         } else if (!strcmp(argv[i], "-q")) {
  429             quiet = 1;
  430         } else if (!strcmp(argv[i], "-s")) {
  431             if (++i == argc)
  432                 usage(use_noarg, argv[i-1]);
  433             server = argv[i];
  434         } else if (!strcmp(argv[i], "-g")) {
  435             if (++i == argc)
  436                 usage(use_noarg, argv[i-1]);
  437             mockup_relay = argv[i];
  438         } else if (!strcmp(argv[i], "-nw")) {
  439             nowait = 1;
  440         } else if (!strcmp(argv[i], "-n")) {
  441             /* do not start up any interfaces */
  442             interfaces_requested = -1;
  443         } else if (!strcmp(argv[i], "-w")) {
  444             /* do not exit if there are no broadcast interfaces. */
  445             persist = 1;
  446         } else if (!strcmp(argv[i], "-e")) {
  447             struct string_list *tmp;
  448             if (++i == argc)
  449                 usage(use_noarg, argv[i-1]);
  450             tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
  451             if (!tmp)
  452                 log_fatal("No memory for %s", argv[i]);
  453             strcpy(tmp->string, argv[i]);
  454             tmp->next = client_env;
  455             client_env = tmp;
  456             client_env_count++;
  457 #ifdef DHCPv6
  458         } else if (!strcmp(argv[i], "-S")) {
  459             if (local_family_set && (local_family == AF_INET)) {
  460                 usage(use_v6command, argv[i]);
  461             }
  462             local_family_set = 1;
  463             local_family = AF_INET6;
  464             wanted_ia_na = 0;
  465             stateless = 1;
  466         } else if (!strcmp(argv[i], "-N")) {
  467             if (local_family_set && (local_family == AF_INET)) {
  468                 usage(use_v6command, argv[i]);
  469             }
  470             local_family_set = 1;
  471             local_family = AF_INET6;
  472             if (wanted_ia_na < 0) {
  473                 wanted_ia_na = 0;
  474             }
  475             wanted_ia_na++;
  476         } else if (!strcmp(argv[i], "-T")) {
  477             if (local_family_set && (local_family == AF_INET)) {
  478                 usage(use_v6command, argv[i]);
  479             }
  480             local_family_set = 1;
  481             local_family = AF_INET6;
  482             if (wanted_ia_na < 0) {
  483                 wanted_ia_na = 0;
  484             }
  485             wanted_ia_ta++;
  486         } else if (!strcmp(argv[i], "-P")) {
  487             if (local_family_set && (local_family == AF_INET)) {
  488                 usage(use_v6command, argv[i]);
  489             }
  490             local_family_set = 1;
  491             local_family = AF_INET6;
  492             if (wanted_ia_na < 0) {
  493                 wanted_ia_na = 0;
  494             }
  495             wanted_ia_pd++;
  496         } else if (!strcmp(argv[i], "-R")) {
  497             if (local_family_set && (local_family == AF_INET)) {
  498                 usage(use_v6command, argv[i]);
  499             }
  500             local_family_set = 1;
  501             local_family = AF_INET6;
  502             require_all_ias = 1;
  503         } else if (!strcmp(argv[i], "--dad-wait-time")) {
  504             if (++i == argc) {
  505                 usage(use_noarg, argv[i-1]);
  506             }
  507             errno = 0;
  508             dad_wait_time = (int)strtol(argv[i], &s, 10);
  509             if (errno || (*s != '\0') || (dad_wait_time < 0)) {
  510                 usage("Invalid value for --dad-wait-time: %s",
  511                       argv[i]);
  512             }
  513         } else if (!strcmp(argv[i], "--prefix-len-hint")) {
  514             if (++i == argc) {
  515                 usage(use_noarg, argv[i-1]);
  516             }
  517 
  518             errno = 0;
  519             prefix_len_hint = (int)strtol(argv[i], &s, 10);
  520             if (errno || (*s != '\0') || (prefix_len_hint < 0)) {
  521                 usage("Invalid value for --prefix-len-hint: %s",
  522                       argv[i]);
  523             }
  524         } else if (!strcmp(argv[i], "--address-prefix-len")) {
  525             if (++i == argc) {
  526                 usage(use_noarg, argv[i-1]);
  527             }
  528             errno = 0;
  529             address_prefix_len = (int)strtol(argv[i], &s, 10);
  530             if (errno || (*s != '\0') ||
  531                 (address_prefix_len < 0)) {
  532                 usage("Invalid value for"
  533                       " --address-prefix-len: %s", argv[i]);
  534             }
  535 #endif /* DHCPv6 */
  536         } else if (!strcmp(argv[i], "--decline-wait-time")) {
  537             if (++i == argc) {
  538                 usage(use_noarg, argv[i-1]);
  539             }
  540 
  541             errno = 0;
  542             decline_wait_time = (int)strtol(argv[i], &s, 10);
  543             if (errno || (*s != '\0') ||
  544                 (decline_wait_time < 0)) {
  545                 usage("Invalid value for "
  546                       "--decline-wait-time: %s", argv[i]);
  547             }
  548         } else if (!strcmp(argv[i], "-D")) {
  549             duid_v4 = 1;
  550             if (++i == argc)
  551                 usage(use_noarg, argv[i-1]);
  552             if (!strcasecmp(argv[i], "LL")) {
  553                 duid_type = DUID_LL;
  554             } else if (!strcasecmp(argv[i], "LLT")) {
  555                 duid_type = DUID_LLT;
  556             } else {
  557                 usage("Unknown argument to -D: %s", argv[i]);
  558             }
  559         } else if (!strcmp(argv[i], "-i")) {
  560             /* enable DUID support for DHCPv4 clients */
  561             duid_v4 = 1;
  562         } else if (!strcmp(argv[i], "-I")) {
  563             /* enable standard DHCID support for DDNS updates */
  564             std_dhcid = 1;
  565         } else if (!strcmp(argv[i], "-v")) {
  566             quiet = 0;
  567         } else if (argv[i][0] == '-') {
  568             usage("Unknown command: %s", argv[i]);
  569         } else if (interfaces_requested < 0) {
  570             usage("No interfaces command -n and "
  571                   " requested interface %s", argv[i]);
  572         } else {
  573             struct interface_info *tmp = NULL;
  574 
  575             status = interface_allocate(&tmp, MDL);
  576             if (status != ISC_R_SUCCESS)
  577             log_fatal("Can't record interface %s:%s",
  578                   argv[i], isc_result_totext(status));
  579             if (strlen(argv[i]) >= sizeof(tmp->name))
  580                 log_fatal("%s: interface name too long (is %ld)",
  581                       argv[i], (long)strlen(argv[i]));
  582             strcpy(tmp->name, argv[i]);
  583             if (interfaces) {
  584                 interface_reference(&tmp->next,
  585                         interfaces, MDL);
  586                 interface_dereference(&interfaces, MDL);
  587             }
  588             interface_reference(&interfaces, tmp, MDL);
  589             tmp->flags = INTERFACE_REQUESTED;
  590             interfaces_requested++;
  591         }
  592     }
  593 
  594     if (wanted_ia_na < 0) {
  595         wanted_ia_na = 1;
  596     }
  597 
  598     /* Support only one (requested) interface for Prefix Delegation. */
  599     if (wanted_ia_pd && (interfaces_requested != 1)) {
  600         usage("PD %s only supports one requested interface", "-P");
  601     }
  602 
  603 #if defined(DHCPv6) && defined(DHCP4o6)
  604     if ((local_family == AF_INET6) && dhcpv4_over_dhcpv6 &&
  605         (exit_mode || release_mode))
  606         log_error("Can't relay DHCPv4-over-DHCPv6 "
  607               "without a persistent DHCPv6 client");
  608     if ((local_family == AF_INET) && dhcpv4_over_dhcpv6 &&
  609         (interfaces_requested != 1))
  610         log_fatal("DHCPv4-over-DHCPv6 requires an explicit "
  611               "interface on which to be applied");
  612 #endif
  613 
  614     if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
  615         path_dhclient_conf = s;
  616     }
  617     if (!no_dhclient_db && (s = getenv("PATH_DHCLIENT_DB"))) {
  618         path_dhclient_db = s;
  619     }
  620     if (!no_dhclient_pid && (s = getenv("PATH_DHCLIENT_PID"))) {
  621         path_dhclient_pid = s;
  622     }
  623     if (!no_dhclient_script && (s = getenv("PATH_DHCLIENT_SCRIPT"))) {
  624         path_dhclient_script = s;
  625     }
  626 
  627     /* Set up the initial dhcp option universe. */
  628     initialize_common_option_spaces();
  629 
  630     /* Set up the initial client option universe. */
  631     initialize_client_option_spaces();
  632 
  633     /* Assign v4 or v6 specific running parameters. */
  634     if (local_family == AF_INET)
  635         dhcpv4_client_assignments();
  636 #ifdef DHCPv6
  637     else if (local_family == AF_INET6)
  638         dhcpv6_client_assignments();
  639 #endif /* DHCPv6 */
  640     else
  641         log_fatal("Impossible condition at %s:%d.", MDL);
  642 
  643     /*
  644      * convert relative path names to absolute, for files that need
  645      * to be reopened after chdir() has been called
  646      */
  647     if (path_dhclient_db[0] != '/') {
  648         path_dhclient_db = absolute_path(path_dhclient_db);
  649     }
  650 
  651     if (path_dhclient_script[0] != '/') {
  652         path_dhclient_script = absolute_path(path_dhclient_script);
  653     }
  654 
  655     /*
  656      * See if we should  kill off any currently running client
  657      * we don't try to kill it off if the user told us not
  658      * to write a pid file - we assume they are controlling
  659      * the process in some other fashion.
  660      */
  661     if ((release_mode || exit_mode) && (no_pid_file == ISC_FALSE)) {
  662         FILE *pidfd;
  663         pid_t oldpid;
  664         long temp;
  665         int e;
  666 
  667         if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) {
  668             e = fscanf(pidfd, "%ld\n", &temp);
  669             oldpid = (pid_t)temp;
  670 
  671             if (e != 0 && e != EOF && oldpid) {
  672                 if (kill(oldpid, SIGTERM) == 0) {
  673                     log_info("Killed old client process");
  674                     (void) unlink(path_dhclient_pid);
  675                     /*
  676                      * wait for the old process to
  677                      * cleanly terminate.
  678                      * Note kill() with sig=0 could
  679                      * detect termination but only
  680                      * the parent can be signaled...
  681                      */
  682                     sleep(1);
  683                 } else if (errno == ESRCH) {
  684                     log_info("Removed stale PID file");
  685                     (void) unlink(path_dhclient_pid);
  686                 }
  687             }
  688             fclose(pidfd);
  689         }
  690     }
  691 
  692     if (!quiet) {
  693         log_info("%s %s", message, PACKAGE_VERSION);
  694         log_info(copyright);
  695         log_info(arr);
  696         log_info(url);
  697         log_info("%s", "");
  698     } else {
  699         log_perror = 0;
  700         quiet_interface_discovery = 1;
  701     }
  702 
  703     /* If we're given a relay agent address to insert, for testing
  704        purposes, figure out what it is. */
  705     if (mockup_relay) {
  706         if (!inet_aton(mockup_relay, &giaddr)) {
  707             struct hostent *he;
  708             he = gethostbyname(mockup_relay);
  709             if (he) {
  710                 memcpy(&giaddr, he->h_addr_list[0],
  711                        sizeof giaddr);
  712             } else {
  713                 log_fatal("%s: no such host", mockup_relay);
  714             }
  715         }
  716     }
  717 
  718     /* Get the current time... */
  719     gettimeofday(&cur_tv, NULL);
  720 
  721     sockaddr_broadcast.sin_family = AF_INET;
  722     sockaddr_broadcast.sin_port = remote_port;
  723     if (server) {
  724         if (!inet_aton(server, &sockaddr_broadcast.sin_addr)) {
  725             struct hostent *he;
  726             he = gethostbyname(server);
  727             if (he) {
  728                 memcpy(&sockaddr_broadcast.sin_addr,
  729                        he->h_addr_list[0],
  730                        sizeof sockaddr_broadcast.sin_addr);
  731             } else
  732                 sockaddr_broadcast.sin_addr.s_addr =
  733                     INADDR_BROADCAST;
  734         }
  735     } else {
  736         sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
  737     }
  738 
  739     inaddr_any.s_addr = INADDR_ANY;
  740 
  741     /* Stateless special case. */
  742     if (stateless) {
  743         if (release_mode || (wanted_ia_na > 0) ||
  744             wanted_ia_ta || wanted_ia_pd ||
  745             (interfaces_requested != 1)) {
  746             usage("Stateless command: %s incompatibile with "
  747                   "other commands", "-S");
  748         }
  749 #if defined(DHCPv6) && defined(DHCP4o6)
  750         run_stateless(exit_mode, dhcp4o6_port);
  751 #else
  752         run_stateless(exit_mode, 0);
  753 #endif
  754         finish(0);
  755     }
  756 
  757     /* Discover all the network interfaces. */
  758     discover_interfaces(DISCOVER_UNCONFIGURED);
  759 
  760     /* Parse the dhclient.conf file. */
  761     read_client_conf();
  762 
  763     /* Parse the lease database. */
  764     read_client_leases();
  765 
  766     /* If desired parse the secondary lease database for a DUID */
  767     if ((default_duid.len == 0) && (path_dhclient_duid != NULL)) {
  768         read_client_duid();
  769     }
  770 
  771     /* Rewrite the lease database... */
  772     rewrite_client_leases();
  773 
  774     /* XXX */
  775 /*  config_counter(&snd_counter, &rcv_counter); */
  776 
  777     /*
  778      * If no broadcast interfaces were discovered, call the script
  779      * and tell it so.
  780      */
  781     if (!interfaces) {
  782         /*
  783          * Call dhclient-script with the NBI flag,
  784          * in case somebody cares.
  785          */
  786         script_init(NULL, "NBI", NULL);
  787         script_go(NULL);
  788 
  789         /*
  790          * If we haven't been asked to persist, waiting for new
  791          * interfaces, then just exit.
  792          */
  793         if (!persist) {
  794             /* Nothing more to do. */
  795             log_info("No broadcast interfaces found - exiting.");
  796             finish(0);
  797         }
  798     } else if (!release_mode && !exit_mode) {
  799         /* Call the script with the list of interfaces. */
  800         for (ip = interfaces; ip; ip = ip->next) {
  801             /*
  802              * If interfaces were specified, don't configure
  803              * interfaces that weren't specified!
  804              */
  805             if ((interfaces_requested > 0) &&
  806                 ((ip->flags & (INTERFACE_REQUESTED |
  807                        INTERFACE_AUTOMATIC)) !=
  808                  INTERFACE_REQUESTED))
  809                 continue;
  810 
  811             if (local_family == AF_INET6) {
  812                 script_init(ip->client, "PREINIT6", NULL);
  813             } else {
  814                 script_init(ip->client, "PREINIT", NULL);
  815                     if (ip->client->alias != NULL)
  816                     script_write_params(ip->client,
  817                                 "alias_",
  818                                 ip->client->alias);
  819             }
  820             script_go(ip->client);
  821         }
  822     }
  823 
  824     /* At this point, all the interfaces that the script thinks
  825        are relevant should be running, so now we once again call
  826        discover_interfaces(), and this time ask it to actually set
  827        up the interfaces. */
  828     discover_interfaces(interfaces_requested != 0
  829                 ? DISCOVER_REQUESTED
  830                 : DISCOVER_RUNNING);
  831 
  832     /* PLEASE PREFER the random device: not all systems use random
  833      * process identifiers so the alternative can be predictable. */
  834     seed = 0;
  835     size_t nrnd = 0;
  836 #ifdef ISC_PATH_RANDOMDEV
  837     FILE *frnd = fopen(ISC_PATH_RANDOMDEV, "r");
  838     if (frnd) {
  839         nrnd = fread(&seed, sizeof(seed), 1, frnd);
  840         fclose(frnd);
  841     }
  842 #endif
  843     /* Please leave the compiler to emit a warning about a constant
  844      * condition in the if test. */
  845     if (!nrnd) {
  846         /* Make up a seed for the random number generator from current
  847            time plus the sum of the last four bytes of each
  848            interface's hardware address interpreted as an integer.
  849            Not much entropy, but we're booting, so we're not likely to
  850            find anything better. */
  851 
  852         for (ip = interfaces; ip; ip = ip->next) {
  853             int junk;
  854             memcpy(&junk,
  855                    &ip->hw_address.hbuf[ip->hw_address.hlen -
  856                             sizeof seed], sizeof seed);
  857             seed += junk;
  858         }
  859         seed += cur_time + (unsigned)getpid();
  860     }
  861     srandom(seed);
  862 
  863     /*
  864      * Establish a default DUID.  We always do so for v6 and
  865      * do so if desired for v4 via the -D or -i options
  866      */
  867     if ((local_family == AF_INET6) ||
  868         ((local_family == AF_INET) && (duid_v4 == 1))) {
  869         if (default_duid.len == 0) {
  870             if (default_duid.buffer != NULL)
  871                 data_string_forget(&default_duid, MDL);
  872 
  873             form_duid(&default_duid, MDL);
  874             write_duid(&default_duid);
  875         }
  876     }
  877 
  878 #if defined(DHCPv6) && defined(DHCP4o6)
  879     if (dhcpv4_over_dhcpv6 && !exit_mode)
  880         dhcp4o6_setup(dhcp4o6_port);
  881 #endif
  882 
  883     /* Start a configuration state machine for each interface. */
  884 #ifdef DHCPv6
  885     if (local_family == AF_INET6) {
  886         for (ip = interfaces ; ip != NULL ; ip = ip->next) {
  887             for (client = ip->client ; client != NULL ;
  888                  client = client->next) {
  889                 if (release_mode) {
  890                     start_release6(client);
  891                     continue;
  892                 } else if (exit_mode) {
  893                     unconfigure6(client, "STOP6");
  894                     continue;
  895                 }
  896 
  897                 /* If we have a previous binding, Confirm
  898                  * that we can (or can't) still use it.
  899                  */
  900                 if ((client->active_lease != NULL) &&
  901                     !client->active_lease->released)
  902                     start_confirm6(client);
  903                 else
  904                     start_init6(client);
  905             }
  906         }
  907     } else
  908 #endif /* DHCPv6 */
  909     {
  910         for (ip = interfaces ; ip ; ip = ip->next) {
  911             ip->flags |= INTERFACE_RUNNING;
  912             for (client = ip->client ; client ;
  913                  client = client->next) {
  914                 if (exit_mode)
  915                     state_stop(client);
  916                 if (release_mode)
  917                     do_release(client);
  918                 else {
  919                     client->state = S_INIT;
  920 
  921                     if (top_level_config.initial_delay>0)
  922                     {
  923                         tv.tv_sec = 0;
  924                         if (top_level_config.
  925                             initial_delay>1)
  926                             tv.tv_sec = cur_time
  927                             + random()
  928                             % (top_level_config.
  929                                initial_delay-1);
  930                         tv.tv_usec = random()
  931                             % 1000000;
  932                         /*
  933                          * this gives better
  934                          * distribution than just
  935                          *whole seconds
  936                          */
  937                         add_timeout(&tv, state_reboot,
  938                                     client, 0, 0);
  939                     } else {
  940                         state_reboot(client);
  941                     }
  942                 }
  943             }
  944         }
  945     }
  946 
  947     if (exit_mode)
  948         finish(0);
  949     if (release_mode) {
  950 #ifndef DHCPv6
  951         finish(0);
  952 #else
  953         if ((local_family == AF_INET6) || dhcpv4_over_dhcpv6) {
  954             if (onetry)
  955                 finish(0);
  956         } else
  957             finish(0);
  958 #endif /* DHCPv6 */
  959     }
  960 
  961     /* Start up a listener for the object management API protocol. */
  962     if (top_level_config.omapi_port != -1) {
  963         listener = NULL;
  964         result = omapi_generic_new(&listener, MDL);
  965         if (result != ISC_R_SUCCESS)
  966             log_fatal("Can't allocate new generic object: %s\n",
  967                   isc_result_totext(result));
  968         result = omapi_protocol_listen(listener,
  969                            (unsigned)
  970                            top_level_config.omapi_port,
  971                            1);
  972         if (result != ISC_R_SUCCESS)
  973             log_fatal("Can't start OMAPI protocol: %s",
  974                   isc_result_totext (result));
  975     }
  976 
  977     /* Set up the bootp packet handler... */
  978     bootp_packet_handler = do_packet;
  979 #ifdef DHCPv6
  980     dhcpv6_packet_handler = do_packet6;
  981 #endif /* DHCPv6 */
  982 
  983 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
  984         defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
  985     dmalloc_cutoff_generation = dmalloc_generation;
  986     dmalloc_longterm = dmalloc_outstanding;
  987     dmalloc_outstanding = 0;
  988 #endif
  989 
  990 #if defined(ENABLE_GENTLE_SHUTDOWN)
  991     /* no signal handlers until we deal with the side effects */
  992         /* install signal handlers */
  993     signal(SIGINT, dhcp_signal_handler);   /* control-c */
  994     signal(SIGTERM, dhcp_signal_handler);  /* kill */
  995 #endif
  996 
  997     /* If we're not supposed to wait before getting the address,
  998        don't. */
  999     if (nowait)
 1000         detach();
 1001 
 1002     /* If we're not going to daemonize, write the pid file
 1003        now. */
 1004     if (no_daemon || nowait)
 1005         write_client_pid_file();
 1006 
 1007     /* Start dispatching packets and timeouts... */
 1008     dispatch();
 1009 
 1010     /* In fact dispatch() never returns. */
 1011     return 0;
 1012 }
 1013 
 1014 /*
 1015  * \brief Run the DHCPv6 stateless client (dhclient -6 -S)
 1016  *
 1017  * \param exist_mode set to 1 when dhclient was called with -x
 1018  * \param port DHCPv4-over-DHCPv6 client inter-process communication
 1019  *  UDP port pair (port,port+1 with port in network byte order)
 1020  */
 1021 
 1022 void run_stateless(int exit_mode, u_int16_t port)
 1023 {
 1024 #ifdef DHCPv6
 1025     struct client_state *client;
 1026     omapi_object_t *listener;
 1027     isc_result_t result;
 1028 
 1029 #ifndef DHCP4o6
 1030     IGNORE_UNUSED(port);
 1031 #endif
 1032 
 1033     /* Discover the network interface. */
 1034     discover_interfaces(DISCOVER_REQUESTED);
 1035 
 1036     if (!interfaces)
 1037         usage("No interfaces available for stateless command: %s", "-S");
 1038 
 1039     /* Parse the dhclient.conf file. */
 1040 #ifdef DHCP4o6
 1041     if (dhcpv4_over_dhcpv6) {
 1042         /* Mark we want to request IRT too! */
 1043         dhcpv4_over_dhcpv6++;
 1044     }
 1045 #endif
 1046     read_client_conf();
 1047 
 1048     /* Parse the lease database. */
 1049     read_client_leases();
 1050 
 1051     /* If desired parse the secondary lease database for a DUID */
 1052     if ((default_duid.len == 0) && (path_dhclient_duid != NULL)) {
 1053         read_client_duid();
 1054     }
 1055 
 1056     /* Establish a default DUID. */
 1057     if (default_duid.len == 0) {
 1058         if (default_duid.buffer != NULL)
 1059             data_string_forget(&default_duid, MDL);
 1060 
 1061         form_duid(&default_duid, MDL);
 1062     }
 1063 
 1064 #ifdef DHCP4o6
 1065     if (dhcpv4_over_dhcpv6 && !exit_mode)
 1066         dhcp4o6_setup(port);
 1067 #endif
 1068 
 1069     /* Start a configuration state machine. */
 1070     for (client = interfaces->client ;
 1071          client != NULL ;
 1072          client = client->next) {
 1073         if (exit_mode) {
 1074             unconfigure6(client, "STOP6");
 1075             continue;
 1076         }
 1077         start_info_request6(client);
 1078     }
 1079     if (exit_mode)
 1080         return;
 1081 
 1082     /* Start up a listener for the object management API protocol. */
 1083     if (top_level_config.omapi_port != -1) {
 1084         listener = NULL;
 1085         result = omapi_generic_new(&listener, MDL);
 1086         if (result != ISC_R_SUCCESS)
 1087             log_fatal("Can't allocate new generic object: %s\n",
 1088                   isc_result_totext(result));
 1089         result = omapi_protocol_listen(listener,
 1090                            (unsigned)
 1091                            top_level_config.omapi_port,
 1092                            1);
 1093         if (result != ISC_R_SUCCESS)
 1094             log_fatal("Can't start OMAPI protocol: %s",
 1095                   isc_result_totext(result));
 1096     }
 1097 
 1098     /* Set up the packet handler... */
 1099     dhcpv6_packet_handler = do_packet6;
 1100 
 1101 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
 1102         defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
 1103     dmalloc_cutoff_generation = dmalloc_generation;
 1104     dmalloc_longterm = dmalloc_outstanding;
 1105     dmalloc_outstanding = 0;
 1106 #endif
 1107 
 1108     /* If we're not supposed to wait before getting the address,
 1109        don't. */
 1110     if (nowait)
 1111         detach();
 1112 
 1113     /* If we're not going to daemonize, write the pid file
 1114        now. */
 1115     if (no_daemon || nowait)
 1116         write_client_pid_file();
 1117 
 1118     /* Start dispatching packets and timeouts... */
 1119     dispatch();
 1120 
 1121 #endif /* DHCPv6 */
 1122     return;
 1123 }
 1124 #endif /* !UNIT_TEST */
 1125 
 1126 isc_result_t find_class (struct class **c,
 1127         const char *s, const char *file, int line)
 1128 {
 1129     return 0;
 1130 }
 1131 
 1132 int check_collection (packet, lease, collection)
 1133     struct packet *packet;
 1134     struct lease *lease;
 1135     struct collection *collection;
 1136 {
 1137     return 0;
 1138 }
 1139 
 1140 void classify (packet, class)
 1141     struct packet *packet;
 1142     struct class *class;
 1143 {
 1144 }
 1145 
 1146 void unbill_class (lease)
 1147     struct lease *lease;
 1148 {
 1149 }
 1150 
 1151 int find_subnet (struct subnet **sp,
 1152          struct iaddr addr, const char *file, int line)
 1153 {
 1154     return 0;
 1155 }
 1156 
 1157 /* Individual States:
 1158  *
 1159  * Each routine is called from the dhclient_state_machine() in one of
 1160  * these conditions:
 1161  * -> entering INIT state
 1162  * -> recvpacket_flag == 0: timeout in this state
 1163  * -> otherwise: received a packet in this state
 1164  *
 1165  * Return conditions as handled by dhclient_state_machine():
 1166  * Returns 1, sendpacket_flag = 1: send packet, reset timer.
 1167  * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
 1168  * Returns 0: finish the nap which was interrupted for no good reason.
 1169  *
 1170  * Several per-interface variables are used to keep track of the process:
 1171  *   active_lease: the lease that is being used on the interface
 1172  *                 (null pointer if not configured yet).
 1173  *   offered_leases: leases corresponding to DHCPOFFER messages that have
 1174  *           been sent to us by DHCP servers.
 1175  *   acked_leases: leases corresponding to DHCPACK messages that have been
 1176  *         sent to us by DHCP servers.
 1177  *   sendpacket: DHCP packet we're trying to send.
 1178  *   destination: IP address to send sendpacket to
 1179  * In addition, there are several relevant per-lease variables.
 1180  *   T1_expiry, T2_expiry, lease_expiry: lease milestones
 1181  * In the active lease, these control the process of renewing the lease;
 1182  * In leases on the acked_leases list, this simply determines when we
 1183  * can no longer legitimately use the lease.
 1184  */
 1185 
 1186 void state_reboot (cpp)
 1187     void *cpp;
 1188 {
 1189     struct client_state *client = cpp;
 1190 
 1191 #if defined(DHCPv6) && defined(DHCP4o6)
 1192     if (dhcpv4_over_dhcpv6 && (dhcp4o6_state <= 0)) {
 1193         if (dhcp4o6_state < 0)
 1194             dhcp4o6_poll(NULL);
 1195         client->pending = P_REBOOT;
 1196         return;
 1197     }
 1198 #endif
 1199 
 1200     client->pending= P_NONE;
 1201 
 1202     /* If we don't remember an active lease, go straight to INIT. */
 1203     if (!client -> active ||
 1204         client -> active -> is_bootp ||
 1205         client -> active -> expiry <= cur_time) {
 1206         state_init (client);
 1207         return;
 1208     }
 1209 
 1210     /* We are in the rebooting state. */
 1211     client -> state = S_REBOOTING;
 1212 
 1213     /*
 1214      * make_request doesn't initialize xid because it normally comes
 1215      * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
 1216      * so pick an xid now.
 1217      */
 1218     client -> xid = random ();
 1219 
 1220     /*
 1221      * Make a DHCPREQUEST packet, and set
 1222      * appropriate per-interface flags.
 1223      */
 1224     make_request (client, client -> active);
 1225     client -> destination = iaddr_broadcast;
 1226     client -> first_sending = cur_time;
 1227     client -> interval = client -> config -> initial_interval;
 1228 
 1229     /* Zap the medium list... */
 1230     client -> medium = NULL;
 1231 
 1232     /* Send out the first DHCPREQUEST packet. */
 1233     send_request (client);
 1234 }
 1235 
 1236 /* Called when a lease has completely expired and we've been unable to
 1237    renew it. */
 1238 
 1239 void state_init (cpp)
 1240     void *cpp;
 1241 {
 1242     struct client_state *client = cpp;
 1243 
 1244     ASSERT_STATE(state, S_INIT);
 1245 
 1246     /* Make a DHCPDISCOVER packet, and set appropriate per-interface
 1247        flags. */
 1248     make_discover (client, client -> active);
 1249     client -> xid = client -> packet.xid;
 1250     client -> destination = iaddr_broadcast;
 1251     client -> state = S_SELECTING;
 1252     client -> first_sending = cur_time;
 1253     client -> interval = client -> config -> initial_interval;
 1254 
 1255     /* Add an immediate timeout to cause the first DHCPDISCOVER packet
 1256        to go out. */
 1257     send_discover (client);
 1258 }
 1259 
 1260 /* check_v6only is called by dhcpoffer and dhcpack. It checks if a
 1261  * requested v6-only-preferred option is present and returned the
 1262  * V6ONLY_WAIT delay to suspend DHCPv4. */
 1263 
 1264 uint32_t check_v6only(packet, client)
 1265     struct packet *packet;
 1266     struct client_state *client;
 1267 {
 1268     int i;
 1269     struct option **req;
 1270     isc_boolean_t found = ISC_FALSE;
 1271     struct option_cache *oc;
 1272     struct data_string data;
 1273     uint32_t v6only_wait = 0;
 1274 
 1275     /* Check if the v6-only-preferred was requested. */
 1276     req = client->config->requested_options;
 1277 
 1278     if (req == NULL)
 1279         return 0;
 1280 
 1281     for (i = 0 ; req[i] != NULL ; i++) {
 1282         if ((req[i]->universe == &dhcp_universe) &&
 1283             (req[i]->code == DHO_V6_ONLY_PREFERRED)) {
 1284             found = ISC_TRUE;
 1285             break;
 1286         }
 1287     }
 1288 
 1289     if (found == ISC_FALSE)
 1290         return 0;
 1291 
 1292     /* Get the V6ONLY_WAIT timer. */
 1293     oc = lookup_option(&dhcp_universe, packet->options,
 1294                DHO_V6_ONLY_PREFERRED);
 1295     if (!oc)
 1296         return 0;
 1297 
 1298     memset(&data, 0, sizeof(data));
 1299 
 1300     if (evaluate_option_cache(&data, packet, (struct lease *)0, client,
 1301                   packet->options, (struct option_state *)0,
 1302                   &global_scope, oc, MDL)) {
 1303         if (data.len == 4) {
 1304             v6only_wait = getULong(data.data);
 1305             if (v6only_wait < MIN_V6ONLY_WAIT)
 1306                 v6only_wait = MIN_V6ONLY_WAIT;
 1307         }
 1308         data_string_forget(&data, MDL);
 1309     }
 1310 
 1311     return (v6only_wait);
 1312 }
 1313 
 1314 /* finish_v6only is called when the V6ONLY_WAIT timer expired. */
 1315 
 1316 void finish_v6only(cpp)
 1317     void *cpp;
 1318 {
 1319     struct client_state *client = cpp;
 1320 
 1321     cancel_timeout(finish_v6only, client);
 1322     client->state = S_INIT;
 1323     state_init(cpp);
 1324 }
 1325 
 1326 /*
 1327  * start_v6only is called when a requested v6-only-preferred option was
 1328  * returned by the server. */
 1329 
 1330 void start_v6only(client, v6only_wait)
 1331     struct client_state *client;
 1332     uint32_t v6only_wait;
 1333 {
 1334     struct timeval tv;
 1335 
 1336     /* Enter V6ONLY state. */
 1337 
 1338     client->state = S_V6ONLY;
 1339 
 1340     /* Run the client script. */
 1341     script_init(client, "V6ONLY", NULL);
 1342     if (client->active) {
 1343         script_write_params(client, "old_", client->active);
 1344         destroy_client_lease(client->active);
 1345         client->active = NULL;
 1346     }
 1347     script_write_requested(client);
 1348     client_envadd(client, "", "v6-only-preferred", "%lu",
 1349               (long unsigned)v6only_wait);
 1350     script_go(client);
 1351 
 1352     /* Trigger finish_v6only after V6ONLY_WAIT seconds. */
 1353     tv.tv_sec = cur_tv.tv_sec + v6only_wait;
 1354     tv.tv_usec = cur_tv.tv_usec;
 1355 
 1356     add_timeout(&tv, finish_v6only, client, 0, 0);
 1357 }
 1358 
 1359 /*
 1360  * state_selecting is called when one or more DHCPOFFER packets have been
 1361  * received and a configurable period of time has passed.
 1362  */
 1363 
 1364 void state_selecting (cpp)
 1365     void *cpp;
 1366 {
 1367     struct client_state *client = cpp;
 1368     struct client_lease *lp, *next, *picked;
 1369 
 1370 
 1371     ASSERT_STATE(state, S_SELECTING);
 1372 
 1373     /*
 1374      * Cancel state_selecting and send_discover timeouts, since either
 1375      * one could have got us here.
 1376      */
 1377     cancel_timeout (state_selecting, client);
 1378     cancel_timeout (send_discover, client);
 1379 
 1380     /*
 1381      * We have received one or more DHCPOFFER packets.   Currently,
 1382      * the only criterion by which we judge leases is whether or
 1383      * not we get a response when we arp for them.
 1384      */
 1385     picked = NULL;
 1386     for (lp = client -> offered_leases; lp; lp = next) {
 1387         next = lp -> next;
 1388 
 1389         /*
 1390          * Check to see if we got an ARPREPLY for the address
 1391          * in this particular lease.
 1392          */
 1393         if (!picked) {
 1394             picked = lp;
 1395             picked -> next = NULL;
 1396         } else {
 1397             destroy_client_lease (lp);
 1398         }
 1399     }
 1400     client -> offered_leases = NULL;
 1401 
 1402     /*
 1403      * If we just tossed all the leases we were offered, go back
 1404      * to square one.
 1405      */
 1406     if (!picked) {
 1407         client -> state = S_INIT;
 1408         state_init (client);
 1409         return;
 1410     }
 1411 
 1412     /* If it was a BOOTREPLY, we can just take the address right now. */
 1413     if (picked -> is_bootp) {
 1414         client -> new = picked;
 1415 
 1416         /* Make up some lease expiry times
 1417            XXX these should be configurable. */
 1418         client -> new -> expiry = cur_time + 12000;
 1419         client -> new -> renewal += cur_time + 8000;
 1420         client -> new -> rebind += cur_time + 10000;
 1421 
 1422         client -> state = S_REQUESTING;
 1423 
 1424         /* Bind to the address we received. */
 1425         bind_lease (client);
 1426         return;
 1427     }
 1428 
 1429     /* Go to the REQUESTING state. */
 1430     client -> destination = iaddr_broadcast;
 1431     client -> state = S_REQUESTING;
 1432     client -> first_sending = cur_time;
 1433     client -> interval = client -> config -> initial_interval;
 1434 
 1435     /* Make a DHCPREQUEST packet from the lease we picked. */
 1436     make_request (client, picked);
 1437     client -> xid = client -> packet.xid;
 1438 
 1439     /* Toss the lease we picked - we'll get it back in a DHCPACK. */
 1440     destroy_client_lease (picked);
 1441 
 1442     /* Add an immediate timeout to send the first DHCPREQUEST packet. */
 1443     send_request (client);
 1444 }
 1445 
 1446 /* state_requesting is called when we receive a DHCPACK message after
 1447    having sent out one or more DHCPREQUEST packets. */
 1448 
 1449 void dhcpack (packet)
 1450     struct packet *packet;
 1451 {
 1452     struct interface_info *ip = packet -> interface;
 1453     struct client_state *client;
 1454     uint32_t v6only_wait;
 1455     struct client_lease *lease;
 1456     struct option_cache *oc;
 1457     struct data_string ds;
 1458 
 1459     /* If we're not receptive to an offer right now, or if the offer
 1460        has an unrecognizable transaction id, then just drop it. */
 1461     for (client = ip -> client; client; client = client -> next) {
 1462         if (client -> xid == packet -> raw -> xid)
 1463             break;
 1464     }
 1465     if (!client ||
 1466         (packet -> interface -> hw_address.hlen - 1 !=
 1467          packet -> raw -> hlen) ||
 1468         (memcmp (&packet -> interface -> hw_address.hbuf [1],
 1469              packet -> raw -> chaddr, packet -> raw -> hlen))) {
 1470 #if defined (DEBUG)
 1471         log_debug ("DHCPACK in wrong transaction.");
 1472 #endif
 1473         return;
 1474     }
 1475 
 1476     if (client -> state != S_REBOOTING &&
 1477         client -> state != S_REQUESTING &&
 1478         client -> state != S_RENEWING &&
 1479         client -> state != S_REBINDING) {
 1480 #if defined (DEBUG)
 1481         log_debug ("DHCPACK in wrong state.");
 1482 #endif
 1483         return;
 1484     }
 1485 
 1486     log_info ("DHCPACK of %s from %s",
 1487           inet_ntoa(packet->raw->yiaddr),
 1488           piaddr (packet->client_addr));
 1489 
 1490     /* Check v6only first. */
 1491     v6only_wait = check_v6only(packet, client);
 1492     if (v6only_wait > 0) {
 1493         log_info("v6 only preferred for %lu seconds.",
 1494              (long unsigned)v6only_wait);
 1495         cancel_timeout(send_request, client);
 1496         start_v6only(client, v6only_wait);
 1497         return;
 1498     }
 1499 
 1500     lease = packet_to_lease (packet, client);
 1501     if (!lease) {
 1502         log_info ("packet_to_lease failed.");
 1503         return;
 1504     }
 1505 
 1506     client -> new = lease;
 1507 
 1508     /* Stop resending DHCPREQUEST. */
 1509     cancel_timeout (send_request, client);
 1510 
 1511     /* Figure out the lease time. */
 1512     oc = lookup_option (&dhcp_universe, client -> new -> options,
 1513                 DHO_DHCP_LEASE_TIME);
 1514     memset (&ds, 0, sizeof ds);
 1515     if (oc &&
 1516         evaluate_option_cache (&ds, packet, (struct lease *)0, client,
 1517                    packet -> options, client -> new -> options,
 1518                    &global_scope, oc, MDL)) {
 1519         if (ds.len > 3)
 1520             client -> new -> expiry = getULong (ds.data);
 1521         else
 1522             client -> new -> expiry = 0;
 1523         data_string_forget (&ds, MDL);
 1524     } else
 1525             client -> new -> expiry = 0;
 1526 
 1527     if (client->new->expiry == 0) {
 1528         struct timeval tv;
 1529 
 1530         log_error ("no expiry time on offered lease.");
 1531 
 1532         /* Quench this (broken) server.  Return to INIT to reselect. */
 1533         add_reject(packet);
 1534 
 1535         /* 1/2 second delay to restart at INIT. */
 1536         tv.tv_sec = cur_tv.tv_sec;
 1537         tv.tv_usec = cur_tv.tv_usec + 500000;
 1538 
 1539         if (tv.tv_usec >= 1000000) {
 1540             tv.tv_sec++;
 1541             tv.tv_usec -= 1000000;
 1542         }
 1543 
 1544         add_timeout(&tv, state_init, client, 0, 0);
 1545         return;
 1546     }
 1547 
 1548     /*
 1549      * A number that looks negative here is really just very large,
 1550      * because the lease expiry offset is unsigned.
 1551      */
 1552     if (client->new->expiry < 0)
 1553         client->new->expiry = TIME_MAX;
 1554 
 1555     /* Take the server-provided renewal time if there is one. */
 1556     oc = lookup_option (&dhcp_universe, client -> new -> options,
 1557                 DHO_DHCP_RENEWAL_TIME);
 1558     if (oc &&
 1559         evaluate_option_cache (&ds, packet, (struct lease *)0, client,
 1560                    packet -> options, client -> new -> options,
 1561                    &global_scope, oc, MDL)) {
 1562         if (ds.len > 3)
 1563             client -> new -> renewal = getULong (ds.data);
 1564         else
 1565             client -> new -> renewal = 0;
 1566         data_string_forget (&ds, MDL);
 1567     } else
 1568             client -> new -> renewal = 0;
 1569 
 1570     /* If it wasn't specified by the server, calculate it. */
 1571     if (!client -> new -> renewal)
 1572         client -> new -> renewal = client -> new -> expiry / 2 + 1;
 1573 
 1574     if (client -> new -> renewal <= 0)
 1575         client -> new -> renewal = TIME_MAX;
 1576 
 1577     /* Now introduce some randomness to the renewal time: */
 1578     if (client->new->renewal <= ((TIME_MAX / 3) - 3))
 1579         client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
 1580                 (((random() % client->new->renewal) + 3) / 4);
 1581 
 1582     /* Same deal with the rebind time. */
 1583     oc = lookup_option (&dhcp_universe, client -> new -> options,
 1584                 DHO_DHCP_REBINDING_TIME);
 1585     if (oc &&
 1586         evaluate_option_cache (&ds, packet, (struct lease *)0, client,
 1587                    packet -> options, client -> new -> options,
 1588                    &global_scope, oc, MDL)) {
 1589         if (ds.len > 3)
 1590             client -> new -> rebind = getULong (ds.data);
 1591         else
 1592             client -> new -> rebind = 0;
 1593         data_string_forget (&ds, MDL);
 1594     } else
 1595             client -> new -> rebind = 0;
 1596 
 1597     if (client -> new -> rebind <= 0) {
 1598         if (client -> new -> expiry <= TIME_MAX / 7)
 1599             client -> new -> rebind =
 1600                     client -> new -> expiry * 7 / 8;
 1601         else
 1602             client -> new -> rebind =
 1603                     client -> new -> expiry / 8 * 7;
 1604     }
 1605 
 1606     /* Make sure our randomness didn't run the renewal time past the
 1607        rebind time. */
 1608     if (client -> new -> renewal > client -> new -> rebind) {
 1609         if (client -> new -> rebind <= TIME_MAX / 3)
 1610             client -> new -> renewal =
 1611                     client -> new -> rebind * 3 / 4;
 1612         else
 1613             client -> new -> renewal =
 1614                     client -> new -> rebind / 4 * 3;
 1615     }
 1616 
 1617     client -> new -> expiry += cur_time;
 1618     /* Lease lengths can never be negative. */
 1619     if (client -> new -> expiry < cur_time)
 1620         client -> new -> expiry = TIME_MAX;
 1621     client -> new -> renewal += cur_time;
 1622     if (client -> new -> renewal < cur_time)
 1623         client -> new -> renewal = TIME_MAX;
 1624     client -> new -> rebind += cur_time;
 1625     if (client -> new -> rebind < cur_time)
 1626         client -> new -> rebind = TIME_MAX;
 1627 
 1628     bind_lease (client);
 1629 }
 1630 
 1631 void bind_lease (client)
 1632     struct client_state *client;
 1633 {
 1634     struct timeval tv;
 1635 
 1636     /* Remember the medium. */
 1637     client->new->medium = client->medium;
 1638 
 1639     /* Run the client script with the new parameters. */
 1640     script_init(client, (client->state == S_REQUESTING ? "BOUND" :
 1641                  (client->state == S_RENEWING ? "RENEW" :
 1642                   (client->state == S_REBOOTING ? "REBOOT" :
 1643                    "REBIND"))),
 1644             client->new->medium);
 1645     if (client->active && client->state != S_REBOOTING)
 1646         script_write_params(client, "old_", client->active);
 1647     script_write_params(client, "new_", client->new);
 1648     script_write_requested(client);
 1649     if (client->alias)
 1650         script_write_params(client, "alias_", client->alias);
 1651 
 1652     /* If the BOUND/RENEW code detects another machine using the
 1653        offered address, then per our man page it should exit with
 1654        a non-zero status, to which we send a DHCPDECLINE and toss
 1655        the lease. A return value of less than zero indicates
 1656        the script crashed (e.g. segfault) which script_go will log
 1657        but we will ignore here. */
 1658     if (script_go(client) > 0)  {
 1659         make_decline(client, client->new);
 1660         send_decline(client);
 1661         destroy_client_lease(client->new);
 1662         client->new = NULL;
 1663         if (onetry) {
 1664             if (!quiet) {
 1665                 log_info("Unable to obtain a lease on first "
 1666                      "try (declined).  Exiting.");
 1667             }
 1668 
 1669 #if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
 1670             /* Let's call a script and we're done */
 1671             script_init(client, "FAIL", (struct string_list *)0);
 1672             script_go(client);
 1673 #endif
 1674             finish(2);
 1675         } else {
 1676             struct timeval tv;
 1677             tv.tv_sec = cur_tv.tv_sec + decline_wait_time;
 1678             tv.tv_usec = cur_tv.tv_usec;
 1679             add_timeout(&tv, state_init, client, 0, 0);
 1680             return;
 1681         }
 1682     }
 1683 
 1684     /* Write out the new lease if it has been long enough. */
 1685     if (!client->last_write ||
 1686         (cur_time - client->last_write) >= MIN_LEASE_WRITE)
 1687         write_client_lease(client, client->new, 0, 1);
 1688 
 1689     /* Replace the old active lease with the new one. */
 1690     if (client->active) {
 1691         if (client->active->is_static) {
 1692             // We need to preserve the fallback lease in case
 1693             // we lose DHCP service again.
 1694             add_to_tail(&client->leases, client->active);
 1695         } else {
 1696             destroy_client_lease(client->active);
 1697         }
 1698     }
 1699 
 1700     client->active = client->new;
 1701     client->new = NULL;
 1702 
 1703     /* Set up a timeout to start the renewal process. */
 1704     tv.tv_sec = client->active->renewal;
 1705     tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ?
 1706             random() % 1000000 : cur_tv.tv_usec;
 1707     add_timeout(&tv, state_bound, client, 0, 0);
 1708 
 1709     log_info("bound to %s -- renewal in %ld seconds.",
 1710           piaddr(client->active->address),
 1711           (long)(client->active->renewal - cur_time));
 1712     client->state = S_BOUND;
 1713     reinitialize_interfaces();
 1714     detach();
 1715 #if defined (NSUPDATE)
 1716     if (client->config->do_forward_update)
 1717         dhclient_schedule_updates(client, &client->active->address, 1);
 1718 #endif /* defined NSUPDATE */
 1719 
 1720 }
 1721 
 1722 /* state_bound is called when we've successfully bound to a particular
 1723    lease, but the renewal time on that lease has expired.   We are
 1724    expected to unicast a DHCPREQUEST to the server that gave us our
 1725    original lease. */
 1726 
 1727 void state_bound (cpp)
 1728     void *cpp;
 1729 {
 1730     struct client_state *client = cpp;
 1731     struct option_cache *oc;
 1732     struct data_string ds;
 1733 
 1734     ASSERT_STATE(state, S_BOUND);
 1735 
 1736     /* T1 has expired. */
 1737     make_request (client, client -> active);
 1738     client -> xid = client -> packet.xid;
 1739 
 1740     memset (&ds, 0, sizeof ds);
 1741     oc = lookup_option (&dhcp_universe, client -> active -> options,
 1742                 DHO_DHCP_SERVER_IDENTIFIER);
 1743     if (oc &&
 1744         evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
 1745                    client, (struct option_state *)0,
 1746                    client -> active -> options,
 1747                    &global_scope, oc, MDL)) {
 1748         if (ds.len > 3) {
 1749             memcpy (client -> destination.iabuf, ds.data, 4);
 1750             client -> destination.len = 4;
 1751         } else
 1752             client -> destination = iaddr_broadcast;
 1753 
 1754         data_string_forget (&ds, MDL);
 1755     } else
 1756         client -> destination = iaddr_broadcast;
 1757 
 1758     client -> first_sending = cur_time;
 1759     client -> interval = client -> config -> initial_interval;
 1760     client -> state = S_RENEWING;
 1761 
 1762     /* Send the first packet immediately. */
 1763     send_request (client);
 1764 }
 1765 
 1766 /* state_stop is called when we've been told to shut down.   We unconfigure
 1767    the interfaces, and then stop operating until told otherwise. */
 1768 
 1769 void state_stop (cpp)
 1770     void *cpp;
 1771 {
 1772     struct client_state *client = cpp;
 1773 
 1774     client->pending = P_NONE;
 1775 
 1776     /* Cancel all timeouts. */
 1777     cancel_timeout(state_selecting, client);
 1778     cancel_timeout(send_discover, client);
 1779     cancel_timeout(send_request, client);
 1780     cancel_timeout(state_bound, client);
 1781     cancel_timeout(finish_v6only, client);
 1782 
 1783     /* If we have an address, unconfigure it. */
 1784     if (client->active) {
 1785         script_init(client, "STOP", client->active->medium);
 1786         script_write_params(client, "old_", client->active);
 1787         script_write_requested(client);
 1788         if (client->alias)
 1789             script_write_params(client, "alias_", client->alias);
 1790         script_go(client);
 1791     }
 1792 }
 1793 
 1794 int commit_leases ()
 1795 {
 1796     return 0;
 1797 }
 1798 
 1799 int write_lease (lease)
 1800     struct lease *lease;
 1801 {
 1802     return 0;
 1803 }
 1804 
 1805 int write_host (host)
 1806     struct host_decl *host;
 1807 {
 1808     return 0;
 1809 }
 1810 
 1811 void db_startup (testp)
 1812     int testp;
 1813 {
 1814 }
 1815 
 1816 void bootp (packet)
 1817     struct packet *packet;
 1818 {
 1819     struct iaddrmatchlist *ap;
 1820     char addrbuf[4*16];
 1821     char maskbuf[4*16];
 1822 
 1823     if (packet -> raw -> op != BOOTREPLY)
 1824         return;
 1825 
 1826     /* If there's a reject list, make sure this packet's sender isn't
 1827        on it. */
 1828     for (ap = packet -> interface -> client -> config -> reject_list;
 1829          ap; ap = ap -> next) {
 1830         if (addr_match(&packet->client_addr, &ap->match)) {
 1831 
 1832                 /* piaddr() returns its result in a static
 1833                buffer sized 4*16 (see common/inet.c). */
 1834 
 1835                 strcpy(addrbuf, piaddr(ap->match.addr));
 1836                 strcpy(maskbuf, piaddr(ap->match.mask));
 1837 
 1838             log_info("BOOTREPLY from %s rejected by rule %s "
 1839                  "mask %s.", piaddr(packet->client_addr),
 1840                  addrbuf, maskbuf);
 1841             return;
 1842         }
 1843     }
 1844 
 1845     dhcpoffer (packet);
 1846 
 1847 }
 1848 
 1849 void dhcp (packet)
 1850     struct packet *packet;
 1851 {
 1852     struct iaddrmatchlist *ap;
 1853     void (*handler) (struct packet *);
 1854     const char *type;
 1855     char addrbuf[4*16];
 1856     char maskbuf[4*16];
 1857 
 1858     switch (packet -> packet_type) {
 1859           case DHCPOFFER:
 1860         handler = dhcpoffer;
 1861         type = "DHCPOFFER";
 1862         break;
 1863 
 1864           case DHCPNAK:
 1865         handler = dhcpnak;
 1866         type = "DHCPNACK";
 1867         break;
 1868 
 1869           case DHCPACK:
 1870         handler = dhcpack;
 1871         type = "DHCPACK";
 1872         break;
 1873 
 1874           default:
 1875         return;
 1876     }
 1877 
 1878     /* If there's a reject list, make sure this packet's sender isn't
 1879        on it. */
 1880     for (ap = packet -> interface -> client -> config -> reject_list;
 1881          ap; ap = ap -> next) {
 1882         if (addr_match(&packet->client_addr, &ap->match)) {
 1883 
 1884                 /* piaddr() returns its result in a static
 1885                buffer sized 4*16 (see common/inet.c). */
 1886 
 1887                 strcpy(addrbuf, piaddr(ap->match.addr));
 1888                 strcpy(maskbuf, piaddr(ap->match.mask));
 1889 
 1890             log_info("%s from %s rejected by rule %s mask %s.",
 1891                  type, piaddr(packet->client_addr),
 1892                  addrbuf, maskbuf);
 1893             return;
 1894         }
 1895     }
 1896     (*handler) (packet);
 1897 }
 1898 
 1899 #ifdef DHCPv6
 1900 void
 1901 dhcpv6(struct packet *packet) {
 1902     struct iaddrmatchlist *ap;
 1903     struct client_state *client;
 1904     char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
 1905 
 1906     /* Silently drop bogus messages. */
 1907     if (packet->dhcpv6_msg_type >= dhcpv6_type_name_max)
 1908         return;
 1909 
 1910     /* Discard, with log, packets from quenched sources. */
 1911     for (ap = packet->interface->client->config->reject_list ;
 1912          ap ; ap = ap->next) {
 1913         if (addr_match(&packet->client_addr, &ap->match)) {
 1914             strcpy(addrbuf, piaddr(packet->client_addr));
 1915             log_info("%s from %s rejected by rule %s",
 1916                  dhcpv6_type_names[packet->dhcpv6_msg_type],
 1917                  addrbuf,
 1918                  piaddrmask(&ap->match.addr, &ap->match.mask));
 1919             return;
 1920         }
 1921     }
 1922 
 1923     /* Screen out nonsensical messages. */
 1924     switch(packet->dhcpv6_msg_type) {
 1925 #ifdef DHCP4o6
 1926           case DHCPV6_DHCPV4_RESPONSE:
 1927         if (dhcpv4_over_dhcpv6) {
 1928           log_info("RCV: %s message on %s from %s.",
 1929                dhcpv6_type_names[packet->dhcpv6_msg_type],
 1930                packet->interface->name,
 1931                piaddr(packet->client_addr));
 1932           forw_dhcpv4_response(packet);
 1933         }
 1934         return;
 1935 #endif
 1936           case DHCPV6_ADVERTISE:
 1937           case DHCPV6_RECONFIGURE:
 1938         if (stateless)
 1939           return;
 1940           /* Falls through */
 1941           case DHCPV6_REPLY:
 1942         log_info("RCV: %s message on %s from %s.",
 1943              dhcpv6_type_names[packet->dhcpv6_msg_type],
 1944              packet->interface->name, piaddr(packet->client_addr));
 1945         break;
 1946 
 1947           default:
 1948         return;
 1949     }
 1950 
 1951     /* Find a client state that matches the incoming XID. */
 1952     for (client = packet->interface->client ; client ;
 1953          client = client->next) {
 1954         if (memcmp(&client->dhcpv6_transaction_id,
 1955                packet->dhcpv6_transaction_id, 3) == 0) {
 1956             client->v6_handler(packet, client);
 1957             return;
 1958         }
 1959     }
 1960 
 1961     /* XXX: temporary log for debugging */
 1962     log_info("Packet received, but nothing done with it.");
 1963 }
 1964 
 1965 #ifdef DHCP4o6
 1966 /*
 1967  * \brief Forward a DHCPv4-response to the DHCPv4 client.
 1968  *  (DHCPv6 client function)
 1969  *
 1970  * The DHCPv6 client receives a DHCPv4-response which is forwarded
 1971  * to the DHCPv4 client.
 1972  * Format: address:16 + DHCPv4 message content
 1973  * (we have no state to keep the address so it is transported in
 1974  *  DHCPv6 <-> DHCPv6 inter-process messages)
 1975  *
 1976  * \param packet the DHCPv4-response packet
 1977  */
 1978 static void forw_dhcpv4_response(struct packet *packet)
 1979 {
 1980     struct option_cache *oc;
 1981     struct data_string enc_opt_data;
 1982     struct data_string ds;
 1983     int cc;
 1984 
 1985     /*
 1986      * Discard if relay is not ready.
 1987      */
 1988     if (dhcp4o6_state == -1) {
 1989         log_info("forw_dhcpv4_response: not ready.");
 1990         return;
 1991     }
 1992 
 1993     if (packet->client_addr.len != 16) {
 1994         log_error("forw_dhcpv4_response: bad address");
 1995         return;
 1996     }
 1997 
 1998     /*
 1999      * Get our encapsulated DHCPv4 message.
 2000      */
 2001     oc = lookup_option(&dhcpv6_universe, packet->options, D6O_DHCPV4_MSG);
 2002     if (oc == NULL) {
 2003         log_info("DHCPv4-response from %s missing "
 2004              "DHCPv4 Message option.",
 2005              piaddr(packet->client_addr));
 2006         return;
 2007     }
 2008 
 2009     memset(&enc_opt_data, 0, sizeof(enc_opt_data));
 2010     if (!evaluate_option_cache(&enc_opt_data, NULL, NULL, NULL,
 2011                    NULL, NULL, &global_scope, oc, MDL)) {
 2012         log_error("forw_dhcpv4_response: error evaluating "
 2013               "DHCPv4 message.");
 2014         data_string_forget(&enc_opt_data, MDL);
 2015         return;
 2016     }
 2017 
 2018     if (enc_opt_data.len < DHCP_FIXED_NON_UDP) {
 2019         log_error("forw_dhcpv4_response: "
 2020               "no memory for encapsulated packet.");
 2021         data_string_forget(&enc_opt_data, MDL);
 2022         return;
 2023     }
 2024 
 2025     /*
 2026      * Append address.
 2027      */
 2028     memset(&ds, 0, sizeof(ds));
 2029     if (!buffer_allocate(&ds.buffer, enc_opt_data.len + 16, MDL)) {
 2030         log_error("forw_dhcpv4_response: no memory buffer.");
 2031         data_string_forget(&enc_opt_data, MDL);
 2032         return;
 2033     }
 2034     ds.data = ds.buffer->data;
 2035     ds.len = enc_opt_data.len + 16;
 2036     memcpy(ds.buffer->data, enc_opt_data.data, enc_opt_data.len);
 2037     memcpy(ds.buffer->data + enc_opt_data.len,
 2038            packet->client_addr.iabuf, 16);
 2039     data_string_forget(&enc_opt_data, MDL);
 2040 
 2041     /*
 2042      * Forward them.
 2043      */
 2044     cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
 2045     if (cc < 0)
 2046         log_error("forw_dhcpv4_response: send(): %m");
 2047 
 2048     data_string_forget(&ds, MDL);
 2049 }
 2050 
 2051 /*
 2052  * \brief Receive a DHCPv4-response from the DHCPv6 client.
 2053  *  (DHCPv4 client function)
 2054  *
 2055  * The DHCPv4 client receives a DHCPv4-response forwarded
 2056  * by the DHCPv6 client (using \ref forw_dhcpv4_response())
 2057  *
 2058  * \param raw the DHCPv4-response raw packet
 2059  */
 2060 static void recv_dhcpv4_response(struct data_string *raw)
 2061 {
 2062     struct packet *packet;
 2063     struct iaddr from;
 2064 
 2065     if (interfaces == NULL) {
 2066         log_error("recv_dhcpv4_response: no interfaces.");
 2067         return;
 2068     }
 2069 
 2070     from.len = 16;
 2071     memcpy(from.iabuf, raw->data + (raw->len - 16), 16);
 2072 
 2073     /*
 2074      * Build a packet structure.
 2075      */
 2076     packet = NULL;
 2077     if (!packet_allocate(&packet, MDL)) {
 2078         log_error("recv_dhcpv4_response: no memory for packet.");
 2079         return;
 2080     }
 2081 
 2082     packet->raw = (struct dhcp_packet *) raw->data;
 2083     packet->packet_length = raw->len - 16;
 2084     packet->client_port = remote_port;
 2085     packet->client_addr = from;
 2086     interface_reference(&packet->interface, interfaces, MDL);
 2087 
 2088     /* Allocate packet->options now so it is non-null for all packets */
 2089     if (!option_state_allocate (&packet->options, MDL)) {
 2090         log_error("recv_dhcpv4_response: no memory for options.");
 2091         packet_dereference (&packet, MDL);
 2092         return;
 2093     }
 2094 
 2095     /* If there's an option buffer, try to parse it. */
 2096     if (packet->packet_length >= DHCP_FIXED_NON_UDP + 4) {
 2097         struct option_cache *op;
 2098         if (!parse_options(packet)) {
 2099             if (packet->options)
 2100                 option_state_dereference
 2101                     (&packet->options, MDL);
 2102             packet_dereference (&packet, MDL);
 2103             return;
 2104         }
 2105 
 2106         if (packet->options_valid &&
 2107             (op = lookup_option(&dhcp_universe,
 2108                     packet->options,
 2109                     DHO_DHCP_MESSAGE_TYPE))) {
 2110             struct data_string dp;
 2111             memset(&dp, 0, sizeof dp);
 2112             evaluate_option_cache(&dp, packet, NULL, NULL,
 2113                           packet->options, NULL,
 2114                           NULL, op, MDL);
 2115             if (dp.len > 0)
 2116                 packet->packet_type = dp.data[0];
 2117             else
 2118                 packet->packet_type = 0;
 2119             data_string_forget(&dp, MDL);
 2120         }
 2121     }
 2122 
 2123     if (validate_packet(packet) != 0) {
 2124         if (packet->packet_type)
 2125             dhcp(packet);
 2126         else
 2127             bootp(packet);
 2128     }
 2129 
 2130     /* If the caller kept the packet, they'll have upped the refcnt. */
 2131     packet_dereference(&packet, MDL);
 2132 }
 2133 #endif /* DHCP4o6 */
 2134 #endif /* DHCPv6 */
 2135 
 2136 void dhcpoffer (packet)
 2137     struct packet *packet;
 2138 {
 2139     struct interface_info *ip = packet -> interface;
 2140     struct client_state *client;
 2141     uint32_t v6only_wait;
 2142     struct client_lease *lease, *lp;
 2143     struct option **req;
 2144     int i;
 2145     int stop_selecting;
 2146     const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
 2147     char obuf [1024];
 2148     struct timeval tv;
 2149 
 2150 #ifdef DEBUG_PACKET
 2151     dump_packet (packet);
 2152 #endif
 2153 
 2154     /* Find a client state that matches the xid... */
 2155     for (client = ip -> client; client; client = client -> next)
 2156         if (client -> xid == packet -> raw -> xid)
 2157             break;
 2158 
 2159     /* If we're not receptive to an offer right now, or if the offer
 2160        has an unrecognizable transaction id, then just drop it. */
 2161     if (!client ||
 2162         client -> state != S_SELECTING ||
 2163         (packet -> interface -> hw_address.hlen - 1 !=
 2164          packet -> raw -> hlen) ||
 2165         (memcmp (&packet -> interface -> hw_address.hbuf [1],
 2166              packet -> raw -> chaddr, packet -> raw -> hlen))) {
 2167 #if defined (DEBUG)
 2168         log_debug ("%s in wrong transaction.", name);
 2169 #endif
 2170         return;
 2171     }
 2172 
 2173     sprintf (obuf, "%s of %s from %s", name,
 2174          inet_ntoa(packet->raw->yiaddr),
 2175          piaddr(packet->client_addr));
 2176 
 2177     /* Check v6only first. */
 2178     v6only_wait = check_v6only(packet, client);
 2179     if (v6only_wait > 0) {
 2180         log_info("%s: v6 only preferred for %lu.", obuf,
 2181              (long unsigned)v6only_wait);
 2182         cancel_timeout(send_discover, client);
 2183         start_v6only(client, v6only_wait);
 2184         return;
 2185     }
 2186 
 2187     /* If this lease doesn't supply the minimum required DHCPv4 parameters,
 2188      * ignore it.
 2189      */
 2190     req = client->config->required_options;
 2191     if (req != NULL) {
 2192         for (i = 0 ; req[i] != NULL ; i++) {
 2193             if ((req[i]->universe == &dhcp_universe) &&
 2194                 !lookup_option(&dhcp_universe, packet->options,
 2195                        req[i]->code)) {
 2196                 struct option *option = NULL;
 2197                 unsigned code = req[i]->code;
 2198 
 2199                 option_code_hash_lookup(&option,
 2200                             dhcp_universe.code_hash,
 2201                             &code, 0, MDL);
 2202 
 2203                 if (option)
 2204                     log_info("%s: no %s option.", obuf,
 2205                          option->name);
 2206                 else
 2207                     log_info("%s: no unknown-%u option.",
 2208                          obuf, code);
 2209 
 2210                 option_dereference(&option, MDL);
 2211 
 2212                 return;
 2213             }
 2214         }
 2215     }
 2216 
 2217     /* If we've already seen this lease, don't record it again. */
 2218     for (lease = client -> offered_leases; lease; lease = lease -> next) {
 2219         if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
 2220             !memcmp (lease -> address.iabuf,
 2221                  &packet -> raw -> yiaddr, lease -> address.len)) {
 2222             log_debug ("%s: already seen.", obuf);
 2223             return;
 2224         }
 2225     }
 2226 
 2227     lease = packet_to_lease (packet, client);
 2228     if (!lease) {
 2229         log_info ("%s: packet_to_lease failed.", obuf);
 2230         return;
 2231     }
 2232 
 2233     /* log it now, so it emits before the request goes out */
 2234     log_info("%s", obuf);
 2235 
 2236     /* If this lease was acquired through a BOOTREPLY, record that
 2237        fact. */
 2238     if (!packet -> options_valid || !packet -> packet_type)
 2239         lease -> is_bootp = 1;
 2240 
 2241     /* Record the medium under which this lease was offered. */
 2242     lease -> medium = client -> medium;
 2243 
 2244     /* Figure out when we're supposed to stop selecting. */
 2245     stop_selecting = (client -> first_sending +
 2246               client -> config -> select_interval);
 2247 
 2248     /* If this is the lease we asked for, put it at the head of the
 2249        list, and don't mess with the arp request timeout. */
 2250     if (lease -> address.len == client -> requested_address.len &&
 2251         !memcmp (lease -> address.iabuf,
 2252              client -> requested_address.iabuf,
 2253              client -> requested_address.len)) {
 2254         lease -> next = client -> offered_leases;
 2255         client -> offered_leases = lease;
 2256     } else {
 2257         /* Put the lease at the end of the list. */
 2258         lease -> next = (struct client_lease *)0;
 2259         if (!client -> offered_leases)
 2260             client -> offered_leases = lease;
 2261         else {
 2262             for (lp = client -> offered_leases; lp -> next;
 2263                  lp = lp -> next)
 2264                 ;
 2265             lp -> next = lease;
 2266         }
 2267     }
 2268 
 2269     /* If the selecting interval has expired, go immediately to
 2270        state_selecting().  Otherwise, time out into
 2271        state_selecting at the select interval. */
 2272     if (stop_selecting <= cur_tv.tv_sec)
 2273         state_selecting (client);
 2274     else {
 2275         tv.tv_sec = stop_selecting;
 2276         tv.tv_usec = cur_tv.tv_usec;
 2277         add_timeout(&tv, state_selecting, client, 0, 0);
 2278         cancel_timeout(send_discover, client);
 2279     }
 2280 }
 2281 
 2282 /* Allocate a client_lease structure and initialize it from the parameters
 2283    in the specified packet. */
 2284 
 2285 struct client_lease *packet_to_lease (packet, client)
 2286     struct packet *packet;
 2287     struct client_state *client;
 2288 {
 2289     struct client_lease *lease;
 2290     unsigned i;
 2291     struct option_cache *oc;
 2292     struct option *option = NULL;
 2293     struct data_string data;
 2294 
 2295     lease = (struct client_lease *)new_client_lease (MDL);
 2296 
 2297     if (!lease) {
 2298         log_error("packet_to_lease: no memory to record lease.\n");
 2299         return NULL;
 2300     }
 2301 
 2302     memset(lease, 0, sizeof(*lease));
 2303 
 2304     /* Copy the lease options. */
 2305     option_state_reference(&lease->options, packet->options, MDL);
 2306 
 2307     lease->address.len = sizeof(packet->raw->yiaddr);
 2308     memcpy(lease->address.iabuf, &packet->raw->yiaddr,
 2309            lease->address.len);
 2310 
 2311     lease->next_srv_addr.len = sizeof(packet->raw->siaddr);
 2312     memcpy(lease->next_srv_addr.iabuf, &packet->raw->siaddr,
 2313            lease->next_srv_addr.len);
 2314 
 2315     memset(&data, 0, sizeof(data));
 2316 
 2317     if (client -> config -> vendor_space_name) {
 2318         i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
 2319 
 2320         /* See if there was a vendor encapsulation option. */
 2321         oc = lookup_option (&dhcp_universe, lease -> options, i);
 2322         if (oc &&
 2323             client -> config -> vendor_space_name &&
 2324             evaluate_option_cache (&data, packet,
 2325                        (struct lease *)0, client,
 2326                        packet -> options, lease -> options,
 2327                        &global_scope, oc, MDL)) {
 2328             if (data.len) {
 2329                 if (!option_code_hash_lookup(&option,
 2330                         dhcp_universe.code_hash,
 2331                         &i, 0, MDL))
 2332                     log_fatal("Unable to find VENDOR "
 2333                           "option (%s:%d).", MDL);
 2334                 parse_encapsulated_suboptions
 2335                     (packet -> options, option,
 2336                      data.data, data.len, &dhcp_universe,
 2337                      client -> config -> vendor_space_name
 2338                         );
 2339 
 2340                 option_dereference(&option, MDL);
 2341             }
 2342             data_string_forget (&data, MDL);
 2343         }
 2344     } else
 2345         i = 0;
 2346 
 2347     /* Figure out the overload flag. */
 2348     oc = lookup_option (&dhcp_universe, lease -> options,
 2349                 DHO_DHCP_OPTION_OVERLOAD);
 2350     if (oc &&
 2351         evaluate_option_cache (&data, packet, (struct lease *)0, client,
 2352                    packet -> options, lease -> options,
 2353                    &global_scope, oc, MDL)) {
 2354         if (data.len > 0)
 2355             i = data.data [0];
 2356         else
 2357             i = 0;
 2358         data_string_forget (&data, MDL);
 2359     } else
 2360         i = 0;
 2361 
 2362     /* If the server name was filled out, copy it. */
 2363     if (!(i & 2) && packet -> raw -> sname [0]) {
 2364         unsigned len;
 2365         /* Don't count on the NUL terminator. */
 2366         for (len = 0; len < DHCP_SNAME_LEN; len++)
 2367             if (!packet -> raw -> sname [len])
 2368                 break;
 2369         lease -> server_name = dmalloc (len + 1, MDL);
 2370         if (!lease -> server_name) {
 2371             log_error ("dhcpoffer: no memory for server name.\n");
 2372             destroy_client_lease (lease);
 2373             return (struct client_lease *)0;
 2374         } else {
 2375             memcpy (lease -> server_name,
 2376                 packet -> raw -> sname, len);
 2377             lease -> server_name [len] = 0;
 2378         }
 2379     }
 2380 
 2381     /* Ditto for the filename. */
 2382     if (!(i & 1) && packet -> raw -> file [0]) {
 2383         unsigned len;
 2384         /* Don't count on the NUL terminator. */
 2385         for (len = 0; len < DHCP_FILE_LEN; len++)
 2386             if (!packet -> raw -> file [len])
 2387                 break;
 2388         lease -> filename = dmalloc (len + 1, MDL);
 2389         if (!lease -> filename) {
 2390             log_error ("dhcpoffer: no memory for filename.\n");
 2391             destroy_client_lease (lease);
 2392             return (struct client_lease *)0;
 2393         } else {
 2394             memcpy (lease -> filename,
 2395                 packet -> raw -> file, len);
 2396             lease -> filename [len] = 0;
 2397         }
 2398     }
 2399 
 2400     execute_statements_in_scope(NULL, (struct packet *)packet, NULL,
 2401                     client, lease->options, lease->options,
 2402                     &global_scope, client->config->on_receipt,
 2403                     NULL, NULL);
 2404 
 2405     return lease;
 2406 }
 2407 
 2408 void dhcpnak (packet)
 2409     struct packet *packet;
 2410 {
 2411     struct interface_info *ip = packet -> interface;
 2412     struct client_state *client;
 2413 
 2414     /* Find a client state that matches the xid... */
 2415     for (client = ip -> client; client; client = client -> next)
 2416         if (client -> xid == packet -> raw -> xid)
 2417             break;
 2418 
 2419     /* If we're not receptive to an offer right now, or if the offer
 2420        has an unrecognizable transaction id, then just drop it. */
 2421     if (!client ||
 2422         (packet -> interface -> hw_address.hlen - 1 !=
 2423          packet -> raw -> hlen) ||
 2424         (memcmp (&packet -> interface -> hw_address.hbuf [1],
 2425              packet -> raw -> chaddr, packet -> raw -> hlen))) {
 2426 #if defined (DEBUG)
 2427         log_debug ("DHCPNAK in wrong transaction.");
 2428 #endif
 2429         return;
 2430     }
 2431 
 2432     if (client -> state != S_REBOOTING &&
 2433         client -> state != S_REQUESTING &&
 2434         client -> state != S_RENEWING &&
 2435         client -> state != S_REBINDING) {
 2436 #if defined (DEBUG)
 2437         log_debug ("DHCPNAK in wrong state.");
 2438 #endif
 2439         return;
 2440     }
 2441 
 2442     log_info ("DHCPNAK from %s", piaddr (packet -> client_addr));
 2443 
 2444     if (!client -> active) {
 2445 #if defined (DEBUG)
 2446         log_info ("DHCPNAK with no active lease.\n");
 2447 #endif
 2448         return;
 2449     }
 2450 
 2451     /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
 2452      * to indicate that we want all old bindings to be removed.  (It
 2453      * is possible that we may get a NAK while in the RENEW state,
 2454      * so we might have bindings active at that time)
 2455      */
 2456     script_init(client, "EXPIRE", NULL);
 2457     script_write_params(client, "old_", client->active);
 2458     script_write_requested(client);
 2459     if (client->alias)
 2460         script_write_params(client, "alias_", client->alias);
 2461     script_go(client);
 2462 
 2463     destroy_client_lease (client -> active);
 2464     client -> active = (struct client_lease *)0;
 2465 
 2466     /* Stop sending DHCPREQUEST packets... */
 2467     cancel_timeout (send_request, client);
 2468 
 2469     /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
 2470      * down (this expunges any routes and arp cache).  This makes the
 2471      * interface unusable by state_init(), which we call next.  So, we
 2472      * need to 'PREINIT' the interface to bring it back up.
 2473      */
 2474     script_init(client, "PREINIT", NULL);
 2475     if (client->alias)
 2476         script_write_params(client, "alias_", client->alias);
 2477     script_go(client);
 2478 
 2479     client -> state = S_INIT;
 2480     state_init (client);
 2481 }
 2482 
 2483 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
 2484    one after the right interval has expired.  If we don't get an offer by
 2485    the time we reach the panic interval, call the panic function. */
 2486 
 2487 void send_discover (cpp)
 2488     void *cpp;
 2489 {
 2490     struct client_state *client = cpp;
 2491 
 2492     int result;
 2493     int interval;
 2494     int increase = 1;
 2495     struct timeval tv;
 2496 
 2497     /* Figure out how long it's been since we started transmitting. */
 2498     interval = cur_time - client -> first_sending;
 2499 
 2500     /* If we're past the panic timeout, call the script and tell it
 2501        we haven't found anything for this interface yet. */
 2502     if (interval > client -> config -> timeout) {
 2503         state_panic (client);
 2504         return;
 2505     }
 2506 
 2507     /* If we're selecting media, try the whole list before doing
 2508        the exponential backoff, but if we've already received an
 2509        offer, stop looping, because we obviously have it right. */
 2510     if (!client -> offered_leases &&
 2511         client -> config -> media) {
 2512         int fail = 0;
 2513           again:
 2514         if (client -> medium) {
 2515             client -> medium = client -> medium -> next;
 2516             increase = 0;
 2517         }
 2518         if (!client -> medium) {
 2519             if (fail)
 2520                 log_fatal ("No valid media types for %s!",
 2521                        client -> interface -> name);
 2522             client -> medium =
 2523                 client -> config -> media;
 2524             increase = 1;
 2525         }
 2526 
 2527         log_info ("Trying medium \"%s\" %d",
 2528               client -> medium -> string, increase);
 2529         script_init(client, "MEDIUM", client -> medium);
 2530         if (script_go(client)) {
 2531             fail = 1;
 2532             goto again;
 2533         }
 2534     }
 2535 
 2536     /* If we're supposed to increase the interval, do so.  If it's
 2537        currently zero (i.e., we haven't sent any packets yet), set
 2538        it to initial_interval; otherwise, add to it a random number
 2539        between zero and two times itself.  On average, this means
 2540        that it will double with every transmission. */
 2541     if (increase) {
 2542         if (!client->interval)
 2543             client->interval = client->config->initial_interval;
 2544         else
 2545             client->interval += random() % (2 * client->interval);
 2546 
 2547         /* Don't backoff past cutoff. */
 2548         if (client->interval > client->config->backoff_cutoff)
 2549             client->interval = (client->config->backoff_cutoff / 2)
 2550                  + (random() % client->config->backoff_cutoff);
 2551     } else if (!client->interval)
 2552         client->interval = client->config->initial_interval;
 2553 
 2554     /* If the backoff would take us to the panic timeout, just use that
 2555        as the interval. */
 2556     if (cur_time + client -> interval >
 2557         client -> first_sending + client -> config -> timeout)
 2558         client -> interval =
 2559             (client -> first_sending +
 2560              client -> config -> timeout) - cur_time + 1;
 2561 
 2562     /* Record the number of seconds since we started sending. */
 2563     if (interval < 65536)
 2564         client -> packet.secs = htons (interval);
 2565     else
 2566         client -> packet.secs = htons (65535);
 2567     client -> secs = client -> packet.secs;
 2568 
 2569 #if defined(DHCPv6) && defined(DHCP4o6)
 2570     if (dhcpv4_over_dhcpv6) {
 2571         log_info ("DHCPDISCOVER interval %ld",
 2572               (long)(client -> interval));
 2573     } else
 2574 #endif
 2575     log_info ("DHCPDISCOVER on %s to %s port %d interval %ld",
 2576           client -> name ? client -> name : client -> interface -> name,
 2577           inet_ntoa (sockaddr_broadcast.sin_addr),
 2578           ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval));
 2579 
 2580     /* Send out a packet. */
 2581 #if defined(DHCPv6) && defined(DHCP4o6)
 2582     if (dhcpv4_over_dhcpv6) {
 2583         result = send_dhcpv4_query(client, 1);
 2584     } else
 2585 #endif
 2586     result = send_packet(client->interface, NULL, &client->packet,
 2587                  client->packet_length, inaddr_any,
 2588                              &sockaddr_broadcast, NULL);
 2589         if (result < 0) {
 2590 #if defined(DHCPv6) && defined(DHCP4o6)
 2591         if (dhcpv4_over_dhcpv6) {
 2592             log_error("%s:%d: Failed to send %d byte long packet.",
 2593                   MDL, client->packet_length);
 2594         } else
 2595 #endif
 2596         log_error("%s:%d: Failed to send %d byte long packet over %s "
 2597               "interface.", MDL, client->packet_length,
 2598               client->interface->name);
 2599     }
 2600 
 2601     /*
 2602      * If we used 0 microseconds here, and there were other clients on the
 2603      * same network with a synchronized local clock (ntp), and a similar
 2604      * zero-microsecond-scheduler behavior, then we could be participating
 2605      * in a sub-second DOS ttck.
 2606      */
 2607     tv.tv_sec = cur_tv.tv_sec + client->interval;
 2608     tv.tv_usec = client->interval > 1 ? random() % 1000000 : cur_tv.tv_usec;
 2609     add_timeout(&tv, send_discover, client, 0, 0);
 2610 }
 2611 
 2612 
 2613 /*
 2614  * \brief Remove leases from a list of leases which duplicate a given lease
 2615  *
 2616  * Searches through a linked-list of leases, remove the first one matches the
 2617  * given lease's address and value of is_static.   The latter test is done
 2618  * so we only remove leases that are from the same source (i.e server/lease file
 2619  *  vs config file).  This ensures we do not discard "fallback" config file leases
 2620  * that happen to match non-config file leases.
 2621  *
 2622  * \param lease_list list of leases to clean
 2623  * \param lease lease for which duplicates should be removed
 2624  */
 2625 void discard_duplicate (struct client_lease** lease_list, struct client_lease* lease) {
 2626     struct client_lease *cur, *prev, *next;
 2627 
 2628     if (!lease_list || !lease) {
 2629         return;
 2630     }
 2631 
 2632     prev = (struct client_lease *)0;
 2633     for (cur = *lease_list; cur; cur = next) {
 2634         next = cur->next;
 2635         if ((cur->is_static == lease->is_static) &&
 2636             (cur->address.len == lease->address.len &&
 2637              !memcmp (cur->address.iabuf, lease->address.iabuf,
 2638                   lease->address.len))) {
 2639             if (prev)
 2640                 prev->next = next;
 2641             else
 2642                 *lease_list = next;
 2643 
 2644             destroy_client_lease (cur);
 2645             break;
 2646         } else {
 2647             prev = cur;
 2648         }
 2649     }
 2650 }
 2651 
 2652 /*
 2653  * \brief Add a given lease to the end of list of leases
 2654  *
 2655  * Searches through a linked-list of leases, removing any that match the
 2656  * given lease's address and value of is_static.  The latter test is done
 2657  * so we only remove leases that are from the same source (i.e server/lease file
 2658  *  vs config file).  This ensures we do not discard "fallback" config file leases
 2659  * that happen to match non-config file leases.
 2660  *
 2661  * \param lease_list list of leases to clean
 2662  * \param lease lease for which duplicates should be removed
 2663  */
 2664 void add_to_tail(struct client_lease** lease_list,
 2665          struct client_lease* lease)
 2666 {
 2667     if (!lease_list || !lease) {
 2668         return;
 2669     }
 2670 
 2671     /* If there is already a lease for this address and
 2672     * is_static value, toss discard it.  This ensures
 2673     * we only keep one dynamic and/or one static lease
 2674     * for a given address. */
 2675     discard_duplicate(lease_list, lease);
 2676 
 2677     /* Find the tail */
 2678     struct client_lease* tail;
 2679     for (tail = *lease_list; tail && tail->next; tail = tail->next){};
 2680 
 2681     /* Ensure the tail points nowhere. */
 2682     lease->next = NULL;
 2683 
 2684     /* Add to the tail. */
 2685     if (!tail) {
 2686         *lease_list = lease;
 2687     } else {
 2688         tail->next = lease;
 2689     }
 2690 }
 2691 
 2692 #if 0
 2693 void dbg_print_lease(char *text, struct client_lease* lease) {
 2694     if (!lease) {
 2695         log_debug("%s, lease is null", text);
 2696     } else {
 2697         log_debug ("%s: %p addr:%s expires:%ld :is_static? %d",
 2698                text, lease, piaddr (lease->address),
 2699                            (lease->expiry - cur_time),
 2700                lease->is_static);
 2701     }
 2702 }
 2703 #endif
 2704 
 2705 /* state_panic gets called if we haven't received any offers in a preset
 2706    amount of time.   When this happens, we try to use existing leases that
 2707    haven't yet expired, and failing that, we call the client script and
 2708    hope it can do something. */
 2709 
 2710 void state_panic (cpp)
 2711     void *cpp;
 2712 {
 2713     struct client_state *client = cpp;
 2714     struct client_lease *loop;
 2715     struct client_lease *lp;
 2716     struct timeval tv;
 2717 
 2718     loop = lp = client -> active;
 2719 
 2720     log_info ("No DHCPOFFERS received.");
 2721 
 2722     /* We may not have an active lease, but we may have some
 2723        predefined leases that we can try. */
 2724     if (!client -> active && client -> leases)
 2725         goto activate_next;
 2726 
 2727     /* Run through the list of leases and see if one can be used. */
 2728     while (client -> active) {
 2729         if (client -> active -> expiry > cur_time) {
 2730             log_info ("Trying %s lease %s",
 2731                   (client -> active -> is_static
 2732                    ? "fallback" : "recorded"),
 2733                   piaddr (client -> active -> address));
 2734             /* Run the client script with the existing
 2735                parameters. */
 2736             script_init(client, "TIMEOUT",
 2737                      client -> active -> medium);
 2738             script_write_params(client, "new_", client -> active);
 2739             script_write_requested(client);
 2740             if (client -> alias)
 2741                 script_write_params(client, "alias_",
 2742                             client -> alias);
 2743 
 2744             /* If the old lease is still good and doesn't
 2745                yet need renewal, go into BOUND state and
 2746                timeout at the renewal time. */
 2747             if (!script_go(client)) {
 2748                 if (cur_time < client -> active -> renewal) {
 2749                 client -> state = S_BOUND;
 2750                 log_info ("bound: renewal in %ld %s.",
 2751                       (long)(client -> active -> renewal -
 2752                          cur_time), "seconds");
 2753                 tv.tv_sec = client->active->renewal;
 2754                 tv.tv_usec = ((client->active->renewal -
 2755                             cur_time) > 1) ?
 2756                         random() % 1000000 :
 2757                         cur_tv.tv_usec;
 2758                 add_timeout(&tv, state_bound, client, 0, 0);
 2759                 } else {
 2760                 client -> state = S_BOUND;
 2761                 log_info ("bound: immediate renewal.");
 2762                 state_bound (client);
 2763                 }
 2764                 reinitialize_interfaces ();
 2765                 detach ();
 2766                 return;
 2767             }
 2768         }
 2769 
 2770         /* If there are no other leases, give up. */
 2771         if (!client -> leases) {
 2772             client -> leases = client -> active;
 2773             client -> active = (struct client_lease *)0;
 2774             break;
 2775         }
 2776 
 2777     activate_next:
 2778         /* Otherwise, put the active lease at the end of the
 2779            lease list, and try another lease.. */
 2780         add_to_tail(&client->leases, client->active);
 2781 
 2782         client -> active = client -> leases;
 2783         client -> leases = client -> leases -> next;
 2784 
 2785         /* If we already tried this lease, we've exhausted the
 2786            set of leases, so we might as well give up for
 2787            now. */
 2788         if (client -> active == loop)
 2789             break;
 2790         else if (!loop)
 2791             loop = client -> active;
 2792     }
 2793 
 2794     /* No leases were available, or what was available didn't work, so
 2795        tell the shell script that we failed to allocate an address,
 2796        and try again later. */
 2797     if (onetry) {
 2798         if (!quiet) {
 2799             log_info ("Unable to obtain a lease on first try.%s",
 2800                   "  Exiting.");
 2801         }
 2802 
 2803 #if defined (CALL_SCRIPT_ON_ONETRY_FAIL)
 2804         /* Let's call a script and we're done */
 2805         script_init(client, "FAIL", (struct string_list *)0);
 2806         script_go(client);
 2807 #endif
 2808         finish(2);
 2809     }
 2810 
 2811     log_info ("No working leases in persistent database - sleeping.");
 2812     script_init(client, "FAIL", (struct string_list *)0);
 2813     if (client -> alias)
 2814         script_write_params(client, "alias_", client -> alias);
 2815     script_go(client);
 2816     client -> state = S_INIT;
 2817     tv.tv_sec = cur_tv.tv_sec + ((client->config->retry_interval + 1) / 2 +
 2818             (random() % client->config->retry_interval));
 2819     tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
 2820             random() % 1000000 : cur_tv.tv_usec;
 2821     add_timeout(&tv, state_init, client, 0, 0);
 2822     detach ();
 2823 }
 2824 
 2825 void send_request (cpp)
 2826     void *cpp;
 2827 {
 2828     struct client_state *client = cpp;
 2829 
 2830     int result;
 2831     int interval;
 2832     struct sockaddr_in destination;
 2833     struct in_addr from;
 2834     struct timeval tv;
 2835     char rip_buf[128];
 2836     const char* rip_str = "";
 2837 
 2838     /* Figure out how long it's been since we started transmitting. */
 2839     interval = cur_time - client -> first_sending;
 2840 
 2841     /* If we're in the INIT-REBOOT or REQUESTING state and we're
 2842        past the reboot timeout, go to INIT and see if we can
 2843        DISCOVER an address... */
 2844     /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
 2845        means either that we're on a network with no DHCP server,
 2846        or that our server is down.  In the latter case, assuming
 2847        that there is a backup DHCP server, DHCPDISCOVER will get
 2848        us a new address, but we could also have successfully
 2849        reused our old address.  In the former case, we're hosed
 2850        anyway.  This is not a win-prone situation. */
 2851     if ((client -> state == S_REBOOTING ||
 2852          client -> state == S_REQUESTING) &&
 2853         interval > client -> config -> reboot_timeout) {
 2854     cancel:
 2855         client -> state = S_INIT;
 2856         cancel_timeout (send_request, client);
 2857         state_init (client);
 2858         return;
 2859     }
 2860 
 2861     /* If we're in the reboot state, make sure the media is set up
 2862        correctly. */
 2863     if (client -> state == S_REBOOTING &&
 2864         !client -> medium &&
 2865         client -> active -> medium ) {
 2866         script_init(client, "MEDIUM", client -> active -> medium);
 2867 
 2868         /* If the medium we chose won't fly, go to INIT state. */
 2869         if (script_go(client))
 2870             goto cancel;
 2871 
 2872         /* Record the medium. */
 2873         client -> medium = client -> active -> medium;
 2874     }
 2875 
 2876     /* If the lease has expired, relinquish the address and go back
 2877        to the INIT state. */
 2878     if (client -> state != S_REQUESTING &&
 2879         cur_time > client -> active -> expiry) {
 2880         /* Run the client script with the new parameters. */
 2881         script_init(client, "EXPIRE", (struct string_list *)0);
 2882         script_write_params(client, "old_", client -> active);
 2883         script_write_requested(client);
 2884         if (client -> alias)
 2885             script_write_params(client, "alias_",
 2886                         client -> alias);
 2887         script_go(client);
 2888 
 2889         /* Now do a preinit on the interface so that we can
 2890            discover a new address. */
 2891         script_init(client, "PREINIT", (struct string_list *)0);
 2892         if (client -> alias)
 2893             script_write_params(client, "alias_",
 2894                         client -> alias);
 2895         script_go(client);
 2896 
 2897         client -> state = S_INIT;
 2898         state_init (client);
 2899         return;
 2900     }
 2901 
 2902     /* Do the exponential backoff... */
 2903     if (!client -> interval)
 2904         client -> interval = client -> config -> initial_interval;
 2905     else {
 2906         client -> interval += ((random () >> 2) %
 2907                        (2 * client -> interval));
 2908     }
 2909 
 2910     /* Don't backoff past cutoff. */
 2911     if (client -> interval >
 2912         client -> config -> backoff_cutoff)
 2913         client -> interval =
 2914             ((client -> config -> backoff_cutoff / 2)
 2915              + ((random () >> 2) %
 2916                     client -> config -> backoff_cutoff));
 2917 
 2918     /* If the backoff would take us to the expiry time, just set the
 2919        timeout to the expiry time. */
 2920     if (client -> state != S_REQUESTING &&
 2921         cur_time + client -> interval > client -> active -> expiry)
 2922         client -> interval =
 2923             client -> active -> expiry - cur_time + 1;
 2924 
 2925     /* If the lease T2 time has elapsed, or if we're not yet bound,
 2926        broadcast the DHCPREQUEST rather than unicasting. */
 2927     if (client -> state == S_REQUESTING ||
 2928         client -> state == S_REBOOTING ||
 2929         cur_time > client -> active -> rebind)
 2930         destination.sin_addr = sockaddr_broadcast.sin_addr;
 2931     else
 2932         memcpy (&destination.sin_addr.s_addr,
 2933             client -> destination.iabuf,
 2934             sizeof destination.sin_addr.s_addr);
 2935     destination.sin_port = remote_port;
 2936     destination.sin_family = AF_INET;
 2937 #ifdef HAVE_SA_LEN
 2938     destination.sin_len = sizeof destination;
 2939 #endif
 2940 
 2941     if (client -> state == S_RENEWING ||
 2942         client -> state == S_REBINDING)
 2943         memcpy (&from, client -> active -> address.iabuf,
 2944             sizeof from);
 2945     else
 2946         from.s_addr = INADDR_ANY;
 2947 
 2948     /* Record the number of seconds since we started sending. */
 2949     if (client -> state == S_REQUESTING)
 2950         client -> packet.secs = client -> secs;
 2951     else {
 2952         if (interval < 65536)
 2953             client -> packet.secs = htons (interval);
 2954         else
 2955             client -> packet.secs = htons (65535);
 2956     }
 2957 
 2958 #if defined(DHCPv6) && defined(DHCP4o6)
 2959     if (dhcpv4_over_dhcpv6) {
 2960         log_info ("DHCPREQUEST");
 2961     } else
 2962 #endif
 2963     memset(rip_buf, 0x0, sizeof(rip_buf));
 2964     if (client->state == S_BOUND || client->state == S_RENEWING ||
 2965         client->state == S_REBINDING) {
 2966         rip_str = inet_ntoa(client->packet.ciaddr);
 2967     } else {
 2968         rip_str = piaddr(client->requested_address);
 2969     }
 2970 
 2971     strncpy(rip_buf, rip_str, sizeof(rip_buf)-1);
 2972     log_info ("DHCPREQUEST for %s on %s to %s port %d", rip_buf,
 2973           client->name ? client->name : client->interface->name,
 2974           inet_ntoa(destination.sin_addr),
 2975           ntohs (destination.sin_port));
 2976 
 2977 #if defined(DHCPv6) && defined(DHCP4o6)
 2978     if (dhcpv4_over_dhcpv6) {
 2979         int broadcast = 0;
 2980         if (destination.sin_addr.s_addr == INADDR_BROADCAST)
 2981             broadcast = 1;
 2982         result = send_dhcpv4_query(client, broadcast);
 2983         if (result < 0) {
 2984             log_error("%s:%d: Failed to send %d byte long packet.",
 2985                   MDL, client->packet_length);
 2986         }
 2987     } else
 2988 #endif
 2989     if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
 2990         fallback_interface) {
 2991         result = send_packet(fallback_interface, NULL, &client->packet,
 2992                      client->packet_length, from, &destination,
 2993                      NULL);
 2994         if (result < 0) {
 2995             log_error("%s:%d: Failed to send %d byte long packet "
 2996                   "over %s interface.", MDL,
 2997                   client->packet_length,
 2998                   fallback_interface->name);
 2999         }
 3000         }
 3001     else {
 3002         /* Send out a packet. */
 3003         result = send_packet(client->interface, NULL, &client->packet,
 3004                      client->packet_length, from, &destination,
 3005                      NULL);
 3006         if (result < 0) {
 3007             log_error("%s:%d: Failed to send %d byte long packet"
 3008                   " over %s interface.", MDL,
 3009                   client->packet_length,
 3010                   client->interface->name);
 3011         }
 3012         }
 3013 
 3014     tv.tv_sec = cur_tv.tv_sec + client->interval;
 3015     tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
 3016             random() % 1000000 : cur_tv.tv_usec;
 3017     add_timeout(&tv, send_request, client, 0, 0);
 3018 }
 3019 
 3020 void send_decline (cpp)
 3021     void *cpp;
 3022 {
 3023     struct client_state *client = cpp;
 3024 
 3025     int result;
 3026 
 3027 #if defined(DHCPv6) && defined(DHCP4o6)
 3028     if (dhcpv4_over_dhcpv6) {
 3029         log_info ("DHCPDECLINE");
 3030     } else
 3031 #endif
 3032     log_info ("DHCPDECLINE of %s on %s to %s port %d",
 3033           piaddr(client->requested_address),
 3034           (client->name ? client->name : client->interface->name),
 3035           inet_ntoa(sockaddr_broadcast.sin_addr),
 3036           ntohs(sockaddr_broadcast.sin_port));
 3037 
 3038     /* Send out a packet. */
 3039 #if defined(DHCPv6) && defined(DHCP4o6)
 3040     if (dhcpv4_over_dhcpv6) {
 3041         result = send_dhcpv4_query(client, 1);
 3042     } else
 3043 #endif
 3044     result = send_packet(client->interface, NULL, &client->packet,
 3045                  client->packet_length, inaddr_any,
 3046                  &sockaddr_broadcast, NULL);
 3047     if (result < 0) {
 3048 #if defined(DHCPv6) && defined(DHCP4o6)
 3049         if (dhcpv4_over_dhcpv6) {
 3050             log_error("%s:%d: Failed to send %d byte long packet.",
 3051                   MDL, client->packet_length);
 3052         } else
 3053 #endif
 3054         log_error("%s:%d: Failed to send %d byte long packet over %s"
 3055               " interface.", MDL, client->packet_length,
 3056               client->interface->name);
 3057     }
 3058 }
 3059 
 3060 void send_release (cpp)
 3061     void *cpp;
 3062 {
 3063     struct client_state *client = cpp;
 3064 
 3065     int result;
 3066     struct sockaddr_in destination;
 3067     struct in_addr from;
 3068 
 3069     memcpy (&from, client -> active -> address.iabuf,
 3070         sizeof from);
 3071     memcpy (&destination.sin_addr.s_addr,
 3072         client -> destination.iabuf,
 3073         sizeof destination.sin_addr.s_addr);
 3074     destination.sin_port = remote_port;
 3075     destination.sin_family = AF_INET;
 3076 #ifdef HAVE_SA_LEN
 3077     destination.sin_len = sizeof destination;
 3078 #endif
 3079 
 3080     /* Set the lease to end now, so that we don't accidentally
 3081        reuse it if we restart before the old expiry time. */
 3082     client -> active -> expiry =
 3083         client -> active -> renewal =
 3084         client -> active -> rebind = cur_time;
 3085     if (!write_client_lease (client, client -> active, 1, 1)) {
 3086         log_error ("Can't release lease: lease write failed.");
 3087         return;
 3088     }
 3089 
 3090 #if defined(DHCPv6) && defined(DHCP4o6)
 3091     if (dhcpv4_over_dhcpv6) {
 3092         log_info ("DHCPRELEASE");
 3093     } else
 3094 #endif
 3095     log_info ("DHCPRELEASE of %s on %s to %s port %d",
 3096           piaddr(client->active->address),
 3097           client->name ? client->name : client->interface->name,
 3098           inet_ntoa (destination.sin_addr),
 3099           ntohs (destination.sin_port));
 3100 
 3101 #if defined(DHCPv6) && defined(DHCP4o6)
 3102     if (dhcpv4_over_dhcpv6) {
 3103         int broadcast = 0;
 3104         if (destination.sin_addr.s_addr == INADDR_BROADCAST)
 3105             broadcast = 1;
 3106         result = send_dhcpv4_query(client, broadcast);
 3107         if (result < 0) {
 3108             log_error("%s:%d: Failed to send %d byte long packet.",
 3109                   MDL, client->packet_length);
 3110         }
 3111     } else
 3112 #endif
 3113     if (fallback_interface) {
 3114         result = send_packet(fallback_interface, NULL, &client->packet,
 3115                       client->packet_length, from, &destination,
 3116                       NULL);
 3117         if (result < 0) {
 3118             log_error("%s:%d: Failed to send %d byte long packet"
 3119                   " over %s interface.", MDL,
 3120                   client->packet_length,
 3121                   fallback_interface->name);
 3122         }
 3123         } else {
 3124         /* Send out a packet. */
 3125         result = send_packet(client->interface, NULL, &client->packet,
 3126                       client->packet_length, from, &destination,
 3127                       NULL);
 3128         if (result < 0) {
 3129             log_error ("%s:%d: Failed to send %d byte long packet"
 3130                    " over %s interface.", MDL,
 3131                    client->packet_length,
 3132                    client->interface->name);
 3133         }
 3134 
 3135         }
 3136 }
 3137 
 3138 #if defined(DHCPv6) && defined(DHCP4o6)
 3139 /*
 3140  * \brief Send a DHCPv4-query to the DHCPv6 client
 3141  *  (DHCPv4 client function)
 3142  *
 3143  * The DHCPv4 client sends a DHCPv4-query to the DHCPv6 client over
 3144  * the inter-process communication socket.
 3145  *
 3146  * \param client the DHCPv4 client state
 3147  * \param broadcast the broadcast flag
 3148  * \return the sent byte count (-1 on error)
 3149  */
 3150 static int send_dhcpv4_query(struct client_state *client, int broadcast) {
 3151     struct data_string ds;
 3152     struct dhcpv4_over_dhcpv6_packet *query;
 3153     int ofs, len, cc;
 3154 
 3155     if (dhcp4o6_state <= 0) {
 3156         log_info("send_dhcpv4_query: not ready.");
 3157         return -1;
 3158     }
 3159 
 3160     /*
 3161      * Compute buffer length and allocate it.
 3162      */
 3163     len = ofs = (int)(offsetof(struct dhcpv4_over_dhcpv6_packet, options));
 3164     len += dhcpv6_universe.tag_size + dhcpv6_universe.length_size;
 3165     len += client->packet_length;
 3166     memset(&ds, 0, sizeof(ds));
 3167     if (!buffer_allocate(&ds.buffer, len, MDL)) {
 3168         log_error("Unable to allocate memory for DHCPv4-query.");
 3169         return -1;
 3170     }
 3171     ds.data = ds.buffer->data;
 3172     ds.len = len;
 3173 
 3174     /*
 3175      * Fill header.
 3176      */
 3177     query = (struct dhcpv4_over_dhcpv6_packet *)ds.data;
 3178     query->msg_type = DHCPV6_DHCPV4_QUERY;
 3179     query->flags[0] = query->flags[1] = query->flags[2] = 0;
 3180     if (!broadcast)
 3181         query->flags[0] |= DHCP4O6_QUERY_UNICAST;
 3182 
 3183     /*
 3184      * Append DHCPv4 message.
 3185      */
 3186     dhcpv6_universe.store_tag(ds.buffer->data + ofs, D6O_DHCPV4_MSG);
 3187     ofs += dhcpv6_universe.tag_size;
 3188     dhcpv6_universe.store_length(ds.buffer->data + ofs,
 3189                      client->packet_length);
 3190     ofs += dhcpv6_universe.length_size;
 3191     memcpy(ds.buffer->data + ofs, &client->packet, client->packet_length);
 3192 
 3193     /*
 3194      * Send DHCPv6 message.
 3195      */
 3196     cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
 3197     if (cc < 0)
 3198         log_error("send_dhcpv4_query: send(): %m");
 3199 
 3200     data_string_forget(&ds, MDL);
 3201 
 3202     return cc;
 3203 }
 3204 
 3205 /*
 3206  * \brief Forward a DHCPv4-query to all DHCPv4 over DHCPv6 server addresses.
 3207  *  (DHCPv6 client function)
 3208  *
 3209  * \param raw the DHCPv6 DHCPv4-query message raw content
 3210  */
 3211 static void forw_dhcpv4_query(struct data_string *raw) {
 3212     struct interface_info *ip;
 3213     struct client_state *client;
 3214     struct dhc6_lease *lease;
 3215     struct option_cache *oc;
 3216     struct data_string addrs;
 3217     struct sockaddr_in6 sin6;
 3218     int i, send_ret, attempt, success;
 3219 
 3220     attempt = success = 0;
 3221     memset(&sin6, 0, sizeof(sin6));
 3222     sin6.sin6_family = AF_INET6;
 3223     sin6.sin6_port = remote_port;
 3224 #ifdef HAVE_SA_LEN
 3225     sin6.sin6_len = sizeof(sin6);
 3226 #endif
 3227     memset(&addrs, 0, sizeof(addrs));
 3228     for (ip = interfaces; ip != NULL; ip = ip->next) {
 3229         for (client = ip->client; client != NULL;
 3230              client = client->next) {
 3231             if ((client->state != S_BOUND) &&
 3232                 (client->state != S_RENEWING) &&
 3233                 (client->state != S_REBINDING))
 3234                 continue;
 3235             lease = client->active_lease;
 3236             if ((lease == NULL) || lease->released)
 3237                 continue;
 3238             oc = lookup_option(&dhcpv6_universe,
 3239                        lease->options,
 3240                        D6O_DHCP4_O_DHCP6_SERVER);
 3241             if ((oc == NULL) ||
 3242                 !evaluate_option_cache(&addrs, NULL, NULL, NULL,
 3243                            lease->options, NULL,
 3244                            &global_scope, oc, MDL) ||
 3245                 ((addrs.len % sizeof(sin6.sin6_addr)) != 0)) {
 3246                 data_string_forget(&addrs, MDL);
 3247                 continue;
 3248             }
 3249             if (addrs.len == 0) {
 3250                 /* note there is nothing to forget */
 3251                 inet_pton(AF_INET6,
 3252                       All_DHCP_Relay_Agents_and_Servers,
 3253                       &sin6.sin6_addr);
 3254                 attempt++;
 3255                 send_ret = send_packet6(ip, raw->data,
 3256                             raw->len, &sin6);
 3257                 if (send_ret == raw->len)
 3258                     success++;
 3259                 continue;
 3260             }
 3261             for (i = 0; i < addrs.len;
 3262                  i += sizeof(sin6.sin6_addr)) {
 3263                 memcpy(&sin6.sin6_addr, addrs.data + i,
 3264                        sizeof(sin6.sin6_addr));
 3265                 attempt++;
 3266                 send_ret = send_packet6(ip, raw->data,
 3267                             raw->len, &sin6);
 3268                 if (send_ret == raw->len)
 3269                     success++;
 3270             }
 3271             data_string_forget(&addrs, MDL);
 3272         }
 3273     }
 3274 
 3275     log_info("forw_dhcpv4_query: sent(%d): %d/%d",
 3276          raw->len, success, attempt);
 3277 
 3278     if (attempt == 0)
 3279         dhcp4o6_stop();
 3280 }
 3281 #endif
 3282 
 3283 void
 3284 make_client_options(struct client_state *client, struct client_lease *lease,
 3285             u_int8_t *type, struct option_cache *sid,
 3286             struct iaddr *rip, struct option **prl,
 3287             struct option_state **op)
 3288 {
 3289     unsigned i;
 3290     struct option_cache *oc;
 3291     struct option *option = NULL;
 3292     struct buffer *bp = NULL;
 3293 
 3294     /* If there are any leftover options, get rid of them. */
 3295     if (*op)
 3296         option_state_dereference(op, MDL);
 3297 
 3298     /* Allocate space for options. */
 3299     option_state_allocate(op, MDL);
 3300 
 3301     /* Send the server identifier if provided. */
 3302     if (sid)
 3303         save_option(&dhcp_universe, *op, sid);
 3304 
 3305     oc = NULL;
 3306 
 3307     /* Send the requested address if provided. */
 3308     if (rip) {
 3309         client->requested_address = *rip;
 3310         i = DHO_DHCP_REQUESTED_ADDRESS;
 3311         if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
 3312                           &i, 0, MDL) &&
 3313               make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
 3314                           option, MDL)))
 3315             log_error ("can't make requested address cache.");
 3316         else {
 3317             save_option(&dhcp_universe, *op, oc);
 3318             option_cache_dereference(&oc, MDL);
 3319         }
 3320         option_dereference(&option, MDL);
 3321     } else {
 3322         client->requested_address.len = 0;
 3323     }
 3324 
 3325     i = DHO_DHCP_MESSAGE_TYPE;
 3326     if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
 3327                       MDL) &&
 3328           make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
 3329         log_error("can't make message type.");
 3330     else {
 3331         save_option(&dhcp_universe, *op, oc);
 3332         option_cache_dereference(&oc, MDL);
 3333     }
 3334     option_dereference(&option, MDL);
 3335 
 3336     if (prl) {
 3337         int len;
 3338 
 3339         /* Probe the length of the list. */
 3340         len = 0;
 3341         for (i = 0 ; prl[i] != NULL ; i++)
 3342             if (prl[i]->universe == &dhcp_universe)
 3343                 len++;
 3344 
 3345         if (!buffer_allocate(&bp, len, MDL))
 3346             log_error("can't make parameter list buffer.");
 3347         else {
 3348             unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
 3349 
 3350             len = 0;
 3351             for (i = 0 ; prl[i] != NULL ; i++)
 3352                 if (prl[i]->universe == &dhcp_universe)
 3353                     bp->data[len++] = prl[i]->code;
 3354 
 3355             if (!(option_code_hash_lookup(&option,
 3356                               dhcp_universe.code_hash,
 3357                               &code, 0, MDL) &&
 3358                   make_const_option_cache(&oc, &bp, NULL, len,
 3359                               option, MDL))) {
 3360                 if (bp != NULL)
 3361                     buffer_dereference(&bp, MDL);
 3362                 log_error ("can't make option cache");
 3363             } else {
 3364                 save_option(&dhcp_universe, *op, oc);
 3365                 option_cache_dereference(&oc, MDL);
 3366             }
 3367             option_dereference(&option, MDL);
 3368         }
 3369     }
 3370 
 3371     /*
 3372      * If requested (duid_v4 == 1) add an RFC4361 compliant client-identifier
 3373      * This can be overridden by including a client id in the configuration
 3374      * file.
 3375      */
 3376     if (duid_v4 == 1) {
 3377         struct data_string client_identifier;
 3378         int hw_idx, hw_len;
 3379 
 3380         memset(&client_identifier, 0, sizeof(client_identifier));
 3381         client_identifier.len = 1 + 4 + default_duid.len;
 3382         if (!buffer_allocate(&client_identifier.buffer,
 3383                      client_identifier.len, MDL))
 3384             log_fatal("no memory for default DUID!");
 3385         client_identifier.data = client_identifier.buffer->data;
 3386 
 3387         i = DHO_DHCP_CLIENT_IDENTIFIER;
 3388 
 3389         /* Client-identifier type : 1 byte */
 3390         *client_identifier.buffer->data = 255;
 3391 
 3392         /* IAID : 4 bytes
 3393          * we use the low 4 bytes from the interface address
 3394          */
 3395         if (client->interface->hw_address.hlen > 4) {
 3396             hw_idx = client->interface->hw_address.hlen - 4;
 3397             hw_len = 4;
 3398         } else {
 3399             hw_idx = 0;
 3400             hw_len = client->interface->hw_address.hlen;
 3401         }
 3402         memcpy(client_identifier.buffer->data + 5 - hw_len,
 3403                client->interface->hw_address.hbuf + hw_idx,
 3404                hw_len);
 3405 
 3406         /* Add the default duid */
 3407         memcpy(client_identifier.buffer->data + (1 + 4),
 3408                default_duid.data, default_duid.len);
 3409 
 3410         /* And save the option */
 3411         if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
 3412                           &i, 0, MDL) &&
 3413               make_const_option_cache(&oc, NULL,
 3414                           (u_int8_t *)client_identifier.data,
 3415                           client_identifier.len,
 3416                           option, MDL)))
 3417             log_error ("can't make requested client id cache..");
 3418         else {
 3419             save_option (&dhcp_universe, *op, oc);
 3420             option_cache_dereference (&oc, MDL);
 3421         }
 3422         option_dereference(&option, MDL);
 3423     }
 3424 
 3425     /* Run statements that need to be run on transmission. */
 3426     if (client->config->on_transmission)
 3427         execute_statements_in_scope(NULL, NULL, NULL, client,
 3428                         (lease ? lease->options : NULL),
 3429                         *op, &global_scope,
 3430                         client->config->on_transmission,
 3431                         NULL, NULL);
 3432 }
 3433 
 3434 void make_discover (client, lease)
 3435     struct client_state *client;
 3436     struct client_lease *lease;
 3437 {
 3438     unsigned char discover = DHCPDISCOVER;
 3439     struct option_state *options = (struct option_state *)0;
 3440 
 3441     memset (&client -> packet, 0, sizeof (client -> packet));
 3442 
 3443     make_client_options (client,
 3444                  lease, &discover, (struct option_cache *)0,
 3445                  lease ? &lease -> address : (struct iaddr *)0,
 3446                  client -> config -> requested_options,
 3447                  &options);
 3448 
 3449     /* Set up the option buffer... */
 3450     client -> packet_length =
 3451         cons_options ((struct packet *)0, &client -> packet,
 3452                   (struct lease *)0, client,
 3453                   /* maximum packet size */1500,
 3454                   (struct option_state *)0,
 3455                   options,
 3456                   /* scope */ &global_scope,
 3457                   /* overload */ 0,
 3458                   /* terminate */0,
 3459                   /* bootpp    */0,
 3460                   (struct data_string *)0,
 3461                   client -> config -> vendor_space_name);
 3462 
 3463     option_state_dereference (&options, MDL);
 3464     if (client -> packet_length < BOOTP_MIN_LEN)
 3465         client -> packet_length = BOOTP_MIN_LEN;
 3466 
 3467     client -> packet.op = BOOTREQUEST;
 3468     client -> packet.htype = client -> interface -> hw_address.hbuf [0];
 3469     /* Assumes hw_address is known, otherwise a random value may result */
 3470     client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
 3471     client -> packet.hops = 0;
 3472     client -> packet.xid = random ();
 3473     client -> packet.secs = 0; /* filled in by send_discover. */
 3474 
 3475     if (can_receive_unicast_unconfigured (client -> interface))
 3476         client -> packet.flags = 0;
 3477     else
 3478         client -> packet.flags = htons (BOOTP_BROADCAST);
 3479 
 3480     memset (&(client -> packet.ciaddr),
 3481         0, sizeof client -> packet.ciaddr);
 3482     memset (&(client -> packet.yiaddr),
 3483         0, sizeof client -> packet.yiaddr);
 3484     memset (&(client -> packet.siaddr),
 3485         0, sizeof client -> packet.siaddr);
 3486     client -> packet.giaddr = giaddr;
 3487     if (client -> interface -> hw_address.hlen > 0)
 3488         memcpy (client -> packet.chaddr,
 3489             &client -> interface -> hw_address.hbuf [1],
 3490             (unsigned)(client -> interface -> hw_address.hlen - 1));
 3491 
 3492 #ifdef DEBUG_PACKET
 3493     dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
 3494 #endif
 3495 }
 3496 
 3497 
 3498 void make_request (client, lease)
 3499     struct client_state *client;
 3500     struct client_lease *lease;
 3501 {
 3502     unsigned char request = DHCPREQUEST;
 3503     struct option_cache *oc;
 3504 
 3505     memset (&client -> packet, 0, sizeof (client -> packet));
 3506 
 3507     if (client -> state == S_REQUESTING)
 3508         oc = lookup_option (&dhcp_universe, lease -> options,
 3509                     DHO_DHCP_SERVER_IDENTIFIER);
 3510     else
 3511         oc = (struct option_cache *)0;
 3512 
 3513     if (client -> sent_options)
 3514         option_state_dereference (&client -> sent_options, MDL);
 3515 
 3516     make_client_options (client, lease, &request, oc,
 3517                  ((client -> state == S_REQUESTING ||
 3518                    client -> state == S_REBOOTING)
 3519                   ? &lease -> address
 3520                   : (struct iaddr *)0),
 3521                  client -> config -> requested_options,
 3522                  &client -> sent_options);
 3523 
 3524     /* Set up the option buffer... */
 3525     client -> packet_length =
 3526         cons_options ((struct packet *)0, &client -> packet,
 3527                   (struct lease *)0, client,
 3528                   /* maximum packet size */1500,
 3529                   (struct option_state *)0,
 3530                   client -> sent_options,
 3531                   /* scope */ &global_scope,
 3532                   /* overload */ 0,
 3533                   /* terminate */0,
 3534                   /* bootpp    */0,
 3535                   (struct data_string *)0,
 3536                   client -> config -> vendor_space_name);
 3537 
 3538     if (client -> packet_length < BOOTP_MIN_LEN)
 3539         client -> packet_length = BOOTP_MIN_LEN;
 3540 
 3541     client -> packet.op = BOOTREQUEST;
 3542     client -> packet.htype = client -> interface -> hw_address.hbuf [0];
 3543     /* Assumes hw_address is known, otherwise a random value may result */
 3544     client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
 3545     client -> packet.hops = 0;
 3546     client -> packet.xid = client -> xid;
 3547     client -> packet.secs = 0; /* Filled in by send_request. */
 3548 
 3549     /* If we own the address we're requesting, put it in ciaddr;
 3550        otherwise set ciaddr to zero. */
 3551     if (client -> state == S_BOUND ||
 3552         client -> state == S_RENEWING ||
 3553         client -> state == S_REBINDING) {
 3554         memcpy (&client -> packet.ciaddr,
 3555             lease -> address.iabuf, lease -> address.len);
 3556         client -> packet.flags = 0;
 3557     } else {
 3558         memset (&client -> packet.ciaddr, 0,
 3559             sizeof client -> packet.ciaddr);
 3560         if (can_receive_unicast_unconfigured (client -> interface))
 3561             client -> packet.flags = 0;
 3562         else
 3563             client -> packet.flags = htons (BOOTP_BROADCAST);
 3564     }
 3565 
 3566     memset (&client -> packet.yiaddr, 0,
 3567         sizeof client -> packet.yiaddr);
 3568     memset (&client -> packet.siaddr, 0,
 3569         sizeof client -> packet.siaddr);
 3570     if (client -> state != S_BOUND &&
 3571         client -> state != S_RENEWING)
 3572         client -> packet.giaddr = giaddr;
 3573     else
 3574         memset (&client -> packet.giaddr, 0,
 3575             sizeof client -> packet.giaddr);
 3576     if (client -> interface -> hw_address.hlen > 0)
 3577         memcpy (client -> packet.chaddr,
 3578             &client -> interface -> hw_address.hbuf [1],
 3579             (unsigned)(client -> interface -> hw_address.hlen - 1));
 3580 
 3581 #ifdef DEBUG_PACKET
 3582     dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
 3583 #endif
 3584 }
 3585 
 3586 void make_decline (client, lease)
 3587     struct client_state *client;
 3588     struct client_lease *lease;
 3589 {
 3590     unsigned char decline = DHCPDECLINE;
 3591     struct option_cache *oc;
 3592 
 3593     struct option_state *options = (struct option_state *)0;
 3594 
 3595     /* Create the options cache. */
 3596     oc = lookup_option (&dhcp_universe, lease -> options,
 3597                 DHO_DHCP_SERVER_IDENTIFIER);
 3598     make_client_options(client, lease, &decline, oc, &lease->address,
 3599                 NULL, &options);
 3600 
 3601     /* Consume the options cache into the option buffer. */
 3602     memset (&client -> packet, 0, sizeof (client -> packet));
 3603     client -> packet_length =
 3604         cons_options ((struct packet *)0, &client -> packet,
 3605                   (struct lease *)0, client, 0,
 3606                   (struct option_state *)0, options,
 3607                   &global_scope, 0, 0, 0, (struct data_string *)0,
 3608                   client -> config -> vendor_space_name);
 3609 
 3610     /* Destroy the options cache. */
 3611     option_state_dereference (&options, MDL);
 3612 
 3613     if (client -> packet_length < BOOTP_MIN_LEN)
 3614         client -> packet_length = BOOTP_MIN_LEN;
 3615 
 3616     client -> packet.op = BOOTREQUEST;
 3617     client -> packet.htype = client -> interface -> hw_address.hbuf [0];
 3618     /* Assumes hw_address is known, otherwise a random value may result */
 3619     client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
 3620     client -> packet.hops = 0;
 3621     client -> packet.xid = client -> xid;
 3622     client -> packet.secs = 0; /* Filled in by send_request. */
 3623     if (can_receive_unicast_unconfigured (client -> interface))
 3624         client -> packet.flags = 0;
 3625     else
 3626         client -> packet.flags = htons (BOOTP_BROADCAST);
 3627 
 3628     /* ciaddr must always be zero. */
 3629     memset (&client -> packet.ciaddr, 0,
 3630         sizeof client -> packet.ciaddr);
 3631     memset (&client -> packet.yiaddr, 0,
 3632         sizeof client -> packet.yiaddr);
 3633     memset (&client -> packet.siaddr, 0,
 3634         sizeof client -> packet.siaddr);
 3635     client -> packet.giaddr = giaddr;
 3636     memcpy (client -> packet.chaddr,
 3637         &client -> interface -> hw_address.hbuf [1],
 3638         client -> interface -> hw_address.hlen);
 3639 
 3640 #ifdef DEBUG_PACKET
 3641     dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
 3642 #endif
 3643 }
 3644 
 3645 void make_release (client, lease)
 3646     struct client_state *client;
 3647     struct client_lease *lease;
 3648 {
 3649     unsigned char request = DHCPRELEASE;
 3650     struct option_cache *oc;
 3651 
 3652     struct option_state *options = (struct option_state *)0;
 3653 
 3654     memset (&client -> packet, 0, sizeof (client -> packet));
 3655 
 3656     oc = lookup_option (&dhcp_universe, lease -> options,
 3657                 DHO_DHCP_SERVER_IDENTIFIER);
 3658     make_client_options(client, lease, &request, oc, NULL, NULL, &options);
 3659 
 3660     /* Set up the option buffer... */
 3661     client -> packet_length =
 3662         cons_options ((struct packet *)0, &client -> packet,
 3663                   (struct lease *)0, client,
 3664                   /* maximum packet size */1500,
 3665                   (struct option_state *)0,
 3666                   options,
 3667                   /* scope */ &global_scope,
 3668                   /* overload */ 0,
 3669                   /* terminate */0,
 3670                   /* bootpp    */0,
 3671                   (struct data_string *)0,
 3672                   client -> config -> vendor_space_name);
 3673 
 3674     if (client -> packet_length < BOOTP_MIN_LEN)
 3675         client -> packet_length = BOOTP_MIN_LEN;
 3676     option_state_dereference (&options, MDL);
 3677 
 3678     client -> packet.op = BOOTREQUEST;
 3679     client -> packet.htype = client -> interface -> hw_address.hbuf [0];
 3680     /* Assumes hw_address is known, otherwise a random value may result */
 3681     client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
 3682     client -> packet.hops = 0;
 3683     client -> packet.xid = random ();
 3684     client -> packet.secs = 0;
 3685     client -> packet.flags = 0;
 3686     memcpy (&client -> packet.ciaddr,
 3687         lease -> address.iabuf, lease -> address.len);
 3688     memset (&client -> packet.yiaddr, 0,
 3689         sizeof client -> packet.yiaddr);
 3690     memset (&client -> packet.siaddr, 0,
 3691         sizeof client -> packet.siaddr);
 3692     client -> packet.giaddr = giaddr;
 3693     memcpy (client -> packet.chaddr,
 3694         &client -> interface -> hw_address.hbuf [1],
 3695         client -> interface -> hw_address.hlen);
 3696 
 3697 #ifdef DEBUG_PACKET
 3698     dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
 3699 #endif
 3700 }
 3701 
 3702 void destroy_client_lease (lease)
 3703     struct client_lease *lease;
 3704 {
 3705     if (lease -> server_name)
 3706         dfree (lease -> server_name, MDL);
 3707     if (lease -> filename)
 3708         dfree (lease -> filename, MDL);
 3709     option_state_dereference (&lease -> options, MDL);
 3710     free_client_lease (lease, MDL);
 3711 }
 3712 
 3713 FILE *leaseFile = NULL;
 3714 int leases_written = 0;
 3715 
 3716 void rewrite_client_leases ()
 3717 {
 3718     struct interface_info *ip;
 3719     struct client_state *client;
 3720     struct client_lease *lp;
 3721 
 3722     if (leaseFile != NULL)
 3723         fclose (leaseFile);
 3724     leaseFile = fopen (path_dhclient_db, "w");
 3725     if (leaseFile == NULL) {
 3726         log_error ("can't create %s: %m", path_dhclient_db);
 3727         return;
 3728     }
 3729 
 3730     /* If there is a default duid, write it out. */
 3731     if (default_duid.len != 0)
 3732         write_duid(&default_duid);
 3733 
 3734     /* Write out all the leases attached to configured interfaces that
 3735        we know about. */
 3736     for (ip = interfaces; ip; ip = ip -> next) {
 3737         for (client = ip -> client; client; client = client -> next) {
 3738             for (lp = client -> leases; lp; lp = lp -> next) {
 3739                 write_client_lease (client, lp, 1, 0);
 3740             }
 3741             if (client -> active)
 3742                 write_client_lease (client,
 3743                             client -> active, 1, 0);
 3744 
 3745             if (client->active_lease != NULL)
 3746                 write_client6_lease(client,
 3747                             client->active_lease,
 3748                             1, 0);
 3749 
 3750             /* Reset last_write after rewrites. */
 3751             client->last_write = 0;
 3752         }
 3753     }
 3754 
 3755     /* Write out any leases that are attached to interfaces that aren't
 3756        currently configured. */
 3757     for (ip = dummy_interfaces; ip; ip = ip -> next) {
 3758         for (client = ip -> client; client; client = client -> next) {
 3759             for (lp = client -> leases; lp; lp = lp -> next) {
 3760                 write_client_lease (client, lp, 1, 0);
 3761             }
 3762             if (client -> active)
 3763                 write_client_lease (client,
 3764                             client -> active, 1, 0);
 3765 
 3766             if (client->active_lease != NULL)
 3767                 write_client6_lease(client,
 3768                             client->active_lease,
 3769                             1, 0);
 3770 
 3771             /* Reset last_write after rewrites. */
 3772             client->last_write = 0;
 3773         }
 3774     }
 3775     fflush (leaseFile);
 3776 }
 3777 
 3778 void write_lease_option (struct option_cache *oc,
 3779              struct packet *packet, struct lease *lease,
 3780              struct client_state *client_state,
 3781              struct option_state *in_options,
 3782              struct option_state *cfg_options,
 3783              struct binding_scope **scope,
 3784              struct universe *u, void *stuff)
 3785 {
 3786     const char *name, *dot;
 3787     struct data_string ds;
 3788     char *preamble = stuff;
 3789 
 3790     memset (&ds, 0, sizeof ds);
 3791 
 3792     if (u != &dhcp_universe) {
 3793         name = u -> name;
 3794         dot = ".";
 3795     } else {
 3796         name = "";
 3797         dot = "";
 3798     }
 3799     if (evaluate_option_cache (&ds, packet, lease, client_state,
 3800                    in_options, cfg_options, scope, oc, MDL)) {
 3801         /* The option name */
 3802         fprintf(leaseFile, "%soption %s%s%s", preamble,
 3803             name, dot, oc->option->name);
 3804 
 3805         /* The option value if there is one */
 3806         if ((oc->option->format == NULL) ||
 3807             (oc->option->format[0] != 'Z')) {
 3808             fprintf(leaseFile, " %s",
 3809                 pretty_print_option(oc->option, ds.data,
 3810                             ds.len, 1, 1));
 3811         }
 3812 
 3813         /* The closing semi-colon and newline */
 3814         fprintf(leaseFile, ";\n");
 3815 
 3816         data_string_forget (&ds, MDL);
 3817     }
 3818 }
 3819 
 3820 /* Write an option cache to the lease store. */
 3821 static void
 3822 write_options(struct client_state *client, struct option_state *options,
 3823           const char *preamble)
 3824 {
 3825     int i;
 3826 
 3827     for (i = 0; i < options->universe_count; i++) {
 3828         option_space_foreach(NULL, NULL, client, NULL, options,
 3829                      &global_scope, universes[i],
 3830                      (char *)preamble, write_lease_option);
 3831     }
 3832 }
 3833 
 3834 /*
 3835  * The "best" default DUID, since we cannot predict any information
 3836  * about the system (such as whether or not the hardware addresses are
 3837  * integrated into the motherboard or similar), is the "LLT", link local
 3838  * plus time, DUID. For real stateless "LL" is better.
 3839  *
 3840  * Once generated, this duid is stored into the state database, and
 3841  * retained across restarts.
 3842  *
 3843  * For the time being, there is probably a different state database for
 3844  * every daemon, so this winds up being a per-interface identifier...which
 3845  * is not how it is intended.  Upcoming rearchitecting the client should
 3846  * address this "one daemon model."
 3847  */
 3848 void
 3849 form_duid(struct data_string *duid, const char *file, int line)
 3850 {
 3851     struct interface_info *ip;
 3852     int len;
 3853     char *str;
 3854 
 3855     /* For now, just use the first interface on the list. */
 3856     ip = interfaces;
 3857 
 3858     if (ip == NULL)
 3859         log_fatal("Impossible condition at %s:%d.", MDL);
 3860 
 3861     if ((ip->hw_address.hlen == 0) ||
 3862         (ip->hw_address.hlen > sizeof(ip->hw_address.hbuf)))
 3863         log_fatal("Impossible hardware address length at %s:%d.", MDL);
 3864 
 3865     if (duid_type == 0)
 3866         duid_type = stateless ? DUID_LL : DUID_LLT;
 3867 
 3868     /*
 3869      * 2 bytes for the 'duid type' field.
 3870      * 2 bytes for the 'htype' field.
 3871      * (DUID_LLT) 4 bytes for the 'current time'.
 3872      * enough bytes for the hardware address (note that hw_address has
 3873      * the 'htype' on byte zero).
 3874      */
 3875     len = 4 + (ip->hw_address.hlen - 1);
 3876     if (duid_type == DUID_LLT)
 3877         len += 4;
 3878     if (!buffer_allocate(&duid->buffer, len, MDL))
 3879         log_fatal("no memory for default DUID!");
 3880     duid->data = duid->buffer->data;
 3881     duid->len = len;
 3882 
 3883     /* Basic Link Local Address type of DUID. */
 3884     if (duid_type == DUID_LLT) {
 3885         putUShort(duid->buffer->data, DUID_LLT);
 3886         putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
 3887         putULong(duid->buffer->data + 4, cur_time - DUID_TIME_EPOCH);
 3888         memcpy(duid->buffer->data + 8, ip->hw_address.hbuf + 1,
 3889                ip->hw_address.hlen - 1);
 3890     } else {
 3891         putUShort(duid->buffer->data, DUID_LL);
 3892         putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
 3893         memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
 3894                ip->hw_address.hlen - 1);
 3895     }
 3896 
 3897     /* Now format the output based on lease-id-format */
 3898     str = format_lease_id(duid->data, duid->len,
 3899                   top_level_config.lease_id_format, MDL);
 3900     if (str == NULL) {
 3901         log_info("form_duid: Couldn't allocate memory to log duid!");
 3902     } else {
 3903         log_info("Created duid %s.", str);
 3904         dfree(str, MDL);
 3905     }
 3906 }
 3907 
 3908 /* Write the default DUID to the lease store. */
 3909 static isc_result_t
 3910 write_duid(struct data_string *duid)
 3911 {
 3912     char *str;
 3913     int stat;
 3914 
 3915     if ((duid == NULL) || (duid->len <= 2))
 3916         return DHCP_R_INVALIDARG;
 3917 
 3918     if (leaseFile == NULL) {    /* XXX? */
 3919         leaseFile = fopen(path_dhclient_db, "w");
 3920         if (leaseFile == NULL) {
 3921             log_error("can't create %s: %m", path_dhclient_db);
 3922             return ISC_R_IOERROR;
 3923         }
 3924     }
 3925 
 3926     /* Generate a formatted duid string per lease-id-format */
 3927     str = format_lease_id(duid->data, duid->len,
 3928                   top_level_config.lease_id_format, MDL);
 3929     if (str == NULL)
 3930         return ISC_R_NOMEMORY;
 3931 
 3932     stat = fprintf(leaseFile, "default-duid %s;\n", str);
 3933     dfree(str, MDL);
 3934     if (stat <= 0)
 3935         return ISC_R_IOERROR;
 3936 
 3937     if (fflush(leaseFile) != 0)
 3938         return ISC_R_IOERROR;
 3939 
 3940     return ISC_R_SUCCESS;
 3941 }
 3942 
 3943 /* Write a DHCPv6 lease to the store. */
 3944 isc_result_t
 3945 write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
 3946             int rewrite, int sync)
 3947 {
 3948     struct dhc6_ia *ia;
 3949     struct dhc6_addr *addr;
 3950     int stat;
 3951     const char *ianame;
 3952 
 3953     /* This should include the current lease. */
 3954     if (!rewrite && (leases_written++ > 20)) {
 3955         rewrite_client_leases();
 3956         leases_written = 0;
 3957         return ISC_R_SUCCESS;
 3958     }
 3959 
 3960     if (client == NULL || lease == NULL)
 3961         return DHCP_R_INVALIDARG;
 3962 
 3963     if (leaseFile == NULL) {    /* XXX? */
 3964         leaseFile = fopen(path_dhclient_db, "w");
 3965         if (leaseFile == NULL) {
 3966             log_error("can't create %s: %m", path_dhclient_db);
 3967             return ISC_R_IOERROR;
 3968         }
 3969     }
 3970 
 3971     stat = fprintf(leaseFile, "lease6 {\n");
 3972     if (stat <= 0)
 3973         return ISC_R_IOERROR;
 3974 
 3975     stat = fprintf(leaseFile, "  interface \"%s\";\n",
 3976                client->interface->name);
 3977     if (stat <= 0)
 3978         return ISC_R_IOERROR;
 3979 
 3980     for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
 3981         switch (ia->ia_type) {
 3982             case D6O_IA_NA:
 3983             default:
 3984                 ianame = "ia-na";
 3985                 break;
 3986             case D6O_IA_TA:
 3987                 ianame = "ia-ta";
 3988                 break;
 3989             case D6O_IA_PD:
 3990                 ianame = "ia-pd";
 3991                 break;
 3992         }
 3993 
 3994         /* For some reason IAID was never octal or hex, but string or
 3995          * hex. Go figure.  So for compatibilty's sake we will either
 3996          * do hex or "legacy" i.e string rather than octal. What a
 3997          * cluster. */
 3998         switch(top_level_config.lease_id_format) {
 3999             case TOKEN_HEX: {
 4000                 char* iaid_str = format_lease_id(
 4001                     (const unsigned char *) &ia->iaid, 4,
 4002                     top_level_config.lease_id_format, MDL);
 4003 
 4004                 if (!iaid_str) {
 4005                     log_error("Can't format iaid");
 4006                     return ISC_R_IOERROR;
 4007                 }
 4008 
 4009                 stat = fprintf(leaseFile, "  %s %s {\n",
 4010                            ianame, iaid_str);
 4011                 dfree(iaid_str, MDL);
 4012                 break;
 4013             }
 4014 
 4015             case TOKEN_OCTAL:
 4016             default:
 4017                 stat = fprintf(leaseFile, "  %s %s {\n", ianame,
 4018                            print_hex_1(4, ia->iaid, 12));
 4019                 break;
 4020         }
 4021 
 4022         if (stat <= 0)
 4023             return ISC_R_IOERROR;
 4024 
 4025         if (ia->ia_type != D6O_IA_TA)
 4026             stat = fprintf(leaseFile, "    starts %d;\n"
 4027                           "    renew %u;\n"
 4028                           "    rebind %u;\n",
 4029                        (int)ia->starts, ia->renew, ia->rebind);
 4030         else
 4031             stat = fprintf(leaseFile, "    starts %d;\n",
 4032                        (int)ia->starts);
 4033         if (stat <= 0)
 4034             return ISC_R_IOERROR;
 4035 
 4036         for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
 4037             if (ia->ia_type != D6O_IA_PD)
 4038                 stat = fprintf(leaseFile,
 4039                            "    iaaddr %s {\n",
 4040                            piaddr(addr->address));
 4041             else
 4042                 stat = fprintf(leaseFile,
 4043                            "    iaprefix %s/%d {\n",
 4044                            piaddr(addr->address),
 4045                            (int)addr->plen);
 4046             if (stat <= 0)
 4047                 return ISC_R_IOERROR;
 4048 
 4049             stat = fprintf(leaseFile, "      starts %d;\n"
 4050                           "      preferred-life %u;\n"
 4051                           "      max-life %u;\n",
 4052                        (int)addr->starts, addr->preferred_life,
 4053                        addr->max_life);
 4054             if (stat <= 0)
 4055                 return ISC_R_IOERROR;
 4056 
 4057             if (addr->options != NULL)
 4058                 write_options(client, addr->options, "      ");
 4059 
 4060             stat = fprintf(leaseFile, "    }\n");
 4061             if (stat <= 0)
 4062                 return ISC_R_IOERROR;
 4063         }
 4064 
 4065         if (ia->options != NULL)
 4066             write_options(client, ia->options, "    ");
 4067 
 4068         stat = fprintf(leaseFile, "  }\n");
 4069         if (stat <= 0)
 4070             return ISC_R_IOERROR;
 4071     }
 4072 
 4073     if (lease->released) {
 4074         stat = fprintf(leaseFile, "  released;\n");
 4075         if (stat <= 0)
 4076             return ISC_R_IOERROR;
 4077     }
 4078 
 4079     if (lease->options != NULL)
 4080         write_options(client, lease->options, "  ");
 4081 
 4082     stat = fprintf(leaseFile, "}\n");
 4083     if (stat <= 0)
 4084         return ISC_R_IOERROR;
 4085 
 4086     if (fflush(leaseFile) != 0)
 4087         return ISC_R_IOERROR;
 4088 
 4089     if (sync) {
 4090         if (fsync(fileno(leaseFile)) < 0) {
 4091             log_error("write_client_lease: fsync(): %m");
 4092             return ISC_R_IOERROR;
 4093         }
 4094     }
 4095 
 4096     return ISC_R_SUCCESS;
 4097 }
 4098 
 4099 int write_client_lease (client, lease, rewrite, makesure)
 4100     struct client_state *client;
 4101     struct client_lease *lease;
 4102     int rewrite;
 4103     int makesure;
 4104 {
 4105     struct data_string ds;
 4106     int errors = 0;
 4107     char *s;
 4108     const char *tval;
 4109 
 4110     if (!rewrite) {
 4111         if (leases_written++ > 20) {
 4112             rewrite_client_leases ();
 4113             leases_written = 0;
 4114         }
 4115     }
 4116 
 4117     /* If the lease came from the config file, we don't need to stash
 4118        a copy in the lease database. */
 4119     if (lease -> is_static)
 4120         return 1;
 4121 
 4122     if (leaseFile == NULL) {    /* XXX */
 4123         leaseFile = fopen (path_dhclient_db, "w");
 4124         if (leaseFile == NULL) {
 4125             log_error ("can't create %s: %m", path_dhclient_db);
 4126             return 0;
 4127         }
 4128     }
 4129 
 4130     errno = 0;
 4131     fprintf (leaseFile, "lease {\n");
 4132     if (lease -> is_bootp) {
 4133         fprintf (leaseFile, "  bootp;\n");
 4134         if (errno) {
 4135             ++errors;
 4136             errno = 0;
 4137         }
 4138     }
 4139     fprintf (leaseFile, "  interface \"%s\";\n",
 4140          client -> interface -> name);
 4141     if (errno) {
 4142         ++errors;
 4143         errno = 0;
 4144     }
 4145     if (client -> name) {
 4146         fprintf (leaseFile, "  name \"%s\";\n", client -> name);
 4147         if (errno) {
 4148             ++errors;
 4149             errno = 0;
 4150         }
 4151     }
 4152     fprintf (leaseFile, "  fixed-address %s;\n",
 4153          piaddr (lease -> address));
 4154     if (errno) {
 4155         ++errors;
 4156         errno = 0;
 4157     }
 4158     if (lease -> filename) {
 4159         s = quotify_string (lease -> filename, MDL);
 4160         if (s) {
 4161             fprintf (leaseFile, "  filename \"%s\";\n", s);
 4162             if (errno) {
 4163                 ++errors;
 4164                 errno = 0;
 4165             }
 4166             dfree (s, MDL);
 4167         } else
 4168             errors++;
 4169 
 4170     }
 4171     if (lease->server_name != NULL) {
 4172         s = quotify_string(lease->server_name, MDL);
 4173         if (s != NULL) {
 4174             fprintf(leaseFile, "  server-name \"%s\";\n", s);
 4175             if (errno) {
 4176                 ++errors;
 4177                 errno = 0;
 4178             }
 4179             dfree(s, MDL);
 4180         } else
 4181             ++errors;
 4182     }
 4183     if (lease -> medium) {
 4184         s = quotify_string (lease -> medium -> string, MDL);
 4185         if (s) {
 4186             fprintf (leaseFile, "  medium \"%s\";\n", s);
 4187             if (errno) {
 4188                 ++errors;
 4189                 errno = 0;
 4190             }
 4191             dfree (s, MDL);
 4192         } else
 4193             errors++;
 4194     }
 4195     if (errno != 0) {
 4196         errors++;
 4197         errno = 0;
 4198     }
 4199 
 4200     memset (&ds, 0, sizeof ds);
 4201 
 4202     write_options(client, lease->options, "  ");
 4203 
 4204     tval = print_time(lease->renewal);
 4205     if (tval == NULL ||
 4206         fprintf(leaseFile, "  renew %s\n", tval) < 0)
 4207         errors++;
 4208 
 4209     tval = print_time(lease->rebind);
 4210     if (tval == NULL ||
 4211         fprintf(leaseFile, "  rebind %s\n", tval) < 0)
 4212         errors++;
 4213 
 4214     tval = print_time(lease->expiry);
 4215     if (tval == NULL ||
 4216         fprintf(leaseFile, "  expire %s\n", tval) < 0)
 4217         errors++;
 4218 
 4219     if (fprintf(leaseFile, "}\n") < 0)
 4220         errors++;
 4221 
 4222     if (fflush(leaseFile) != 0)
 4223         errors++;
 4224 
 4225     client->last_write = cur_time;
 4226 
 4227     if (!errors && makesure) {
 4228         if (fsync (fileno (leaseFile)) < 0) {
 4229             log_info ("write_client_lease: %m");
 4230             return 0;
 4231         }
 4232     }
 4233 
 4234     return errors ? 0 : 1;
 4235 }
 4236 
 4237 /* Variables holding name of script and file pointer for writing to
 4238    script.   Needless to say, this is not reentrant - only one script
 4239    can be invoked at a time. */
 4240 char scriptName [256];
 4241 FILE *scriptFile;
 4242 
 4243 /**
 4244  * @brief Initializes basic variables for a script
 4245  *
 4246  * This function is called as an initial preparation for calling a script.
 4247  * It sets up a number of common env. variables that will be passed to
 4248  * the script. For actual script calling, see @ref script_go .
 4249  *
 4250  * @param client variables will be stored here (if null, the whole function
 4251  *               is no-op)
 4252  * @param reason specified the reason for calling a script (must be non-null)
 4253  * @param medium if specified, defines medium type (may be null)
 4254  */
 4255 void script_init(struct client_state *client, const char *reason,
 4256                  struct string_list *medium)
 4257 {
 4258     struct string_list *sl, *next;
 4259 
 4260     if (client) {
 4261         for (sl = client -> env; sl; sl = next) {
 4262             next = sl -> next;
 4263             dfree (sl, MDL);
 4264         }
 4265         client -> env = (struct string_list *)0;
 4266         client -> envc = 0;
 4267 
 4268         if (client -> interface) {
 4269             client_envadd (client, "", "interface", "%s",
 4270                        client -> interface -> name);
 4271         }
 4272         if (client -> name)
 4273             client_envadd (client,
 4274                        "", "client", "%s", client -> name);
 4275         if (medium)
 4276             client_envadd (client,
 4277                        "", "medium", "%s", medium -> string);
 4278 
 4279         client_envadd (client, "", "reason", "%s", reason);
 4280         client_envadd (client, "", "pid", "%ld", (long int)getpid ());
 4281 #if defined(DHCPv6)
 4282         client_envadd (client, "", "dad_wait_time", "%ld",
 4283                        (long int)dad_wait_time);
 4284 #endif
 4285     }
 4286 }
 4287 
 4288 void client_option_envadd (struct option_cache *oc,
 4289                struct packet *packet, struct lease *lease,
 4290                struct client_state *client_state,
 4291                struct option_state *in_options,
 4292                struct option_state *cfg_options,
 4293                struct binding_scope **scope,
 4294                struct universe *u, void *stuff)
 4295 {
 4296     struct envadd_state *es = stuff;
 4297     struct data_string data;
 4298     memset (&data, 0, sizeof data);
 4299 
 4300     if (evaluate_option_cache (&data, packet, lease, client_state,
 4301                    in_options, cfg_options, scope, oc, MDL)) {
 4302         if (data.len) {
 4303             char name [256];
 4304             if (dhcp_option_ev_name (name, sizeof name,
 4305                          oc->option)) {
 4306                 const char *value;
 4307                 size_t length;
 4308                 value = pretty_print_option(oc->option,
 4309                                 data.data,
 4310                                 data.len, 0, 0);
 4311                 length = strlen(value);
 4312 
 4313                 if (check_option_values(oc->option->universe,
 4314                             oc->option->code,
 4315                             value, length) == 0) {
 4316                     client_envadd(es->client, es->prefix,
 4317                               name, "%s", value);
 4318                 } else {
 4319                     log_error("suspect value in %s "
 4320                           "option - discarded",
 4321                           name);
 4322                 }
 4323             }
 4324         }
 4325 
 4326         data_string_forget (&data, MDL);
 4327     }
 4328 }
 4329 
 4330 /**
 4331  * @brief Adds parameters to environment variables for a script
 4332  *
 4333  * This function add details of specified lease to a list of env. variables
 4334  * to be passed to a script. The lease details will be prepended with
 4335  * specified prefix (e.g. "old_") and added to the list stored in client.
 4336  * Following variables may be set:
 4337  * - ip_address
 4338  * - next_server
 4339  * - network_number
 4340  * - broadcast_address
 4341  * - filename
 4342  * - server_name
 4343  * - expiry
 4344  *
 4345  * @param client env. variables will be stored here
 4346  * @param prefix textual prefix to be added to each variable (e.g. "old_")
 4347  * @param lease lease details will be extracted from here
 4348  */
 4349 void script_write_params(struct client_state *client, const char *prefix,
 4350              struct client_lease *lease)
 4351 {
 4352     int i;
 4353     struct data_string data;
 4354     struct option_cache *oc;
 4355     struct envadd_state es;
 4356 
 4357     es.client = client;
 4358     es.prefix = prefix;
 4359 
 4360     client_envadd (client,
 4361                prefix, "ip_address", "%s", piaddr (lease -> address));
 4362 
 4363     /* If we've set the next server address in the lease structure
 4364        put it into an environment variable for the script */
 4365     if (lease->next_srv_addr.len != 0) {
 4366         client_envadd(client, prefix, "next_server", "%s",
 4367                   piaddr(lease->next_srv_addr));
 4368     }
 4369 
 4370     /* For the benefit of Linux (and operating systems which may
 4371        have similar needs), compute the network address based on
 4372        the supplied ip address and netmask, if provided.  Also
 4373        compute the broadcast address (the host address all ones
 4374        broadcast address, not the host address all zeroes
 4375        broadcast address). */
 4376 
 4377     memset (&data, 0, sizeof data);
 4378     oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
 4379     if (oc && evaluate_option_cache (&data, (struct packet *)0,
 4380                      (struct lease *)0, client,
 4381                      (struct option_state *)0,
 4382                      lease -> options,
 4383                      &global_scope, oc, MDL)) {
 4384         if (data.len > 3) {
 4385             struct iaddr netmask, subnet, broadcast;
 4386 
 4387             /*
 4388              * No matter the length of the subnet-mask option,
 4389              * use only the first four octets.  Note that
 4390              * subnet-mask options longer than 4 octets are not
 4391              * in conformance with RFC 2132, but servers with this
 4392              * flaw do exist.
 4393              */
 4394             memcpy(netmask.iabuf, data.data, 4);
 4395             netmask.len = 4;
 4396             data_string_forget (&data, MDL);
 4397 
 4398             subnet = subnet_number (lease -> address, netmask);
 4399             if (subnet.len) {
 4400                 client_envadd (client, prefix, "network_number",
 4401                        "%s", piaddr (subnet));
 4402 
 4403                 oc = lookup_option (&dhcp_universe,
 4404                         lease -> options,
 4405                         DHO_BROADCAST_ADDRESS);
 4406                 if (!oc ||
 4407                 !(evaluate_option_cache
 4408                   (&data, (struct packet *)0,
 4409                    (struct lease *)0, client,
 4410                    (struct option_state *)0,
 4411                    lease -> options,
 4412                    &global_scope, oc, MDL))) {
 4413                 broadcast = broadcast_addr (subnet, netmask);
 4414                 if (broadcast.len) {
 4415                     client_envadd (client,
 4416                            prefix, "broadcast_address",
 4417                            "%s", piaddr (broadcast));
 4418                 }
 4419                 }
 4420             }
 4421         }
 4422         data_string_forget (&data, MDL);
 4423     }
 4424 
 4425     if (lease->filename) {
 4426         if (check_option_values(NULL, DHO_ROOT_PATH,
 4427                     lease->filename,
 4428                     strlen(lease->filename)) == 0) {
 4429             client_envadd(client, prefix, "filename",
 4430                       "%s", lease->filename);
 4431         } else {
 4432             log_error("suspect value in %s "
 4433                   "option - discarded",
 4434                   lease->filename);
 4435         }
 4436     }
 4437 
 4438     if (lease->server_name) {
 4439         if (check_option_values(NULL, DHO_HOST_NAME,
 4440                     lease->server_name,
 4441                     strlen(lease->server_name)) == 0 ) {
 4442             client_envadd (client, prefix, "server_name",
 4443                        "%s", lease->server_name);
 4444         } else {
 4445             log_error("suspect value in %s "
 4446                   "option - discarded",
 4447                   lease->server_name);
 4448         }
 4449     }
 4450 
 4451     for (i = 0; i < lease -> options -> universe_count; i++) {
 4452         option_space_foreach ((struct packet *)0, (struct lease *)0,
 4453                       client, (struct option_state *)0,
 4454                       lease -> options, &global_scope,
 4455                       universes [i],
 4456                       &es, client_option_envadd);
 4457     }
 4458 
 4459     client_envadd (client, prefix, "expiry", "%lu",
 4460                (unsigned long)(lease -> expiry));
 4461 }
 4462 
 4463 /**
 4464  * @brief Write out the environent variable the client requested.
 4465  * Write out the environment variables for the objects that the
 4466  * client requested.  If the object was requested the variable will be:
 4467  * requested_<option_name>=1
 4468  * If it wasn't requested there won't be a variable.
 4469  *
 4470  * @param client client structure
 4471  */
 4472 void script_write_requested(struct client_state *client)
 4473 {
 4474     int i;
 4475     struct option **req;
 4476     char name[256];
 4477     req = client->config->requested_options;
 4478 
 4479     if (req == NULL)
 4480         return;
 4481 
 4482     for (i = 0 ; req[i] != NULL ; i++) {
 4483         if ((req[i]->universe == &dhcp_universe) &&
 4484             dhcp_option_ev_name(name, sizeof(name), req[i])) {
 4485             client_envadd(client, "requested_", name, "%d", 1);
 4486         }
 4487     }
 4488 }
 4489 
 4490 /**
 4491  * @brief Calls external script.
 4492  *
 4493  * External script is specified either using -sf command line or
 4494  * script parameter in the configuration file.
 4495  *
 4496  * @param client specifies client information (environment variables,
 4497  *        and other parameters will be extracted and passed to the script.
 4498  * @return If positive, it contains exit code of the process running script.
 4499  *         If negative, returns the signal number that cause the script process
 4500  *         to terminate.
 4501  */
 4502 int script_go(struct client_state *client)
 4503 {
 4504     char *scriptName;
 4505     char *argv [2];
 4506     char **envp;
 4507     char reason [] = "REASON=NBI";
 4508     static char client_path [] = CLIENT_PATH;
 4509     int i;
 4510     struct string_list *sp, *next;
 4511     int pid, wpid, wstatus;
 4512 
 4513     if (client)
 4514         scriptName = client -> config -> script_name;
 4515     else
 4516         scriptName = top_level_config.script_name;
 4517 
 4518     envp = dmalloc (((client ? client -> envc : 2) +
 4519              client_env_count + 2) * sizeof (char *), MDL);
 4520     if (!envp) {
 4521         log_error ("No memory for client script environment.");
 4522         return 0;
 4523     }
 4524     i = 0;
 4525     /* Copy out the environment specified on the command line,
 4526        if any. */
 4527     for (sp = client_env; sp; sp = sp -> next) {
 4528         envp [i++] = sp -> string;
 4529     }
 4530     /* Copy out the environment specified by dhclient. */
 4531     if (client) {
 4532         for (sp = client -> env; sp; sp = sp -> next) {
 4533             envp [i++] = sp -> string;
 4534         }
 4535     } else {
 4536         envp [i++] = reason;
 4537     }
 4538     /* Set $PATH. */
 4539     envp [i++] = client_path;
 4540     envp [i] = (char *)0;
 4541 
 4542     argv [0] = scriptName;
 4543     argv [1] = (char *)0;
 4544 
 4545     pid = fork ();
 4546     if (pid < 0) {
 4547         log_error ("fork: %m");
 4548         wstatus = 0;
 4549     } else if (pid) {
 4550         do {
 4551             wpid = wait (&wstatus);
 4552         } while (wpid != pid && wpid > 0);
 4553         if (wpid < 0) {
 4554             log_error ("wait: %m");
 4555             wstatus = 0;
 4556         }
 4557     } else {
 4558         /* We don't want to pass an open file descriptor for
 4559          * dhclient.leases when executing dhclient-script.
 4560          */
 4561         if (leaseFile != NULL)
 4562             fclose(leaseFile);
 4563         execve (scriptName, argv, envp);
 4564         log_error ("execve (%s, ...): %m", scriptName);
 4565         exit (0);
 4566     }
 4567 
 4568     if (client) {
 4569         for (sp = client -> env; sp; sp = next) {
 4570             next = sp -> next;
 4571             dfree (sp, MDL);
 4572         }
 4573         client -> env = (struct string_list *)0;
 4574         client -> envc = 0;
 4575     }
 4576     dfree (envp, MDL);
 4577     gettimeofday(&cur_tv, NULL);
 4578 
 4579     if (!WIFEXITED(wstatus)) {
 4580         int sigval = WTERMSIG(wstatus);
 4581         log_error ("script_go script: %s was terminated by signal %d", scriptName, sigval);
 4582         return  (-sigval);
 4583     }
 4584 
 4585     return (WEXITSTATUS(wstatus));
 4586 }
 4587 
 4588 void client_envadd (struct client_state *client,
 4589             const char *prefix, const char *name, const char *fmt, ...)
 4590 {
 4591     char spbuf [1024];
 4592     char *s;
 4593     unsigned len;
 4594     struct string_list *val;
 4595     va_list list;
 4596 
 4597     va_start (list, fmt);
 4598     len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
 4599     va_end (list);
 4600 
 4601     val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
 4602                len + sizeof *val, MDL);
 4603     if (!val) {
 4604         log_error ("client_envadd: cannot allocate space for variable");
 4605         return;
 4606     }
 4607 
 4608     s = val -> string;
 4609     strcpy (s, prefix);
 4610     strcat (s, name);
 4611     s += strlen (s);
 4612     *s++ = '=';
 4613     if (len >= sizeof spbuf) {
 4614         va_start (list, fmt);
 4615         vsnprintf (s, len + 1, fmt, list);
 4616         va_end (list);
 4617     } else {
 4618         strcpy (s, spbuf);
 4619     }
 4620 
 4621     val -> next = client -> env;
 4622     client -> env = val;
 4623     client -> envc++;
 4624 }
 4625 
 4626 int dhcp_option_ev_name (buf, buflen, option)
 4627     char *buf;
 4628     size_t buflen;
 4629     struct option *option;
 4630 {
 4631     int i, j;
 4632     const char *s;
 4633 
 4634     j = 0;
 4635     if (option -> universe != &dhcp_universe) {
 4636         s = option -> universe -> name;
 4637         i = 0;
 4638     } else {
 4639         s = option -> name;
 4640         i = 1;
 4641     }
 4642 
 4643     do {
 4644         while (*s) {
 4645             if (j + 1 == buflen)
 4646                 return 0;
 4647             if (*s == '-')
 4648                 buf [j++] = '_';
 4649             else
 4650                 buf [j++] = *s;
 4651             ++s;
 4652         }
 4653         if (!i) {
 4654             s = option -> name;
 4655             if (j + 1 == buflen)
 4656                 return 0;
 4657             buf [j++] = '_';
 4658         }
 4659         ++i;
 4660     } while (i != 2);
 4661 
 4662     buf [j] = 0;
 4663     return 1;
 4664 }
 4665 
 4666 void finish (char ret)
 4667 {
 4668     if (no_daemon || dfd[0] == -1 || dfd[1] == -1)
 4669         exit((int)ret);
 4670     if (write(dfd[1], &ret, 1) != 1)
 4671         log_fatal("write to parent: %m");
 4672     (void) close(dfd[1]);
 4673     dfd[0] = dfd[1] = -1;
 4674     exit((int)ret);
 4675 }
 4676 
 4677 void detach ()
 4678 {
 4679     char buf = 0;
 4680 
 4681     /* Don't become a daemon if the user requested otherwise. */
 4682     if (no_daemon) {
 4683         write_client_pid_file ();
 4684         return;
 4685     }
 4686 
 4687     /* Only do it once. */
 4688     if (dfd[0] == -1 || dfd[1] == -1)
 4689         return;
 4690 
 4691     /* Signal parent we started successfully. */
 4692     if (write(dfd[1], &buf, 1) != 1)
 4693         log_fatal("write to parent: %m");
 4694     (void) close(dfd[1]);
 4695     dfd[0] = dfd[1] = -1;
 4696 
 4697     /* Stop logging to stderr... */
 4698     log_perror = 0;
 4699 
 4700     /* Become session leader and get pid... */
 4701     (void) setsid ();
 4702 
 4703     /* Close standard I/O descriptors. */
 4704     (void) close(0);
 4705     (void) close(1);
 4706     (void) close(2);
 4707 
 4708     /* Reopen them on /dev/null. */
 4709     (void) open("/dev/null", O_RDWR);
 4710     (void) open("/dev/null", O_RDWR);
 4711     (void) open("/dev/null", O_RDWR);
 4712 
 4713     write_client_pid_file ();
 4714 
 4715     IGNORE_RET (chdir("/"));
 4716 
 4717 }
 4718 
 4719 void write_client_pid_file ()
 4720 {
 4721     FILE *pf;
 4722     int pfdesc;
 4723 
 4724     /* nothing to do if the user doesn't want a pid file */
 4725     if (no_pid_file == ISC_TRUE) {
 4726         return;
 4727     }
 4728 
 4729     pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
 4730 
 4731     if (pfdesc < 0) {
 4732         log_error ("Can't create %s: %m", path_dhclient_pid);
 4733         return;
 4734     }
 4735 
 4736     pf = fdopen (pfdesc, "w");
 4737     if (!pf) {
 4738         close(pfdesc);
 4739         log_error ("Can't fdopen %s: %m", path_dhclient_pid);
 4740     } else {
 4741         fprintf (pf, "%ld\n", (long)getpid ());
 4742         fclose (pf);
 4743     }
 4744 }
 4745 
 4746 void client_location_changed ()
 4747 {
 4748     struct interface_info *ip;
 4749     struct client_state *client;
 4750 
 4751     for (ip = interfaces; ip; ip = ip -> next) {
 4752         for (client = ip -> client; client; client = client -> next) {
 4753             switch (client -> state) {
 4754                   case S_SELECTING:
 4755                 cancel_timeout (send_discover, client);
 4756                 break;
 4757 
 4758                   case S_BOUND:
 4759                 cancel_timeout (state_bound, client);
 4760                 break;
 4761 
 4762                   case S_REBOOTING:
 4763                   case S_REQUESTING:
 4764                   case S_RENEWING:
 4765                 cancel_timeout (send_request, client);
 4766                 break;
 4767 
 4768                   case S_INIT:
 4769                   case S_REBINDING:
 4770                   case S_STOPPED:
 4771                   case S_DECLINING:
 4772                   case S_V6ONLY:
 4773                 break;
 4774             }
 4775             client -> state = S_INIT;
 4776             state_reboot (client);
 4777         }
 4778     }
 4779 }
 4780 
 4781 void do_release(client)
 4782     struct client_state *client;
 4783 {
 4784     struct data_string ds;
 4785     struct option_cache *oc;
 4786 
 4787 #if defined(DHCPv6) && defined(DHCP4o6)
 4788     if (dhcpv4_over_dhcpv6 && (dhcp4o6_state <= 0)) {
 4789         if (dhcp4o6_state < 0)
 4790             dhcp4o6_poll(NULL);
 4791         client->pending = P_RELEASE;
 4792         return;
 4793     }
 4794 #endif
 4795 
 4796     /* Pick a random xid. */
 4797     client -> xid = random ();
 4798 
 4799     /* is there even a lease to release? */
 4800     if (client -> active) {
 4801         /* Make a DHCPRELEASE packet, and set appropriate per-interface
 4802            flags. */
 4803         make_release (client, client -> active);
 4804 
 4805         memset (&ds, 0, sizeof ds);
 4806         oc = lookup_option (&dhcp_universe,
 4807                     client -> active -> options,
 4808                     DHO_DHCP_SERVER_IDENTIFIER);
 4809         if (oc &&
 4810             evaluate_option_cache (&ds, (struct packet *)0,
 4811                        (struct lease *)0, client,
 4812                        (struct option_state *)0,
 4813                        client -> active -> options,
 4814                        &global_scope, oc, MDL)) {
 4815             if (ds.len > 3) {
 4816                 memcpy (client -> destination.iabuf,
 4817                     ds.data, 4);
 4818                 client -> destination.len = 4;
 4819             } else
 4820                 client -> destination = iaddr_broadcast;
 4821 
 4822             data_string_forget (&ds, MDL);
 4823         } else
 4824             client -> destination = iaddr_broadcast;
 4825         client -> first_sending = cur_time;
 4826         client -> interval = client -> config -> initial_interval;
 4827 
 4828         /* Zap the medium list... */
 4829         client -> medium = (struct string_list *)0;
 4830 
 4831         /* Send out the first and only DHCPRELEASE packet. */
 4832         send_release (client);
 4833 
 4834         /* Do the client script RELEASE operation. */
 4835         script_init (client,
 4836                  "RELEASE", (struct string_list *)0);
 4837         if (client -> alias)
 4838             script_write_params(client, "alias_",
 4839                         client -> alias);
 4840         script_write_params(client, "old_", client -> active);
 4841         script_write_requested(client);
 4842         script_go(client);
 4843     }
 4844 
 4845     /* Cancel any timeouts. */
 4846     cancel_timeout (state_bound, client);
 4847     cancel_timeout (send_discover, client);
 4848     cancel_timeout (state_init, client);
 4849     cancel_timeout (send_request, client);
 4850     cancel_timeout (state_reboot, client);
 4851     cancel_timeout (finish_v6only, client);
 4852     client -> state = S_STOPPED;
 4853 
 4854 #if defined(DHCPv6) && defined(DHCP4o6)
 4855     if (dhcpv4_over_dhcpv6)
 4856         finish(0);
 4857 #endif
 4858 }
 4859 
 4860 int dhclient_interface_shutdown_hook (struct interface_info *interface)
 4861 {
 4862     do_release (interface -> client);
 4863 
 4864     return 1;
 4865 }
 4866 
 4867 int dhclient_interface_discovery_hook (struct interface_info *tmp)
 4868 {
 4869     struct interface_info *last, *ip;
 4870     /* See if we can find the client from dummy_interfaces */
 4871     last = 0;
 4872     for (ip = dummy_interfaces; ip; ip = ip -> next) {
 4873         if (!strcmp (ip -> name, tmp -> name)) {
 4874             /* Remove from dummy_interfaces */
 4875             if (last) {
 4876                 ip = (struct interface_info *)0;
 4877                 interface_reference (&ip, last -> next, MDL);
 4878                 interface_dereference (&last -> next, MDL);
 4879                 if (ip -> next) {
 4880                     interface_reference (&last -> next,
 4881                                  ip -> next, MDL);
 4882                     interface_dereference (&ip -> next,
 4883                                    MDL);
 4884                 }
 4885             } else {
 4886                 ip = (struct interface_info *)0;
 4887                 interface_reference (&ip,
 4888                              dummy_interfaces, MDL);
 4889                 interface_dereference (&dummy_interfaces, MDL);
 4890                 if (ip -> next) {
 4891                     interface_reference (&dummy_interfaces,
 4892                                  ip -> next, MDL);
 4893                     interface_dereference (&ip -> next,
 4894                                    MDL);
 4895                 }
 4896             }
 4897             /* Copy "client" to tmp */
 4898             if (ip -> client) {
 4899                 tmp -> client = ip -> client;
 4900                 tmp -> client -> interface = tmp;
 4901             }
 4902             interface_dereference (&ip, MDL);
 4903             break;
 4904         }
 4905         last = ip;
 4906     }
 4907     return 1;
 4908 }
 4909 
 4910 isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
 4911 {
 4912     struct interface_info *ip;
 4913     struct client_state *client;
 4914 
 4915     /* This code needs some rethinking.   It doesn't test against
 4916        a signal name, and it just kind of bulls into doing something
 4917        that may or may not be appropriate. */
 4918 
 4919     if (interfaces) {
 4920         interface_reference (&interface -> next, interfaces, MDL);
 4921         interface_dereference (&interfaces, MDL);
 4922     }
 4923     interface_reference (&interfaces, interface, MDL);
 4924 
 4925     discover_interfaces (DISCOVER_UNCONFIGURED);
 4926 
 4927     for (ip = interfaces; ip; ip = ip -> next) {
 4928         /* If interfaces were specified, don't configure
 4929            interfaces that weren't specified! */
 4930         if (ip -> flags & INTERFACE_RUNNING ||
 4931            (ip -> flags & (INTERFACE_REQUESTED |
 4932                      INTERFACE_AUTOMATIC)) !=
 4933              INTERFACE_REQUESTED)
 4934             continue;
 4935         script_init (ip -> client,
 4936                  "PREINIT", (struct string_list *)0);
 4937         if (ip -> client -> alias)
 4938             script_write_params(ip -> client, "alias_",
 4939                         ip -> client -> alias);
 4940         script_go(ip -> client);
 4941     }
 4942 
 4943     discover_interfaces (interfaces_requested != 0
 4944                  ? DISCOVER_REQUESTED
 4945                  : DISCOVER_RUNNING);
 4946 
 4947     for (ip = interfaces; ip; ip = ip -> next) {
 4948         if (ip -> flags & INTERFACE_RUNNING)
 4949             continue;
 4950         ip -> flags |= INTERFACE_RUNNING;
 4951         for (client = ip->client ; client ; client = client->next) {
 4952             client->state = S_INIT;
 4953             state_reboot(client);
 4954         }
 4955     }
 4956     return ISC_R_SUCCESS;
 4957 }
 4958 
 4959 /* The client should never receive a relay agent information option,
 4960    so if it does, log it and discard it. */
 4961 
 4962 int parse_agent_information_option (packet, len, data)
 4963     struct packet *packet;
 4964     int len;
 4965     u_int8_t *data;
 4966 {
 4967     return 1;
 4968 }
 4969 
 4970 /* The client never sends relay agent information options. */
 4971 
 4972 unsigned cons_agent_information_options (cfg_options, outpacket,
 4973                      agentix, length)
 4974     struct option_state *cfg_options;
 4975     struct dhcp_packet *outpacket;
 4976     unsigned agentix;
 4977     unsigned length;
 4978 {
 4979     return length;
 4980 }
 4981 
 4982 static void shutdown_exit (void *foo)
 4983 {
 4984     /* get rid of the pid if we can */
 4985     if (no_pid_file == ISC_FALSE)
 4986         (void) unlink(path_dhclient_pid);
 4987     finish(0);
 4988 }
 4989 
 4990 #if defined (NSUPDATE)
 4991 /*
 4992  * If the first query fails, the updater MUST NOT delete the DNS name.  It
 4993  * may be that the host whose lease on the server has expired has moved
 4994  * to another network and obtained a lease from a different server,
 4995  * which has caused the client's A RR to be replaced. It may also be
 4996  * that some other client has been configured with a name that matches
 4997  * the name of the DHCP client, and the policy was that the last client
 4998  * to specify the name would get the name.  In this case, the DHCID RR
 4999  * will no longer match the updater's notion of the client-identity of
 5000  * the host pointed to by the DNS name.
 5001  *   -- "Interaction between DHCP and DNS"
 5002  */
 5003 
 5004 /* The first and second stages are pretty similar so we combine them */
 5005 void
 5006 client_dns_remove_action(dhcp_ddns_cb_t *ddns_cb,
 5007              isc_result_t    eresult)
 5008 {
 5009 
 5010     isc_result_t result;
 5011 
 5012     if ((eresult == ISC_R_SUCCESS) &&
 5013         (ddns_cb->state == DDNS_STATE_REM_FW_YXDHCID)) {
 5014         /* Do the second stage of the FWD removal */
 5015         ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
 5016 
 5017         result = ddns_modify_fwd(ddns_cb, MDL);
 5018         if (result == ISC_R_SUCCESS) {
 5019             return;
 5020         }
 5021     }
 5022 
 5023     /* If we are done or have an error clean up */
 5024     dhclient_ddns_cb_free(ddns_cb, MDL);
 5025     return;
 5026 }
 5027 
 5028 void
 5029 client_dns_remove(struct client_state *client,
 5030           struct iaddr        *addr)
 5031 {
 5032     dhcp_ddns_cb_t *ddns_cb;
 5033     isc_result_t result;
 5034 
 5035     /* if we have an old ddns request for this client, cancel it */
 5036     if (client->ddns_cb != NULL) {
 5037         ddns_cancel(client->ddns_cb, MDL);
 5038         client->ddns_cb = NULL;
 5039     }
 5040 
 5041     ddns_cb = ddns_cb_alloc(MDL);
 5042     if (ddns_cb != NULL) {
 5043         ddns_cb->address = *addr;
 5044         ddns_cb->timeout = 0;
 5045 
 5046         ddns_cb->state = DDNS_STATE_REM_FW_YXDHCID;
 5047         ddns_cb->flags = DDNS_UPDATE_ADDR;
 5048         ddns_cb->cur_func = client_dns_remove_action;
 5049 
 5050         result = client_dns_update(client, ddns_cb);
 5051 
 5052         if (result != ISC_R_TIMEDOUT) {
 5053             dhclient_ddns_cb_free(ddns_cb, MDL);
 5054         }
 5055     }
 5056 }
 5057 #endif /* defined NSUPDATE */
 5058 
 5059 
 5060 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
 5061                      control_object_state_t newstate)
 5062 {
 5063     struct interface_info *ip;
 5064     struct client_state *client;
 5065     struct timeval tv;
 5066 
 5067     if (newstate == server_shutdown) {
 5068         /* Re-entry */
 5069         if (shutdown_signal == SIGUSR1)
 5070             return ISC_R_SUCCESS;
 5071         /* Log shutdown on signal. */
 5072         if ((shutdown_signal == SIGINT) ||
 5073             (shutdown_signal == SIGTERM)) {
 5074             log_info("Received signal %d, initiating shutdown.",
 5075                  shutdown_signal);
 5076         }
 5077         /* Mark it was called. */
 5078         shutdown_signal = SIGUSR1;
 5079     }
 5080 
 5081     /* Do the right thing for each interface. */
 5082     for (ip = interfaces; ip; ip = ip -> next) {
 5083         for (client = ip -> client; client; client = client -> next) {
 5084         switch (newstate) {
 5085           case server_startup:
 5086             return ISC_R_SUCCESS;
 5087 
 5088           case server_running:
 5089             return ISC_R_SUCCESS;
 5090 
 5091           case server_shutdown:
 5092             if (client -> active &&
 5093             client -> active -> expiry > cur_time) {
 5094 #if defined (NSUPDATE)
 5095                 if (client->config->do_forward_update) {
 5096                     client_dns_remove(client,
 5097                               &client->active->address);
 5098                 }
 5099 #endif /* defined NSUPDATE */
 5100 
 5101                 do_release (client);
 5102             }
 5103             break;
 5104 
 5105           case server_hibernate:
 5106             state_stop (client);
 5107             break;
 5108 
 5109           case server_awaken:
 5110             state_reboot (client);
 5111             break;
 5112         }
 5113         }
 5114     }
 5115 
 5116     if (newstate == server_shutdown) {
 5117         tv.tv_sec = cur_tv.tv_sec;
 5118         tv.tv_usec = cur_tv.tv_usec + 1;
 5119         add_timeout(&tv, shutdown_exit, 0, 0, 0);
 5120     }
 5121     return ISC_R_SUCCESS;
 5122 }
 5123 
 5124 #if defined (NSUPDATE)
 5125 /*
 5126  * Called after a timeout if the DNS update failed on the previous try.
 5127  * Starts the retry process.  If the retry times out it will schedule
 5128  * this routine to run again after a 10x wait.
 5129  */
 5130 void
 5131 client_dns_update_timeout (void *cp)
 5132 {
 5133     dhcp_ddns_cb_t *ddns_cb = (dhcp_ddns_cb_t *)cp;
 5134     struct client_state *client = (struct client_state *)ddns_cb->lease;
 5135     isc_result_t status = ISC_R_FAILURE;
 5136 
 5137     if ((client != NULL) &&
 5138         ((client->active != NULL) ||
 5139          (client->active_lease != NULL)))
 5140         status = client_dns_update(client, ddns_cb);
 5141 
 5142     /*
 5143      * A status of timedout indicates that we started the update and
 5144      * have released control of the control block.  Any other status
 5145      * indicates that we should clean up the control block.  We either
 5146      * got a success which indicates that we didn't really need to
 5147      * send an update or some other error in which case we weren't able
 5148      * to start the update process.  In both cases we still own
 5149      * the control block and should free it.
 5150      */
 5151     if (status != ISC_R_TIMEDOUT) {
 5152         dhclient_ddns_cb_free(ddns_cb, MDL);
 5153     }
 5154 }
 5155 
 5156 /*
 5157  * If the first query succeeds, the updater can conclude that it
 5158  * has added a new name whose only RRs are the A and DHCID RR records.
 5159  * The A RR update is now complete (and a client updater is finished,
 5160  * while a server might proceed to perform a PTR RR update).
 5161  *   -- "Interaction between DHCP and DNS"
 5162  *
 5163  * If the second query succeeds, the updater can conclude that the current
 5164  * client was the last client associated with the domain name, and that
 5165  * the name now contains the updated A RR. The A RR update is now
 5166  * complete (and a client updater is finished, while a server would
 5167  * then proceed to perform a PTR RR update).
 5168  *   -- "Interaction between DHCP and DNS"
 5169  *
 5170  * If the second query fails with NXRRSET, the updater must conclude
 5171  * that the client's desired name is in use by another host.  At this
 5172  * juncture, the updater can decide (based on some administrative
 5173  * configuration outside of the scope of this document) whether to let
 5174  * the existing owner of the name keep that name, and to (possibly)
 5175  * perform some name disambiguation operation on behalf of the current
 5176  * client, or to replace the RRs on the name with RRs that represent
 5177  * the current client. If the configured policy allows replacement of
 5178  * existing records, the updater submits a query that deletes the
 5179  * existing A RR and the existing DHCID RR, adding A and DHCID RRs that
 5180  * represent the IP address and client-identity of the new client.
 5181  *   -- "Interaction between DHCP and DNS"
 5182  */
 5183 
 5184 /* The first and second stages are pretty similar so we combine them */
 5185 void
 5186 client_dns_update_action(dhcp_ddns_cb_t *ddns_cb,
 5187              isc_result_t    eresult)
 5188 {
 5189     isc_result_t result;
 5190     struct timeval tv;
 5191 
 5192     switch(eresult) {
 5193     case ISC_R_SUCCESS:
 5194     default:
 5195         /* Either we succeeded or broke in a bad way, clean up */
 5196         break;
 5197 
 5198     case DNS_R_YXRRSET:
 5199         /*
 5200          * This is the only difference between the two stages,
 5201          * check to see if it is the first stage, in which case
 5202          * start the second stage
 5203          */
 5204         if (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) {
 5205             ddns_cb->state = DDNS_STATE_ADD_FW_YXDHCID;
 5206             ddns_cb->cur_func = client_dns_update_action;
 5207 
 5208             result = ddns_modify_fwd(ddns_cb, MDL);
 5209             if (result == ISC_R_SUCCESS) {
 5210                 return;
 5211             }
 5212         }
 5213         break;
 5214 
 5215     case ISC_R_TIMEDOUT:
 5216         /*
 5217          * We got a timeout response from the DNS module.  Schedule
 5218          * another attempt for later.  We forget the name, dhcid and
 5219          * zone so if it gets changed we will get the new information.
 5220          */
 5221         data_string_forget(&ddns_cb->fwd_name, MDL);
 5222         data_string_forget(&ddns_cb->dhcid, MDL);
 5223         if (ddns_cb->zone != NULL) {
 5224             forget_zone((struct dns_zone **)&ddns_cb->zone);
 5225         }
 5226 
 5227         /* Reset to doing the first stage */
 5228         ddns_cb->state    = DDNS_STATE_ADD_FW_NXDOMAIN;
 5229         ddns_cb->cur_func = client_dns_update_action;
 5230 
 5231         /* and update our timer */
 5232         if (ddns_cb->timeout < 3600)
 5233             ddns_cb->timeout *= 10;
 5234         tv.tv_sec = cur_tv.tv_sec + ddns_cb->timeout;
 5235         tv.tv_usec = cur_tv.tv_usec;
 5236         add_timeout(&tv, client_dns_update_timeout,
 5237                 ddns_cb, NULL, NULL);
 5238         return;
 5239     }
 5240 
 5241     dhclient_ddns_cb_free(ddns_cb, MDL);
 5242     return;
 5243 }
 5244 
 5245 /* See if we should do a DNS update, and if so, do it. */
 5246 
 5247 isc_result_t
 5248 client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
 5249 {
 5250     struct data_string client_identifier;
 5251     struct option_cache *oc;
 5252     int ignorep;
 5253     int result;
 5254     int ddns_v4_type;
 5255     isc_result_t rcode;
 5256 
 5257     /* If we didn't send an FQDN option, we certainly aren't going to
 5258        be doing an update. */
 5259     if (!client -> sent_options)
 5260         return ISC_R_SUCCESS;
 5261 
 5262     /* If we don't have a lease, we can't do an update. */
 5263     if ((client->active == NULL) && (client->active_lease == NULL))
 5264         return ISC_R_SUCCESS;
 5265 
 5266     /* If we set the no client update flag, don't do the update. */
 5267     if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
 5268                   FQDN_NO_CLIENT_UPDATE)) &&
 5269         evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
 5270                        (struct lease *)0, client,
 5271                        client -> sent_options,
 5272                        (struct option_state *)0,
 5273                        &global_scope, oc, MDL))
 5274         return ISC_R_SUCCESS;
 5275 
 5276     /* If we set the "server, please update" flag, or didn't set it
 5277        to false, don't do the update. */
 5278     if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
 5279                   FQDN_SERVER_UPDATE)) ||
 5280         evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
 5281                        (struct lease *)0, client,
 5282                        client -> sent_options,
 5283                        (struct option_state *)0,
 5284                        &global_scope, oc, MDL))
 5285         return ISC_R_SUCCESS;
 5286 
 5287     /* If no FQDN option was supplied, don't do the update. */
 5288     if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
 5289                   FQDN_FQDN)) ||
 5290         !evaluate_option_cache (&ddns_cb->fwd_name, (struct packet *)0,
 5291                     (struct lease *)0, client,
 5292                     client -> sent_options,
 5293                     (struct option_state *)0,
 5294                     &global_scope, oc, MDL))
 5295         return ISC_R_SUCCESS;
 5296 
 5297     /*
 5298      * Construct the DHCID value for use in the DDNS update process
 5299      * We have the newer standard version and the older interim version
 5300      * chosen by the '-I' option.  The interim version is left as is
 5301      * for backwards compatibility.  The standard version is based on
 5302      * RFC 4701 section 3.3
 5303      */
 5304 
 5305     result = 0;
 5306     POST(result);
 5307     memset(&client_identifier, 0, sizeof(client_identifier));
 5308 
 5309     if (std_dhcid == 1) {
 5310         /* standard style */
 5311         ddns_cb->dhcid_class = dns_rdatatype_dhcid;
 5312         ddns_v4_type = 1;
 5313     } else {
 5314         /* interim style */
 5315         ddns_cb->dhcid_class = dns_rdatatype_txt;
 5316         /* for backwards compatibility */
 5317         ddns_v4_type = DHO_DHCP_CLIENT_IDENTIFIER;
 5318     }
 5319     if (client->active_lease != NULL) {
 5320         /* V6 request, get the client identifier, then
 5321          * construct the dhcid for either standard
 5322          * or interim */
 5323         if (((oc = lookup_option(&dhcpv6_universe,
 5324                      client->sent_options,
 5325                      D6O_CLIENTID)) != NULL) &&
 5326             evaluate_option_cache(&client_identifier, NULL,
 5327                       NULL, client,
 5328                       client->sent_options, NULL,
 5329                       &global_scope, oc, MDL)) {
 5330             result = get_dhcid(ddns_cb, 2,
 5331                        client_identifier.data,
 5332                        client_identifier.len);
 5333             data_string_forget(&client_identifier, MDL);
 5334         } else
 5335             log_fatal("Impossible condition at %s:%d.", MDL);
 5336     } else {
 5337         /*
 5338          * V4 request, use the client id if there is one or the
 5339          * mac address if there isn't.  If we have a client id
 5340          * we check to see if it is an embedded DUID.
 5341          */
 5342         if (((oc = lookup_option(&dhcp_universe,
 5343                      client->sent_options,
 5344                      DHO_DHCP_CLIENT_IDENTIFIER)) != NULL) &&
 5345             evaluate_option_cache(&client_identifier, NULL,
 5346                       NULL, client,
 5347                       client->sent_options, NULL,
 5348                       &global_scope, oc, MDL)) {
 5349             if ((std_dhcid == 1) && (duid_v4 == 1) &&
 5350                 (client_identifier.data[0] == 255)) {
 5351                 /*
 5352                  * This appears to be an embedded DUID,
 5353                  * extract it and treat it as such
 5354                  */
 5355                 if (client_identifier.len <= 5)
 5356                     log_fatal("Impossible condition at %s:%d.",
 5357                           MDL);
 5358                 result = get_dhcid(ddns_cb, 2,
 5359                            client_identifier.data + 5,
 5360                            client_identifier.len - 5);
 5361             } else {
 5362                 result = get_dhcid(ddns_cb, ddns_v4_type,
 5363                            client_identifier.data,
 5364                            client_identifier.len);
 5365             }
 5366             data_string_forget(&client_identifier, MDL);
 5367         } else
 5368             result = get_dhcid(ddns_cb, 0,
 5369                        client->interface->hw_address.hbuf,
 5370                        client->interface->hw_address.hlen);
 5371     }
 5372 
 5373     if (!result) {
 5374         return ISC_R_SUCCESS;
 5375     }
 5376 
 5377     /*
 5378      * Perform updates.
 5379      */
 5380     if (ddns_cb->fwd_name.len && ddns_cb->dhcid.len) {
 5381         rcode = ddns_modify_fwd(ddns_cb, MDL);
 5382     } else
 5383         rcode = ISC_R_FAILURE;
 5384 
 5385     /*
 5386      * A success from the modify routine means we are performing
 5387      * async processing, for which we use the timedout error message.
 5388      */
 5389     if (rcode == ISC_R_SUCCESS) {
 5390         rcode = ISC_R_TIMEDOUT;
 5391     }
 5392 
 5393     return rcode;
 5394 }
 5395 
 5396 
 5397 /*
 5398  * Schedule the first update.  They will continue to retry occasionally
 5399  * until they no longer time out (or fail).
 5400  */
 5401 void
 5402 dhclient_schedule_updates(struct client_state *client,
 5403               struct iaddr        *addr,
 5404               int                  offset)
 5405 {
 5406     dhcp_ddns_cb_t *ddns_cb;
 5407     struct timeval tv;
 5408 
 5409     if (!client->config->do_forward_update)
 5410         return;
 5411 
 5412     /* cancel any outstanding ddns requests */
 5413     if (client->ddns_cb != NULL) {
 5414         ddns_cancel(client->ddns_cb, MDL);
 5415         client->ddns_cb = NULL;
 5416     }
 5417 
 5418     ddns_cb = ddns_cb_alloc(MDL);
 5419 
 5420     if (ddns_cb != NULL) {
 5421         ddns_cb->lease = (void *)client;
 5422         ddns_cb->address = *addr;
 5423         ddns_cb->timeout = 1;
 5424 
 5425         /*
 5426          * XXX: DNS TTL is a problem we need to solve properly.
 5427          * Until that time, 300 is a placeholder default for
 5428          * something that is less insane than a value scaled
 5429          * by lease timeout.
 5430          */
 5431         ddns_cb->ttl = 300;
 5432 
 5433         ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
 5434         ddns_cb->cur_func = client_dns_update_action;
 5435         ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_INCLUDE_RRSET;
 5436 
 5437         client->ddns_cb = ddns_cb;
 5438         tv.tv_sec = cur_tv.tv_sec + offset;
 5439         tv.tv_usec = cur_tv.tv_usec;
 5440         add_timeout(&tv, client_dns_update_timeout,
 5441                 ddns_cb, NULL, NULL);
 5442     } else {
 5443         log_error("Unable to allocate dns update state for %s",
 5444               piaddr(*addr));
 5445     }
 5446 }
 5447 #endif /* defined NSUPDATE */
 5448 
 5449 void
 5450 dhcpv4_client_assignments(void)
 5451 {
 5452     struct servent *ent;
 5453 
 5454     if (path_dhclient_pid == NULL)
 5455         path_dhclient_pid = _PATH_DHCLIENT_PID;
 5456     if (path_dhclient_db == NULL)
 5457         path_dhclient_db = _PATH_DHCLIENT_DB;
 5458 
 5459     /* Default to the DHCP/BOOTP port. */
 5460     if (!local_port) {
 5461         /* If we're faking a relay agent, and we're not using loopback,
 5462            use the server port, not the client port. */
 5463         if (mockup_relay && giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
 5464             local_port = htons(67);
 5465         } else {
 5466             ent = getservbyname("dhcpc", "udp");
 5467             if (ent == NULL)
 5468                 ent = getservbyname("bootpc", "udp");
 5469             if (ent == NULL)
 5470                 local_port = htons(68);
 5471             else
 5472                 local_port = ent->s_port;
 5473 #ifndef __CYGWIN32__
 5474             endservent ();
 5475 #endif
 5476         }
 5477     }
 5478 
 5479     /* If we're faking a relay agent, and we're not using loopback,
 5480        we're using the server port, not the client port. */
 5481     if (mockup_relay && giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
 5482         remote_port = local_port;
 5483     } else
 5484         remote_port = htons(ntohs(local_port) - 1);   /* XXX */
 5485 }
 5486 
 5487 /*
 5488  * The following routines are used to check that certain
 5489  * strings are reasonable before we pass them to the scripts.
 5490  * This avoids some problems with scripts treating the strings
 5491  * as commands - see ticket 23722
 5492  * The domain checking code should be done as part of assembling
 5493  * the string but we are doing it here for now due to time
 5494  * constraints.
 5495  */
 5496 
 5497 static int check_domain_name(const char *ptr, size_t len, int dots)
 5498 {
 5499     const char *p;
 5500 
 5501     /* not empty or complete length not over 255 characters   */
 5502     if ((len == 0) || (len > 256))
 5503         return(-1);
 5504 
 5505     /* consists of [[:alnum:]-]+ labels separated by [.]      */
 5506     /* a [_] is against RFC but seems to be "widely used"...  */
 5507     for (p=ptr; (*p != 0) && (len-- > 0); p++) {
 5508         if ((*p == '-') || (*p == '_')) {
 5509             /* not allowed at begin or end of a label */
 5510             if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
 5511                 return(-1);
 5512         } else if (*p == '.') {
 5513             /* each label has to be 1-63 characters;
 5514                we allow [.] at the end ('foo.bar.')   */
 5515             size_t d = p - ptr;
 5516             if ((d <= 0) || (d >= 64))
 5517                 return(-1);
 5518             ptr = p + 1; /* jump to the next label    */
 5519             if ((dots > 0) && (len > 0))
 5520                 dots--;
 5521         } else if (isalnum((unsigned char)*p) == 0) {
 5522             /* also numbers at the begin are fine     */
 5523             return(-1);
 5524         }
 5525     }
 5526     return(dots ? -1 : 0);
 5527 }
 5528 
 5529 static int check_domain_name_list(const char *ptr, size_t len, int dots)
 5530 {
 5531     const char *p;
 5532     int ret = -1; /* at least one needed */
 5533 
 5534     if ((ptr == NULL) || (len == 0))
 5535         return(-1);
 5536 
 5537     for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
 5538         if (*p != ' ')
 5539             continue;
 5540         if (p > ptr) {
 5541             if (check_domain_name(ptr, p - ptr, dots) != 0)
 5542                 return(-1);
 5543             ret = 0;
 5544         }
 5545         ptr = p + 1;
 5546     }
 5547     if (p > ptr)
 5548         return(check_domain_name(ptr, p - ptr, dots));
 5549     else
 5550         return(ret);
 5551 }
 5552 
 5553 static int check_option_values(struct universe *universe,
 5554                    unsigned int opt,
 5555                    const char *ptr,
 5556                    size_t len)
 5557 {
 5558     if (ptr == NULL)
 5559         return(-1);
 5560 
 5561     /* just reject options we want to protect, will be escaped anyway */
 5562     if ((universe == NULL) || (universe == &dhcp_universe)) {
 5563         switch(opt) {
 5564               case DHO_DOMAIN_NAME:
 5565 #ifdef ACCEPT_LIST_IN_DOMAIN_NAME
 5566                   return check_domain_name_list(ptr, len, 0);
 5567 #else
 5568                   return check_domain_name(ptr, len, 0);
 5569 #endif
 5570               case DHO_HOST_NAME:
 5571               case DHO_NIS_DOMAIN:
 5572               case DHO_NETBIOS_SCOPE:
 5573             return check_domain_name(ptr, len, 0);
 5574             break;
 5575               case DHO_DOMAIN_SEARCH:
 5576             return check_domain_name_list(ptr, len, 0);
 5577             break;
 5578               case DHO_ROOT_PATH:
 5579             if (len == 0)
 5580                 return(-1);
 5581             for (; (*ptr != 0) && (len-- > 0); ptr++) {
 5582                 if(!(isalnum((unsigned char)*ptr) ||
 5583                      *ptr == '#'  || *ptr == '%' ||
 5584                      *ptr == '+'  || *ptr == '-' ||
 5585                      *ptr == '_'  || *ptr == ':' ||
 5586                      *ptr == '.'  || *ptr == ',' ||
 5587                      *ptr == '@'  || *ptr == '~' ||
 5588                      *ptr == '\\' || *ptr == '/' ||
 5589                      *ptr == '['  || *ptr == ']' ||
 5590                      *ptr == '='  || *ptr == ' '))
 5591                     return(-1);
 5592             }
 5593             return(0);
 5594             break;
 5595         }
 5596     }
 5597 
 5598 #ifdef DHCPv6
 5599     if (universe == &dhcpv6_universe) {
 5600         switch(opt) {
 5601               case D6O_SIP_SERVERS_DNS:
 5602               case D6O_DOMAIN_SEARCH:
 5603               case D6O_NIS_DOMAIN_NAME:
 5604               case D6O_NISP_DOMAIN_NAME:
 5605             return check_domain_name_list(ptr, len, 0);
 5606             break;
 5607         }
 5608     }
 5609 #endif
 5610 
 5611     return(0);
 5612 }
 5613 
 5614 static void
 5615 add_reject(struct packet *packet) {
 5616     struct iaddrmatchlist *list;
 5617 
 5618     list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
 5619     if (!list)
 5620         log_fatal ("no memory for reject list!");
 5621 
 5622     /*
 5623      * client_addr is misleading - it is set to source address in common
 5624      * code.
 5625      */
 5626     list->match.addr = packet->client_addr;
 5627     /* Set mask to indicate host address. */
 5628     list->match.mask.len = list->match.addr.len;
 5629     memset(list->match.mask.iabuf, 0xff, sizeof(list->match.mask.iabuf));
 5630 
 5631     /* Append to reject list for the source interface. */
 5632     list->next = packet->interface->client->config->reject_list;
 5633     packet->interface->client->config->reject_list = list;
 5634 
 5635     /*
 5636      * We should inform user that we won't be accepting this server
 5637      * anymore.
 5638      */
 5639     log_info("Server added to list of rejected servers.");
 5640 }
 5641 
 5642 #if defined(NSUPDATE)
 5643 /* Wrapper function around common ddns_cb_free function that ensures
 5644  * we set the client_state pointer to the control block to NULL. */
 5645 static void
 5646 dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb, char* file, int line) {
 5647     if (ddns_cb) {
 5648         struct client_state *client = (struct client_state *)ddns_cb->lease;
 5649         if (client != NULL) {
 5650             client->ddns_cb = NULL;
 5651         }
 5652 
 5653         ddns_cb_free(ddns_cb, file, line);
 5654     }
 5655 }
 5656 #endif /* defined NSUPDATE */
 5657 
 5658 #if defined(DHCPv6) && defined(DHCP4o6)
 5659 /*
 5660  * \brief Omapi I/O handler
 5661  *
 5662  * The inter-process communication receive handler.
 5663  *
 5664  * On the DHCPv6 side, the message is either a POLL (which is answered
 5665  *  by a START or a STOP) or a DHCPv4-QUERY (which is forwarded to
 5666  *  DHCPv4 over DHCPv6 servers by forw_dhcpv4_query()).
 5667  *
 5668  * On the DHCPv4 side, the message is either a START, a STOP
 5669  *  (both for the DHCP4 over DHCPv6 state machine) or a DHCPv4-RESPONSE
 5670  *  (which is processed by recv_dhcpv4_response()).
 5671  *
 5672  * \param h the OMAPI object
 5673  * \return a result for I/O success or error (used by the I/O subsystem)
 5674  */
 5675 isc_result_t dhcpv4o6_handler(omapi_object_t *h) {
 5676     char buf[65536];
 5677     char start_msg[5] = { 'S', 'T', 'A', 'R', 'T' };
 5678     char stop_msg[4] = { 'S', 'T', 'O', 'P' };
 5679     char poll_msg[4] = { 'P', 'O', 'L', 'L' };
 5680     struct data_string raw;
 5681     int cc;
 5682 
 5683     if (h->type != dhcp4o6_type)
 5684         return DHCP_R_INVALIDARG;
 5685 
 5686     cc = recv(dhcp4o6_fd, buf, sizeof(buf), 0);
 5687     if (cc <= 0)
 5688         return ISC_R_UNEXPECTED;
 5689 
 5690     if (local_family == AF_INET6) {
 5691         if ((cc == 4) &&
 5692             (memcmp(buf, poll_msg, sizeof(poll_msg)) == 0)) {
 5693             log_info("RCV: POLL");
 5694             if (dhcp4o6_state < 0)
 5695                 cc = send(dhcp4o6_fd, stop_msg,
 5696                       sizeof(stop_msg), 0);
 5697             else
 5698                 cc = send(dhcp4o6_fd, start_msg,
 5699                       sizeof(start_msg), 0);
 5700             if (cc < 0) {
 5701                 log_error("dhcpv4o6_handler: send(): %m");
 5702                 return ISC_R_IOERROR;
 5703             }
 5704         } else {
 5705             if (cc < DHCP_FIXED_NON_UDP + 8)
 5706                 return ISC_R_UNEXPECTED;
 5707             memset(&raw, 0, sizeof(raw));
 5708             if (!buffer_allocate(&raw.buffer, cc, MDL)) {
 5709                 log_error("dhcpv4o6_handler: "
 5710                       "no memory buffer.");
 5711                 return ISC_R_NOMEMORY;
 5712             }
 5713             raw.data = raw.buffer->data;
 5714             raw.len = cc;
 5715             memcpy(raw.buffer->data, buf, cc);
 5716 
 5717             forw_dhcpv4_query(&raw);
 5718 
 5719             data_string_forget(&raw, MDL);
 5720         }
 5721     } else {
 5722         if ((cc == 4) &&
 5723             (memcmp(buf, stop_msg, sizeof(stop_msg)) == 0)) {
 5724             log_info("RCV: STOP");
 5725             if (dhcp4o6_state > 0) {
 5726                 dhcp4o6_state = 0;
 5727                 dhcp4o6_poll(NULL);
 5728             }
 5729         } else if ((cc == 5) &&
 5730                (memcmp(buf, start_msg, sizeof(start_msg)) == 0)) {
 5731             log_info("RCV: START");
 5732             if (dhcp4o6_state == 0)
 5733                 cancel_timeout(dhcp4o6_poll, NULL);
 5734             dhcp4o6_state = 1;
 5735             dhcp4o6_resume();
 5736         } else {
 5737             if (cc < DHCP_FIXED_NON_UDP + 16)
 5738                 return ISC_R_UNEXPECTED;
 5739             memset(&raw, 0, sizeof(raw));
 5740             if (!buffer_allocate(&raw.buffer, cc, MDL)) {
 5741                 log_error("dhcpv4o6_handler: "
 5742                       "no memory buffer.");
 5743                 return ISC_R_NOMEMORY;
 5744             }
 5745             raw.data = raw.buffer->data;
 5746             raw.len = cc;
 5747             memcpy(raw.buffer->data, buf, cc);
 5748 
 5749             recv_dhcpv4_response(&raw);
 5750 
 5751             data_string_forget(&raw, MDL);
 5752         }
 5753     }
 5754 
 5755     return ISC_R_SUCCESS;
 5756 }
 5757 
 5758 /*
 5759  * \brief Poll the DHCPv6 client
 5760  *  (DHCPv4 client function)
 5761  *
 5762  * A POLL message is sent to the DHCPv6 client periodically to check
 5763  * if the DHCPv6 is ready (i.e., has a valid DHCPv4-over-DHCPv6 server
 5764  * address option).
 5765  */
 5766 static void dhcp4o6_poll(void *dummy) {
 5767     char msg[4] = { 'P', 'O', 'L', 'L' };
 5768     struct timeval tv;
 5769     int cc;
 5770 
 5771     IGNORE_UNUSED(dummy);
 5772 
 5773     if (dhcp4o6_state < 0)
 5774         dhcp4o6_state = 0;
 5775 
 5776     log_info("POLL");
 5777 
 5778     cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
 5779     if (cc < 0)
 5780         log_error("dhcp4o6_poll: send(): %m");
 5781 
 5782     tv.tv_sec = cur_time + 60;
 5783     tv.tv_usec = random() % 1000000;
 5784 
 5785     add_timeout(&tv, dhcp4o6_poll, NULL, 0, 0);
 5786 }
 5787 
 5788 /*
 5789  * \brief Resume pending operations
 5790  *  (DHCPv4 client function)
 5791  *
 5792  * A START message was received from the DHCPv6 client so pending
 5793  * operations (RELEASE or REBOOT) must be resumed.
 5794  */
 5795 static void dhcp4o6_resume() {
 5796     struct interface_info *ip;
 5797     struct client_state *client;
 5798 
 5799     for (ip = interfaces; ip != NULL; ip = ip->next) {
 5800         for (client = ip->client; client != NULL;
 5801              client = client->next) {
 5802             if (client->pending == P_RELEASE)
 5803                 do_release(client);
 5804             else if (client->pending == P_REBOOT)
 5805                 state_reboot(client);
 5806         }
 5807     }
 5808 }
 5809 
 5810 /*
 5811  * \brief Send a START to the DHCPv4 client
 5812  *  (DHCPv6 client function)
 5813  *
 5814  * First check if there is a valid DHCPv4-over-DHCPv6 server address option,
 5815  * and when found go UP and on a transition from another state send
 5816  * a START message to the DHCPv4 client.
 5817  */
 5818 void dhcp4o6_start() {
 5819     struct interface_info *ip;
 5820     struct client_state *client;
 5821     struct dhc6_lease *lease;
 5822     struct option_cache *oc;
 5823     struct data_string addrs;
 5824     char msg[5] = { 'S', 'T', 'A', 'R', 'T' };
 5825     int cc;
 5826 
 5827     memset(&addrs, 0, sizeof(addrs));
 5828     for (ip = interfaces; ip != NULL; ip = ip->next) {
 5829         for (client = ip->client; client != NULL;
 5830              client = client->next) {
 5831             if ((client->state != S_BOUND) &&
 5832                 (client->state != S_RENEWING) &&
 5833                 (client->state != S_REBINDING))
 5834                 continue;
 5835             lease = client->active_lease;
 5836             if ((lease == NULL) || lease->released)
 5837                 continue;
 5838             oc = lookup_option(&dhcpv6_universe,
 5839                        lease->options,
 5840                        D6O_DHCP4_O_DHCP6_SERVER);
 5841             if ((oc == NULL) ||
 5842                 !evaluate_option_cache(&addrs, NULL, NULL, NULL,
 5843                            lease->options, NULL,
 5844                            &global_scope, oc, MDL))
 5845                 continue;
 5846             if ((addrs.len % 16) != 0) {
 5847                 data_string_forget(&addrs, MDL);
 5848                 continue;
 5849             }
 5850             data_string_forget(&addrs, MDL);
 5851             goto found;
 5852         }
 5853     }
 5854     log_info("dhcp4o6_start: failed");
 5855     dhcp4o6_stop();
 5856     return;
 5857 
 5858 found:
 5859     if (dhcp4o6_state == 1)
 5860         return;
 5861     log_info("dhcp4o6_start: go to UP");
 5862     dhcp4o6_state = 1;
 5863 
 5864     cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
 5865     if (cc < 0)
 5866         log_info("dhcp4o6_start: send(): %m");
 5867 }
 5868 
 5869 /*
 5870  * Send a STOP to the DHCPv4 client
 5871  *  (DHCPv6 client function)
 5872  *
 5873  * Go DOWN and on a transition from another state send a STOP message
 5874  * to the DHCPv4 client.
 5875  */
 5876 static void dhcp4o6_stop() {
 5877     char msg[4] = { 'S', 'T', 'O', 'P' };
 5878     int cc;
 5879 
 5880     if (dhcp4o6_state == -1)
 5881         return;
 5882 
 5883     log_info("dhcp4o6_stop: go to DOWN");
 5884     dhcp4o6_state = -1;
 5885 
 5886     cc = send(dhcp4o6_fd, msg, sizeof(msg), 0);
 5887     if (cc < 0)
 5888         log_error("dhcp4o6_stop: send(): %m");
 5889 }
 5890 #endif /* DHCPv6 && DHCP4o6 */