client/dhclient.c

Go to the documentation of this file.
00001 /* dhclient.c
00002 
00003    DHCP Client. */
00004 
00005 /*
00006  * Copyright (c) 2004-2014 by Internet Systems Consortium, Inc. ("ISC")
00007  * Copyright (c) 1995-2003 by Internet Software Consortium
00008  *
00009  * Permission to use, copy, modify, and distribute this software for any
00010  * purpose with or without fee is hereby granted, provided that the above
00011  * copyright notice and this permission notice appear in all copies.
00012  *
00013  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00014  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00015  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00016  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00017  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00018  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00019  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00020  *
00021  *   Internet Systems Consortium, Inc.
00022  *   950 Charter Street
00023  *   Redwood City, CA 94063
00024  *   <info@isc.org>
00025  *   https://www.isc.org/
00026  *
00027  * This code is based on the original client state machine that was
00028  * written by Elliot Poger.  The code has been extensively hacked on
00029  * by Ted Lemon since then, so any mistakes you find are probably his
00030  * fault and not Elliot's.
00031  */
00032 
00033 #include "dhcpd.h"
00034 #include <syslog.h>
00035 #include <signal.h>
00036 #include <errno.h>
00037 #include <sys/time.h>
00038 #include <sys/wait.h>
00039 #include <limits.h>
00040 #include <dns/result.h>
00041 
00042 #ifdef HAVE_LIBCAP_NG
00043 #include <cap-ng.h>
00044 #endif
00045 
00046 /*
00047  * Defined in stdio.h when _GNU_SOURCE is set, but we don't want to define
00048  * that when building ISC code.
00049  */
00050 extern int asprintf(char **strp, const char *fmt, ...);
00051 
00052 TIME default_lease_time = 43200; /* 12 hours... */
00053 TIME max_lease_time = 86400; /* 24 hours... */
00054 
00055 const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
00056 const char *path_dhclient_db = NULL;
00057 const char *path_dhclient_pid = NULL;
00058 static char path_dhclient_script_array[] = _PATH_DHCLIENT_SCRIPT;
00059 char *path_dhclient_script = path_dhclient_script_array;
00060 
00061 /* False (default) => we write and use a pid file */
00062 isc_boolean_t no_pid_file = ISC_FALSE;
00063 
00064 int dhcp_max_agent_option_packet_length = 0;
00065 
00066 int interfaces_requested = 0;
00067 
00068 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
00069 struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
00070 struct in_addr inaddr_any;
00071 struct sockaddr_in sockaddr_broadcast;
00072 struct in_addr giaddr;
00073 struct data_string default_duid;
00074 int duid_type = 0;
00075 int duid_v4 = 1;
00076 int std_dhcid = 0;
00077 
00078 /* ASSERT_STATE() does nothing now; it used to be
00079    assert (state_is == state_shouldbe). */
00080 #define ASSERT_STATE(state_is, state_shouldbe) {}
00081 
00082 static const char copyright[] = "Copyright 2004-2014 Internet Systems Consortium.";
00083 static const char arr [] = "All rights reserved.";
00084 static const char message [] = "Internet Systems Consortium DHCP Client";
00085 static const char url [] = "For info, please visit https://www.isc.org/software/dhcp/";
00086 
00087 u_int16_t local_port = 0;
00088 u_int16_t remote_port = 0;
00089 int no_daemon = 0;
00090 struct string_list *client_env = NULL;
00091 int client_env_count = 0;
00092 int onetry = 0;
00093 int quiet = 1;
00094 int nowait = 0;
00095 int stateless = 0;
00096 int wanted_ia_na = -1;          /* the absolute value is the real one. */
00097 int wanted_ia_ta = 0;
00098 int wanted_ia_pd = 0;
00099 char *mockup_relay = NULL;
00100 int bootp_broadcast_always = 0;
00101 
00102 extern u_int32_t default_requested_options[];
00103 
00104 void run_stateless(int exit_mode);
00105 
00106 static void usage(void);
00107 
00108 static isc_result_t write_duid(struct data_string *duid);
00109 static void add_reject(struct packet *packet);
00110 
00111 static int check_domain_name(const char *ptr, size_t len, int dots);
00112 static int check_domain_name_list(const char *ptr, size_t len, int dots);
00113 static int check_option_values(struct universe *universe, unsigned int opt,
00114                                const char *ptr, size_t len);
00115 
00116 static void setup_ib_interface(struct interface_info *ip);
00117 
00118 int
00119 main(int argc, char **argv) {
00120         int fd;
00121         int i;
00122         struct interface_info *ip;
00123         struct client_state *client;
00124         unsigned seed;
00125         char *server = NULL;
00126         isc_result_t status;
00127         int exit_mode = 0;
00128         int release_mode = 0;
00129         struct timeval tv;
00130         omapi_object_t *listener;
00131         isc_result_t result;
00132         int persist = 0;
00133         int no_dhclient_conf = 0;
00134         int no_dhclient_db = 0;
00135         int no_dhclient_pid = 0;
00136         int no_dhclient_script = 0;
00137 #ifdef DHCPv6
00138         int local_family_set = 0;
00139 #endif /* DHCPv6 */
00140         char *s;
00141         char *dhcp_client_identifier_arg = NULL;
00142         char *dhcp_host_name_arg = NULL;
00143         char *dhcp_fqdn_arg = NULL;
00144         char *dhcp_vendor_class_identifier_arg = NULL;
00145         char *dhclient_request_options = NULL;
00146 
00147         int timeout_arg = 0;
00148         char *arg_conf = NULL;
00149         int arg_conf_len = 0;
00150 #ifdef HAVE_LIBCAP_NG
00151         int keep_capabilities = 0;
00152 #endif
00153 
00154         /* Initialize client globals. */
00155         memset(&default_duid, 0, sizeof(default_duid));
00156 
00157         /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
00158            2 (stderr) are open. To do this, we assume that when we
00159            open a file the lowest available file descriptor is used. */
00160         fd = open("/dev/null", O_RDWR | O_CLOEXEC);
00161         if (fd == 0)
00162                 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
00163         if (fd == 1)
00164                 fd = open("/dev/null", O_RDWR | O_CLOEXEC);
00165         if (fd == 2)
00166                 log_perror = 0; /* No sense logging to /dev/null. */
00167         else if (fd != -1)
00168                 close(fd);
00169 
00170         openlog("dhclient", LOG_NDELAY | LOG_PID, LOG_DAEMON);
00171 
00172 #if !(defined(DEBUG) || defined(__CYGWIN32__))
00173         setlogmask(LOG_UPTO(LOG_INFO));
00174 #endif
00175 
00176         /* Set up the isc and dns library managers */
00177         status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
00178                                      NULL, NULL);
00179         if (status != ISC_R_SUCCESS)
00180                 log_fatal("Can't initialize context: %s",
00181                           isc_result_totext(status));
00182 
00183         /* Set up the OMAPI. */
00184         status = omapi_init();
00185         if (status != ISC_R_SUCCESS)
00186                 log_fatal("Can't initialize OMAPI: %s",
00187                           isc_result_totext(status));
00188 
00189         /* Set up the OMAPI wrappers for various server database internal
00190            objects. */
00191         dhcp_common_objects_setup();
00192 
00193         dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
00194         dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
00195         dhcp_interface_startup_hook = dhclient_interface_startup_hook;
00196 
00197         for (i = 1; i < argc; i++) {
00198                 if (!strcmp(argv[i], "-r")) {
00199                         release_mode = 1;
00200                         no_daemon = 1;
00201 #ifdef DHCPv6
00202                 } else if (!strcmp(argv[i], "-4")) {
00203                         if (local_family_set && local_family != AF_INET)
00204                                 log_fatal("Client can only do v4 or v6, not "
00205                                           "both.");
00206                         local_family_set = 1;
00207                         local_family = AF_INET;
00208                 } else if (!strcmp(argv[i], "-6")) {
00209                         if (local_family_set && local_family != AF_INET6)
00210                                 log_fatal("Client can only do v4 or v6, not "
00211                                           "both.");
00212                         local_family_set = 1;
00213                         local_family = AF_INET6;
00214 #endif /* DHCPv6 */
00215                 } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */
00216                         release_mode = 0;
00217                         no_daemon = 0;
00218                         exit_mode = 1;
00219                 } else if (!strcmp(argv[i], "-p")) {
00220                         if (++i == argc)
00221                                 usage();
00222                         local_port = validate_port(argv[i]);
00223                         log_debug("binding to user-specified port %d",
00224                                   ntohs(local_port));
00225                 } else if (!strcmp(argv[i], "-d")) {
00226                         no_daemon = 1;
00227                         quiet = 0;
00228                 } else if (!strcmp(argv[i], "-pf")) {
00229                         if (++i == argc)
00230                                 usage();
00231                         path_dhclient_pid = argv[i];
00232                         no_dhclient_pid = 1;
00233                 } else if (!strcmp(argv[i], "--no-pid")) {
00234                         no_pid_file = ISC_TRUE;
00235                 } else if (!strcmp(argv[i], "-cf")) {
00236                         if (++i == argc)
00237                                 usage();
00238                         path_dhclient_conf = argv[i];
00239                         no_dhclient_conf = 1;
00240                 } else if (!strcmp(argv[i], "-lf")) {
00241                         if (++i == argc)
00242                                 usage();
00243                         path_dhclient_db = argv[i];
00244                         no_dhclient_db = 1;
00245                 } else if (!strcmp(argv[i], "-sf")) {
00246                         if (++i == argc)
00247                                 usage();
00248                         path_dhclient_script = argv[i];
00249                         no_dhclient_script = 1;
00250                 } else if (!strcmp(argv[i], "-1")) {
00251                         onetry = 1;
00252                 } else if (!strcmp(argv[i], "-q")) {
00253                         quiet = 1;
00254                 } else if (!strcmp(argv[i], "-s")) {
00255                         if (++i == argc)
00256                                 usage();
00257                         server = argv[i];
00258                 } else if (!strcmp(argv[i], "-g")) {
00259                         if (++i == argc)
00260                                 usage();
00261                         mockup_relay = argv[i];
00262                 } else if (!strcmp(argv[i], "-nw")) {
00263                         nowait = 1;
00264                 } else if (!strcmp(argv[i], "-n")) {
00265                         /* do not start up any interfaces */
00266                         interfaces_requested = -1;
00267                 } else if (!strcmp(argv[i], "-w")) {
00268                         /* do not exit if there are no broadcast interfaces. */
00269                         persist = 1;
00270                 } else if (!strcmp(argv[i], "-e")) {
00271                         struct string_list *tmp;
00272                         if (++i == argc)
00273                                 usage();
00274                         tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
00275                         if (!tmp)
00276                                 log_fatal("No memory for %s", argv[i]);
00277                         strcpy(tmp->string, argv[i]);
00278                         tmp->next = client_env;
00279                         client_env = tmp;
00280                         client_env_count++;
00281 #ifdef DHCPv6
00282                 } else if (!strcmp(argv[i], "-S")) {
00283                         if (local_family_set && (local_family == AF_INET)) {
00284                                 usage();
00285                         }
00286                         local_family_set = 1;
00287                         local_family = AF_INET6;
00288                         wanted_ia_na = 0;
00289                         stateless = 1;
00290                 } else if (!strcmp(argv[i], "-N")) {
00291                         if (local_family_set && (local_family == AF_INET)) {
00292                                 usage();
00293                         }
00294                         local_family_set = 1;
00295                         local_family = AF_INET6;
00296                         if (wanted_ia_na < 0) {
00297                                 wanted_ia_na = 0;
00298                         }
00299                         wanted_ia_na++;
00300                 } else if (!strcmp(argv[i], "-T")) {
00301                         if (local_family_set && (local_family == AF_INET)) {
00302                                 usage();
00303                         }
00304                         local_family_set = 1;
00305                         local_family = AF_INET6;
00306                         if (wanted_ia_na < 0) {
00307                                 wanted_ia_na = 0;
00308                         }
00309                         wanted_ia_ta++;
00310                 } else if (!strcmp(argv[i], "-P")) {
00311                         if (local_family_set && (local_family == AF_INET)) {
00312                                 usage();
00313                         }
00314                         local_family_set = 1;
00315                         local_family = AF_INET6;
00316                         if (wanted_ia_na < 0) {
00317                                 wanted_ia_na = 0;
00318                         }
00319                         wanted_ia_pd++;
00320 #endif /* DHCPv6 */
00321                 } else if (!strcmp(argv[i], "-D")) {
00322                         duid_v4 = 1;
00323                         if (++i == argc)
00324                                 usage();
00325                         if (!strcasecmp(argv[i], "LL")) {
00326                                 duid_type = DUID_LL;
00327                         } else if (!strcasecmp(argv[i], "LLT")) {
00328                                 duid_type = DUID_LLT;
00329                         } else {
00330                                 usage();
00331                         }
00332                 } else if (!strcmp(argv[i], "-i")) {
00333                         /* enable DUID support for DHCPv4 clients */
00334                         duid_v4 = 1;
00335                 } else if (!strcmp(argv[i], "-I")) {
00336                         /* enable standard DHCID support for DDNS updates */
00337                         std_dhcid = 1;
00338                 } else if (!strcmp(argv[i], "-v")) {
00339                         quiet = 0;
00340                 } else if (!strcmp(argv[i], "--version")) {
00341                         log_info("isc-dhclient-%s", PACKAGE_VERSION);
00342                         exit(0);
00343                 } else if (!strcmp(argv[i], "-C")) {
00344                         if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00345                                 usage();
00346                                 exit(1);
00347                         }
00348 
00349                         if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
00350                                 log_error("-C option dhcp-client-identifier string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
00351                                 exit(1);
00352                         }
00353 
00354                         dhcp_client_identifier_arg = argv[i];
00355                 } else if (!strcmp(argv[i], "-B")) {
00356                         bootp_broadcast_always = 1;
00357                 } else if (!strcmp(argv[i], "-H")) {
00358                         if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00359                                 usage();
00360                                 exit(1);
00361                         }
00362 
00363                         if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
00364                                 log_error("-H option host-name string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
00365                                 exit(1);
00366                         }
00367 
00368                         if (dhcp_host_name_arg != NULL) {
00369                                 log_error("The -H <host-name> and -F <fqdn> arguments are mutually exclusive");
00370                                 exit(1);
00371                         }
00372 
00373                         dhcp_host_name_arg = argv[i];
00374                 } else if (!strcmp(argv[i], "-F")) {
00375                         if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00376                                 usage();
00377                                 exit(1);
00378                         }
00379 
00380                         if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
00381                                 log_error("-F option fqdn.fqdn string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
00382                                 exit(1);
00383                         }
00384 
00385                         if (dhcp_fqdn_arg != NULL) {
00386                                 log_error("Only one -F <fqdn> argument can be specified");
00387                                 exit(1);
00388                         }
00389 
00390                         if (dhcp_host_name_arg != NULL) {
00391                                 log_error("The -F <fqdn> and -H <host-name> arguments are mutually exclusive");
00392                                 exit(1);
00393                         }
00394 
00395                         dhcp_fqdn_arg = argv[i];
00396                 } else if (!strcmp(argv[i], "-timeout")) {
00397                         if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00398                                 usage();
00399                                 exit(1);
00400                         }
00401 
00402                         if ((timeout_arg = atoi(argv[i])) <= 0) {
00403                                 log_error("timeout option must be > 0 - bad value: %s",argv[i]);
00404                                 exit(1);
00405                         }
00406                 } else if (!strcmp(argv[i], "-V")) {
00407                         if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00408                                 usage();
00409                                 exit(1);
00410                         }
00411 
00412                         if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) {
00413                                 log_error("-V option vendor-class-identifier string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1);
00414                                 exit(1);
00415                         }
00416 
00417                         dhcp_vendor_class_identifier_arg = argv[i];
00418                 } else if (!strcmp(argv[i], "-R")) {
00419                         if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) {
00420                                 usage();
00421                                 exit(1);
00422                         }
00423 
00424                         dhclient_request_options = argv[i];
00425                 } else if (!strcmp(argv[i], "-nc")) {
00426 #ifdef HAVE_LIBCAP_NG
00427                         keep_capabilities = 1;
00428 #endif
00429                 } else if (argv[i][0] == '-') {
00430                     usage();
00431                 } else if (interfaces_requested < 0) {
00432                     usage();
00433                 } else {
00434                     struct interface_info *tmp = NULL;
00435 
00436                     status = interface_allocate(&tmp, MDL);
00437                     if (status != ISC_R_SUCCESS)
00438                         log_fatal("Can't record interface %s:%s",
00439                                   argv[i], isc_result_totext(status));
00440                     if (strlen(argv[i]) >= sizeof(tmp->name))
00441                             log_fatal("%s: interface name too long (is %ld)",
00442                                       argv[i], (long)strlen(argv[i]));
00443                     strcpy(tmp->name, argv[i]);
00444                     if (interfaces) {
00445                             interface_reference(&tmp->next,
00446                                                 interfaces, MDL);
00447                             interface_dereference(&interfaces, MDL);
00448                     }
00449                     interface_reference(&interfaces, tmp, MDL);
00450                     tmp->flags = INTERFACE_REQUESTED;
00451                     interfaces_requested++;
00452                 }
00453         }
00454 
00455         if (wanted_ia_na < 0) {
00456                 wanted_ia_na = 1;
00457         }
00458 
00459         /* Support only one (requested) interface for Prefix Delegation. */
00460         if (wanted_ia_pd && (interfaces_requested != 1)) {
00461                 usage();
00462         }
00463 
00464         if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
00465                 path_dhclient_conf = s;
00466         }
00467         if (!no_dhclient_db && (s = getenv("PATH_DHCLIENT_DB"))) {
00468                 path_dhclient_db = s;
00469         }
00470         if (!no_dhclient_pid && (s = getenv("PATH_DHCLIENT_PID"))) {
00471                 path_dhclient_pid = s;
00472         }
00473         if (!no_dhclient_script && (s = getenv("PATH_DHCLIENT_SCRIPT"))) {
00474                 path_dhclient_script = s;
00475         }
00476 
00477 #ifdef HAVE_LIBCAP_NG
00478         /* Drop capabilities */
00479         if (!keep_capabilities) {
00480                 capng_clear(CAPNG_SELECT_CAPS);
00481                 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
00482                                 CAP_DAC_OVERRIDE); // Drop this someday
00483                 capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
00484                                 CAP_NET_ADMIN, CAP_NET_RAW,
00485                                 CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, -1);
00486                 capng_apply(CAPNG_SELECT_CAPS);
00487         }
00488 #endif
00489 
00490         /* Set up the initial dhcp option universe. */
00491         initialize_common_option_spaces();
00492 
00493         /* Assign v4 or v6 specific running parameters. */
00494         if (local_family == AF_INET)
00495                 dhcpv4_client_assignments();
00496 #ifdef DHCPv6
00497         else if (local_family == AF_INET6)
00498                 dhcpv6_client_assignments();
00499 #endif /* DHCPv6 */
00500         else
00501                 log_fatal("Impossible condition at %s:%d.", MDL);
00502 
00503         /*
00504          * convert relative path names to absolute, for files that need
00505          * to be reopened after chdir() has been called
00506          */
00507         if (path_dhclient_db[0] != '/') {
00508                 const char *old_path = path_dhclient_db;
00509                 path_dhclient_db = realpath(path_dhclient_db, NULL);
00510                 if (path_dhclient_db == NULL)
00511                         log_fatal("Failed to get realpath for %s: %s", old_path, strerror(errno));
00512         }
00513 
00514         if (path_dhclient_script[0] != '/') {
00515                 const char *old_path = path_dhclient_script;
00516                 path_dhclient_script = realpath(path_dhclient_script, NULL);
00517                 if (path_dhclient_script == NULL)
00518                         log_fatal("Failed to get realpath for %s: %s", old_path, strerror(errno));
00519         }
00520 
00521         /*
00522          * See if we should  kill off any currently running client
00523          * we don't try to kill it off if the user told us not
00524          * to write a pid file - we assume they are controlling
00525          * the process in some other fashion.
00526          */
00527         if ((release_mode || exit_mode) && (no_pid_file == ISC_FALSE)) {
00528                 FILE *pidfd;
00529                 pid_t oldpid;
00530                 long temp;
00531                 int e;
00532 
00533                 if ((pidfd = fopen(path_dhclient_pid, "re")) != NULL) {
00534                         e = fscanf(pidfd, "%ld\n", &temp);
00535                         oldpid = (pid_t)temp;
00536 
00537                         if (e != 0 && e != EOF) {
00538                                 if (oldpid && (kill(oldpid, SIGTERM) == 0)) {
00539                                         /*
00540                                          * wait for the old process to
00541                                          * cleanly terminate.
00542                                          * Note kill() with sig=0 could
00543                                          * detect termination but only
00544                                          * the parent can be signaled...
00545                                          */
00546                                         sleep(1);
00547                                 }
00548                         }
00549                         fclose(pidfd);
00550                 } else {
00551                         /* handle release for interfaces requested with Red Hat
00552                          * /sbin/ifup - pidfile will be /var/run/dhclient-$interface.pid
00553                          */
00554 
00555                         if ((path_dhclient_pid == NULL) || (*path_dhclient_pid == '\0'))
00556                                 path_dhclient_pid = "/var/run/dhclient.pid";
00557 
00558                         char *new_path_dhclient_pid;
00559                         struct interface_info *ip;
00560                         int pdp_len = strlen(path_dhclient_pid), pfx, dpfx;
00561 
00562                         /* find append point: beginning of any trailing '.pid'
00563                          * or '-$IF.pid' */
00564                         for (pfx=pdp_len; (pfx >= 0) && (path_dhclient_pid[pfx] != '.') && (path_dhclient_pid[pfx] != '/'); pfx--);
00565                                 if (pfx == -1)
00566                                         pfx = pdp_len;
00567 
00568                         if (path_dhclient_pid[pfx] == '/')
00569                                 pfx += 1;
00570 
00571                         for (dpfx=pfx; (dpfx >= 0) && (path_dhclient_pid[dpfx] != '-') && (path_dhclient_pid[dpfx] != '/'); dpfx--);
00572                                 if ((dpfx > -1) && (path_dhclient_pid[dpfx] != '/'))
00573                                         pfx = dpfx;
00574 
00575                         for (ip = interfaces; ip; ip = ip->next) {
00576                                 if (interfaces_requested && (ip->flags & (INTERFACE_REQUESTED))) {
00577                                         int n_len = strlen(ip->name);
00578 
00579                                         new_path_dhclient_pid = (char*) malloc(pfx + n_len + 6);
00580                                         strncpy(new_path_dhclient_pid, path_dhclient_pid, pfx);
00581                                         sprintf(new_path_dhclient_pid + pfx, "-%s.pid", ip->name);
00582 
00583                                         if ((pidfd = fopen(new_path_dhclient_pid, "re")) != NULL) {
00584                                                 e = fscanf(pidfd, "%ld\n", &temp);
00585                                                 oldpid = (pid_t)temp;
00586 
00587                                                 if (e != 0 && e != EOF) {
00588                                                         if (oldpid) {
00589                                                                 if (kill(oldpid, SIGTERM) == 0)
00590                                                                         unlink(path_dhclient_pid);
00591                                                         }
00592                                                 }
00593 
00594                                                 fclose(pidfd);
00595                                         }
00596 
00597                                         free(new_path_dhclient_pid);
00598                                 }
00599                         }
00600                 }
00601         } else {
00602                 FILE *pidfp = NULL;
00603                 long temp = 0;
00604                 pid_t dhcpid = 0;
00605                 int dhc_running = 0;
00606                 char procfn[256] = "";
00607 
00608                 if ((pidfp = fopen(path_dhclient_pid, "re")) != NULL) {
00609                         if ((fscanf(pidfp, "%ld", &temp)==1) && ((dhcpid=(pid_t)temp) > 0)) {
00610                                 snprintf(procfn,256,"/proc/%u",dhcpid);
00611                                 dhc_running = (access(procfn, F_OK) == 0);
00612                         }
00613 
00614                         fclose(pidfp);
00615                 }
00616 
00617                 if (dhc_running) {
00618                         log_fatal("dhclient(%u) is already running - exiting. ", dhcpid);
00619                         return(1);
00620                 }
00621         }
00622 
00623         write_client_pid_file();
00624 
00625         if (!quiet) {
00626                 log_info("%s %s", message, PACKAGE_VERSION);
00627                 log_info(copyright);
00628                 log_info(arr);
00629                 log_info(url);
00630                 log_info("%s", "");
00631         } else {
00632                 log_perror = 0;
00633                 quiet_interface_discovery = 1;
00634         }
00635 
00636         /* If we're given a relay agent address to insert, for testing
00637            purposes, figure out what it is. */
00638         if (mockup_relay) {
00639                 if (!inet_aton(mockup_relay, &giaddr)) {
00640                         struct hostent *he;
00641                         he = gethostbyname(mockup_relay);
00642                         if (he) {
00643                                 memcpy(&giaddr, he->h_addr_list[0],
00644                                        sizeof giaddr);
00645                         } else {
00646                                 log_fatal("%s: no such host", mockup_relay);
00647                         }
00648                 }
00649         }
00650 
00651         /* Get the current time... */
00652         gettimeofday(&cur_tv, NULL);
00653 
00654         sockaddr_broadcast.sin_family = AF_INET;
00655         sockaddr_broadcast.sin_port = remote_port;
00656         if (server) {
00657                 if (!inet_aton(server, &sockaddr_broadcast.sin_addr)) {
00658                         struct hostent *he;
00659                         he = gethostbyname(server);
00660                         if (he) {
00661                                 memcpy(&sockaddr_broadcast.sin_addr,
00662                                        he->h_addr_list[0],
00663                                        sizeof sockaddr_broadcast.sin_addr);
00664                         } else
00665                                 sockaddr_broadcast.sin_addr.s_addr =
00666                                         INADDR_BROADCAST;
00667                 }
00668         } else {
00669                 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
00670         }
00671 
00672         inaddr_any.s_addr = INADDR_ANY;
00673 
00674         /* Stateless special case. */
00675         if (stateless) {
00676                 if (release_mode || (wanted_ia_na > 0) ||
00677                     wanted_ia_ta || wanted_ia_pd ||
00678                     (interfaces_requested != 1)) {
00679                         usage();
00680                 }
00681                 run_stateless(exit_mode);
00682                 return 0;
00683         }
00684 
00685         /* Discover all the network interfaces. */
00686         discover_interfaces(DISCOVER_UNCONFIGURED);
00687 
00688         /* Parse the dhclient.conf file. */
00689         read_client_conf();
00690 
00691         /* Parse any extra command line configuration arguments: */
00692         if ((dhcp_client_identifier_arg != NULL) && (*dhcp_client_identifier_arg != '\0')) {
00693                 arg_conf_len = asprintf(&arg_conf, "send dhcp-client-identifier \"%s\";", dhcp_client_identifier_arg);
00694 
00695                 if ((arg_conf == 0) || (arg_conf_len <= 0))
00696                         log_fatal("Unable to send -C option dhcp-client-identifier");
00697         }
00698 
00699         if ((dhcp_host_name_arg != NULL) && (*dhcp_host_name_arg != '\0')) {
00700                 if (arg_conf == 0) {
00701                         arg_conf_len = asprintf(&arg_conf, "send host-name \"%s\";", dhcp_host_name_arg);
00702 
00703                         if ((arg_conf == 0) || (arg_conf_len <= 0))
00704                                 log_fatal("Unable to send -H option host-name");
00705                 } else {
00706                         char *last_arg_conf = arg_conf;
00707                         arg_conf = NULL;
00708                         arg_conf_len = asprintf(&arg_conf, "%s\nsend host-name \"%s\";", last_arg_conf, dhcp_host_name_arg);
00709 
00710                         if ((arg_conf == 0) || (arg_conf_len <= 0))
00711                                 log_fatal("Unable to send -H option host-name");
00712 
00713                         free(last_arg_conf);
00714                 }
00715         }
00716 
00717         if ((dhcp_fqdn_arg != NULL) && (*dhcp_fqdn_arg != '\0')) {
00718                 if (arg_conf == 0) {
00719                         arg_conf_len = asprintf(&arg_conf,  "send fqdn.fqdn \"%s\";", dhcp_fqdn_arg);
00720 
00721                         if ((arg_conf == 0) || (arg_conf_len <= 0))
00722                                 log_fatal("Unable to send -F option fqdn.fqdn");
00723                 } else {
00724                         char *last_arg_conf = arg_conf;
00725                         arg_conf = NULL;
00726                         arg_conf_len = asprintf(&arg_conf, "%s\nsend fqdn.fqdn \"%s\";", last_arg_conf, dhcp_fqdn_arg);
00727 
00728                         if ((arg_conf == 0)  || (arg_conf_len <= 0))
00729                                 log_fatal("Unable to send -F option fqdn.fqdn");
00730 
00731                         free(last_arg_conf);
00732                 }
00733         }
00734 
00735         if (timeout_arg) {
00736                 if (arg_conf == 0) {
00737                         arg_conf_len = asprintf(&arg_conf,  "timeout %d;", timeout_arg);
00738 
00739                         if ((arg_conf == 0) || (arg_conf_len <= 0))
00740                                 log_fatal("Unable to process -timeout timeout argument");
00741                 } else {
00742                         char *last_arg_conf = arg_conf;
00743                         arg_conf = NULL;
00744                         arg_conf_len = asprintf(&arg_conf, "%s\ntimeout %d;", last_arg_conf, timeout_arg);
00745 
00746                         if ((arg_conf == 0) || (arg_conf_len == 0))
00747                                 log_fatal("Unable to process -timeout timeout argument");
00748 
00749                         free(last_arg_conf);
00750                 }
00751         }
00752 
00753         if ((dhcp_vendor_class_identifier_arg != NULL) && (*dhcp_vendor_class_identifier_arg != '\0')) {
00754                 if (arg_conf == 0) {
00755                         arg_conf_len = asprintf(&arg_conf,  "send vendor-class-identifier \"%s\";", dhcp_vendor_class_identifier_arg);
00756 
00757                         if ((arg_conf == 0) || (arg_conf_len <= 0))
00758                                 log_fatal("Unable to send -V option vendor-class-identifier");
00759                 } else {
00760                         char *last_arg_conf = arg_conf;
00761                         arg_conf = NULL;
00762                         arg_conf_len = asprintf(&arg_conf, "%s\nsend vendor-class-identifier \"%s\";", last_arg_conf, dhcp_vendor_class_identifier_arg);
00763 
00764                         if ((arg_conf == 0) || (arg_conf_len <= 0))
00765                                 log_fatal("Unable to send -V option vendor-class-identifier");
00766 
00767                         free(last_arg_conf);
00768                 }
00769         }
00770 
00771         if (dhclient_request_options != NULL) {
00772                 if (arg_conf == 0) {
00773                         arg_conf_len = asprintf(&arg_conf,  "request %s;", dhclient_request_options);
00774 
00775                         if ((arg_conf == 0) || (arg_conf_len <= 0))
00776                                 log_fatal("Unable to parse -R <request options list> argument");
00777                 } else {
00778                         char *last_arg_conf = arg_conf;
00779                         arg_conf = NULL;
00780                         arg_conf_len = asprintf(&arg_conf, "%s\nrequest %s;", last_arg_conf, dhclient_request_options);
00781 
00782                         if ((arg_conf == 0)  || (arg_conf_len <= 0))
00783                                 log_fatal("Unable to parse -R <request options list> argument");
00784 
00785                         free(last_arg_conf);
00786                 }
00787         }
00788 
00789         if (arg_conf) {
00790                 if (arg_conf_len == 0)
00791                         if ((arg_conf_len = strlen(arg_conf)) == 0)
00792                                 /* huh ? cannot happen ! */
00793                                 log_fatal("Unable to process -C/-H/-F/-timeout/-V/-R configuration arguments");
00794 
00795                 /* parse the extra dhclient.conf configuration arguments
00796                  * into top level config: */
00797                 struct parse *cfile = (struct parse *)0;
00798                 const char *val = NULL;
00799                 int token;
00800 
00801                 status = new_parse(&cfile, -1, arg_conf, arg_conf_len, "extra dhclient -C/-H/-F/-timeout/-V/-R configuration arguments", 0);
00802 
00803                 if ((status != ISC_R_SUCCESS) || (cfile -> warnings_occurred))
00804                         log_fatal("Cannot parse -C/-H/-F/-timeout/-V/-R configuration arguments !");
00805                 /* more detailed parse failures will be logged */
00806 
00807                 do {
00808                         token = peek_token(&val, (unsigned *)0, cfile);
00809                         if (token == END_OF_FILE)
00810                                 break;
00811 
00812                         parse_client_statement(cfile, (struct interface_info *)0, &top_level_config);
00813                 } while (1);
00814 
00815                 if (cfile -> warnings_occurred)
00816                         log_fatal("Cannot parse -C/-H/-F/-timeout/-V/-R configuration arguments !");
00817                 end_parse(&cfile);
00818 
00819                 if (timeout_arg) {
00820                         /* we just set the toplevel timeout, but per-client
00821                          * timeouts may still be at defaults.
00822                          */
00823                         for (ip=interfaces; ip; ip = ip->next) {
00824                                 if (ip->client->config->timeout == 60)
00825                                         ip->client->config->timeout = timeout_arg;
00826                         }
00827                 }
00828 
00829                 if ((dhclient_request_options != 0) && (top_level_config.requested_options != default_requested_options)) {
00830                         for (ip=interfaces; ip; ip = ip->next) {
00831                                 if (ip->client->config->requested_options == default_requested_options)
00832                                         ip->client->config->requested_options = top_level_config.requested_options;
00833                         }
00834                 }
00835 
00836                 free(arg_conf);
00837                 arg_conf = NULL;
00838                 arg_conf_len = 0;
00839         }
00840 
00841         /* Parse the lease database. */
00842         read_client_leases();
00843 
00844         /* Rewrite the lease database... */
00845         rewrite_client_leases();
00846 
00847         /* XXX */
00848 /*      config_counter(&snd_counter, &rcv_counter); */
00849 
00850         /*
00851          * If no broadcast interfaces were discovered, call the script
00852          * and tell it so.
00853          */
00854         if (!interfaces) {
00855                 /*
00856                  * Call dhclient-script with the NBI flag,
00857                  * in case somebody cares.
00858                  */
00859                 script_init(NULL, "NBI", NULL);
00860                 script_go(NULL);
00861 
00862                 /*
00863                  * If we haven't been asked to persist, waiting for new
00864                  * interfaces, then just exit.
00865                  */
00866                 if (!persist) {
00867                         /* Nothing more to do. */
00868                         log_info("No broadcast interfaces found - exiting.");
00869                         exit(0);
00870                 }
00871         } else if (!release_mode && !exit_mode) {
00872                 /* Call the script with the list of interfaces. */
00873                 for (ip = interfaces; ip; ip = ip->next) {
00874                         /*
00875                          * If interfaces were specified, don't configure
00876                          * interfaces that weren't specified!
00877                          */
00878                         if ((interfaces_requested > 0) &&
00879                             ((ip->flags & (INTERFACE_REQUESTED |
00880                                            INTERFACE_AUTOMATIC)) !=
00881                              INTERFACE_REQUESTED))
00882                                 continue;
00883 
00884                         if (local_family == AF_INET6) {
00885                                 script_init(ip->client, "PREINIT6", NULL);
00886                         } else {
00887                                 script_init(ip->client, "PREINIT", NULL);
00888                                 if (ip->client->alias != NULL)
00889                                         script_write_params(ip->client,
00890                                                             "alias_",
00891                                                             ip->client->alias);
00892                         }
00893                         script_go(ip->client);
00894                 }
00895         }
00896 
00897         /* We create a backup seed before rediscovering interfaces in order to
00898            have a seed built using all of the available interfaces
00899            It's interesting if required interfaces doesn't let us defined
00900            a really unique seed due to a lack of valid HW addr later
00901            (this is the case with DHCP over IB)
00902            We only use the last device as using a sum could broke the
00903            uniqueness of the seed among multiple nodes
00904          */
00905         unsigned backup_seed = 0;
00906         for (ip = interfaces; ip; ip = ip -> next) {
00907                 int junk;
00908                 if ( ip -> hw_address.hlen <= sizeof seed )
00909                   continue;
00910                 memcpy (&junk,
00911                         &ip -> hw_address.hbuf [ip -> hw_address.hlen -
00912                                                 sizeof seed], sizeof seed);
00913                 backup_seed = junk;
00914         }
00915 
00916 
00917         /* At this point, all the interfaces that the script thinks
00918            are relevant should be running, so now we once again call
00919            discover_interfaces(), and this time ask it to actually set
00920            up the interfaces. */
00921         discover_interfaces(interfaces_requested != 0
00922                             ? DISCOVER_REQUESTED
00923                             : DISCOVER_RUNNING);
00924 
00925         /* Make up a seed for the random number generator from current
00926            time plus the sum of the last four bytes of each
00927            interface's hardware address interpreted as an integer.
00928            Not much entropy, but we're booting, so we're not likely to
00929            find anything better. */
00930         seed = 0;
00931         int seed_flag = 0;
00932         for (ip = interfaces; ip; ip = ip->next) {
00933                 int junk;
00934                 if ( ip -> hw_address.hlen <= sizeof seed )
00935                   continue;
00936                 memcpy(&junk,
00937                        &ip->hw_address.hbuf[ip->hw_address.hlen -
00938                                             sizeof seed], sizeof seed);
00939                 seed += junk;
00940                 seed_flag = 1;
00941         }
00942         if ( seed_flag == 0 ) {
00943                 if ( backup_seed != 0 ) {
00944                   seed = backup_seed;
00945                   log_info ("xid: rand init seed (0x%x) built using all"
00946                             " available interfaces",seed);
00947                 }
00948                 else {
00949                   seed = cur_time^((unsigned) gethostid()) ;
00950                   log_info ("xid: warning: no netdev with useable HWADDR found"
00951                             " for seed's uniqueness enforcement");
00952                   log_info ("xid: rand init seed (0x%x) built using gethostid",
00953                             seed);
00954                 }
00955                 /* we only use seed and no current time as a broadcast reply */
00956                 /* will certainly be used by the hwaddrless interface */
00957                 srandom(seed);
00958         }
00959         else
00960                 srandom(seed + cur_time + (unsigned)getpid());
00961 
00962         /* Setup specific Infiniband options */
00963         for (ip = interfaces; ip; ip = ip->next) {
00964                 if (ip->client &&
00965                     (ip->hw_address.hbuf[0] == HTYPE_INFINIBAND)) {
00966                         setup_ib_interface(ip);
00967                 }
00968         }
00969 
00970         /*
00971          * Establish a default DUID.  We always do so for v6 and
00972          * do so if desired for v4 via the -D or -i options
00973          */
00974         if ((local_family == AF_INET6) ||
00975             ((local_family == AF_INET) && (duid_v4 == 1))) {
00976                 if (default_duid.len == 0) {
00977                         if (default_duid.buffer != NULL)
00978                                 data_string_forget(&default_duid, MDL);
00979 
00980                         if (form_duid(&default_duid, MDL) == ISC_R_SUCCESS)
00981                                 write_duid(&default_duid);
00982                 }
00983         }
00984 
00985         /* Start a configuration state machine for each interface. */
00986 #ifdef DHCPv6
00987         if (local_family == AF_INET6) {
00988                 for (ip = interfaces ; ip != NULL ; ip = ip->next) {
00989                         for (client = ip->client ; client != NULL ;
00990                              client = client->next) {
00991                                 if (release_mode) {
00992                                         start_release6(client);
00993                                         continue;
00994                                 } else if (exit_mode) {
00995                                         unconfigure6(client, "STOP6");
00996                                         continue;
00997                                 }
00998 
00999                                 /* If we have a previous binding, Confirm
01000                                  * that we can (or can't) still use it.
01001                                  */
01002                                 if ((client->active_lease != NULL) &&
01003                                     !client->active_lease->released)
01004                                         start_confirm6(client);
01005                                 else
01006                                         start_init6(client);
01007                         }
01008                 }
01009         } else
01010 #endif /* DHCPv6 */
01011         {
01012                 for (ip = interfaces ; ip ; ip = ip->next) {
01013                         ip->flags |= INTERFACE_RUNNING;
01014                         for (client = ip->client ; client ;
01015                              client = client->next) {
01016                                 if (exit_mode)
01017                                         state_stop(client);
01018                                 else if (release_mode)
01019                                         do_release(client);
01020                                 else {
01021                                         client->state = S_INIT;
01022 
01023                                         if (top_level_config.initial_delay>0)
01024                                         {
01025                                                 tv.tv_sec = 0;
01026                                                 if (top_level_config.
01027                                                     initial_delay>1)
01028                                                         tv.tv_sec = cur_time
01029                                                         + random()
01030                                                         % (top_level_config.
01031                                                            initial_delay-1);
01032                                                 tv.tv_usec = random()
01033                                                         % 1000000;
01034                                                 /*
01035                                                  * this gives better
01036                                                  * distribution than just
01037                                                  *whole seconds
01038                                                  */
01039                                                 add_timeout(&tv, state_reboot,
01040                                                             client, 0, 0);
01041                                         } else {
01042                                                 state_reboot(client);
01043                                         }
01044                                 }
01045                         }
01046                 }
01047         }
01048 
01049         if (exit_mode)
01050                 return 0;
01051         if (release_mode) {
01052 #ifndef DHCPv6
01053                 return 0;
01054 #else
01055                 if (local_family == AF_INET6) {
01056                         if (onetry)
01057                                 return 0;
01058                 } else
01059                         return 0;
01060 #endif /* DHCPv6 */
01061         }
01062 
01063         /* Start up a listener for the object management API protocol. */
01064         if (top_level_config.omapi_port != -1) {
01065                 listener = NULL;
01066                 result = omapi_generic_new(&listener, MDL);
01067                 if (result != ISC_R_SUCCESS)
01068                         log_fatal("Can't allocate new generic object: %s\n",
01069                                   isc_result_totext(result));
01070                 result = omapi_protocol_listen(listener,
01071                                                (unsigned)
01072                                                top_level_config.omapi_port,
01073                                                1);
01074                 if (result != ISC_R_SUCCESS)
01075                         log_fatal("Can't start OMAPI protocol: %s",
01076                                   isc_result_totext (result));
01077         }
01078 
01079         /* Set up the bootp packet handler... */
01080         bootp_packet_handler = do_packet;
01081 #ifdef DHCPv6
01082         dhcpv6_packet_handler = do_packet6;
01083 #endif /* DHCPv6 */
01084 
01085 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
01086                 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
01087         dmalloc_cutoff_generation = dmalloc_generation;
01088         dmalloc_longterm = dmalloc_outstanding;
01089         dmalloc_outstanding = 0;
01090 #endif
01091 
01092         /* install signal handlers */
01093         signal(SIGINT, dhcp_signal_handler);   /* control-c */
01094         signal(SIGTERM, dhcp_signal_handler);  /* kill */
01095 
01096         /* If we're not supposed to wait before getting the address,
01097            don't. */
01098         if (nowait)
01099                 go_daemon();
01100 
01101         /* If we're not going to daemonize, write the pid file
01102            now. */
01103         if (no_daemon || nowait)
01104                 write_client_pid_file();
01105 
01106         /* Start dispatching packets and timeouts... */
01107         dispatch();
01108 
01109         /* In fact dispatch() never returns. */
01110         return 0;
01111 }
01112 
01113 static void usage()
01114 {
01115         log_info("%s %s", message, PACKAGE_VERSION);
01116         log_info(copyright);
01117         log_info(arr);
01118         log_info(url);
01119 
01120 
01121         log_fatal("Usage: dhclient "
01122 #ifdef DHCPv6
01123                   "[-4|-6] [-SNTPI1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
01124 #else /* DHCPv6 */
01125                   "[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
01126 #endif /* DHCPv6 */
01127                   "                [-s server-addr] [-cf config-file] "
01128                   "[-lf lease-file]\n"
01129                   "                [-pf pid-file] [--no-pid] [-e VAR=val]\n"
01130                   "                [-C <dhcp-client-identifier>] [-B]\n"
01131                   "                [-H <host-name> | -F <fqdn.fqdn>] [-timeout <timeout>]\n"
01132                   "                [-V <vendor-class-identifier>]\n"
01133                   "                [-R <request option list>]\n"
01134                   "                [-sf script-file] [interface]");
01135 }
01136 
01137 void run_stateless(int exit_mode)
01138 {
01139 #ifdef DHCPv6
01140         struct client_state *client;
01141         omapi_object_t *listener;
01142         isc_result_t result;
01143 
01144         /* Discover the network interface. */
01145         discover_interfaces(DISCOVER_REQUESTED);
01146 
01147         if (!interfaces)
01148                 usage();
01149 
01150         /* Parse the dhclient.conf file. */
01151         read_client_conf();
01152 
01153         /* Parse the lease database. */
01154         read_client_leases();
01155 
01156         /* Establish a default DUID. */
01157         if (default_duid.len == 0) {
01158                 if (default_duid.buffer != NULL)
01159                         data_string_forget(&default_duid, MDL);
01160 
01161                 form_duid(&default_duid, MDL);
01162         }
01163 
01164         /* Start a configuration state machine. */
01165         for (client = interfaces->client ;
01166              client != NULL ;
01167              client = client->next) {
01168                 if (exit_mode) {
01169                         unconfigure6(client, "STOP6");
01170                         continue;
01171                 }
01172                 start_info_request6(client);
01173         }
01174         if (exit_mode)
01175                 return;
01176 
01177         /* Start up a listener for the object management API protocol. */
01178         if (top_level_config.omapi_port != -1) {
01179                 listener = NULL;
01180                 result = omapi_generic_new(&listener, MDL);
01181                 if (result != ISC_R_SUCCESS)
01182                         log_fatal("Can't allocate new generic object: %s\n",
01183                                   isc_result_totext(result));
01184                 result = omapi_protocol_listen(listener,
01185                                                (unsigned)
01186                                                top_level_config.omapi_port,
01187                                                1);
01188                 if (result != ISC_R_SUCCESS)
01189                         log_fatal("Can't start OMAPI protocol: %s",
01190                                   isc_result_totext(result));
01191         }
01192 
01193         /* Set up the packet handler... */
01194         dhcpv6_packet_handler = do_packet6;
01195 
01196 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
01197                 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
01198         dmalloc_cutoff_generation = dmalloc_generation;
01199         dmalloc_longterm = dmalloc_outstanding;
01200         dmalloc_outstanding = 0;
01201 #endif
01202 
01203         /* If we're not supposed to wait before getting the address,
01204            don't. */
01205         if (nowait)
01206                 go_daemon();
01207 
01208         /* If we're not going to daemonize, write the pid file
01209            now. */
01210         if (no_daemon || nowait)
01211                 write_client_pid_file();
01212 
01213         /* Start dispatching packets and timeouts... */
01214         dispatch();
01215 
01216 #endif /* DHCPv6 */
01217         return;
01218 }
01219 
01220 isc_result_t find_class (struct class **c,
01221                 const char *s, const char *file, int line)
01222 {
01223         return 0;
01224 }
01225 
01226 int check_collection (packet, lease, collection)
01227         struct packet *packet;
01228         struct lease *lease;
01229         struct collection *collection;
01230 {
01231         return 0;
01232 }
01233 
01234 void classify (packet, class)
01235         struct packet *packet;
01236         struct class *class;
01237 {
01238 }
01239 
01240 int unbill_class (lease, class)
01241         struct lease *lease;
01242         struct class *class;
01243 {
01244         return 0;
01245 }
01246 
01247 int find_subnet (struct subnet **sp,
01248                  struct iaddr addr, const char *file, int line)
01249 {
01250         return 0;
01251 }
01252 
01253 static void setup_ib_interface(struct interface_info *ip)
01254 {
01255         struct group *g;
01256 
01257         /* Set the broadcast flag */
01258         ip->client->config->bootp_broadcast_always = 1;
01259 
01260         /*
01261          * Find out if a dhcp-client-identifier option was specified either
01262          * in the config file or on the command line
01263          */
01264         for (g = ip->client->config->on_transmission; g != NULL; g = g->next) {
01265                 if ((g->statements != NULL) &&
01266                     (strcmp(g->statements->data.option->option->name,
01267                             "dhcp-client-identifier") == 0)) {
01268                         return;
01269                 }
01270         }
01271 
01272         /* No client ID specified */
01273         //log_fatal("dhcp-client-identifier must be specified for InfiniBand");
01274 }
01275 
01276 /* Individual States:
01277  *
01278  * Each routine is called from the dhclient_state_machine() in one of
01279  * these conditions:
01280  * -> entering INIT state
01281  * -> recvpacket_flag == 0: timeout in this state
01282  * -> otherwise: received a packet in this state
01283  *
01284  * Return conditions as handled by dhclient_state_machine():
01285  * Returns 1, sendpacket_flag = 1: send packet, reset timer.
01286  * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
01287  * Returns 0: finish the nap which was interrupted for no good reason.
01288  *
01289  * Several per-interface variables are used to keep track of the process:
01290  *   active_lease: the lease that is being used on the interface
01291  *                 (null pointer if not configured yet).
01292  *   offered_leases: leases corresponding to DHCPOFFER messages that have
01293  *                   been sent to us by DHCP servers.
01294  *   acked_leases: leases corresponding to DHCPACK messages that have been
01295  *                 sent to us by DHCP servers.
01296  *   sendpacket: DHCP packet we're trying to send.
01297  *   destination: IP address to send sendpacket to
01298  * In addition, there are several relevant per-lease variables.
01299  *   T1_expiry, T2_expiry, lease_expiry: lease milestones
01300  * In the active lease, these control the process of renewing the lease;
01301  * In leases on the acked_leases list, this simply determines when we
01302  * can no longer legitimately use the lease.
01303  */
01304 
01305 void state_reboot (cpp)
01306         void *cpp;
01307 {
01308         struct client_state *client = cpp;
01309 
01310         /* If we don't remember an active lease, go straight to INIT. */
01311         if (!client -> active ||
01312             client -> active -> is_bootp ||
01313             client -> active -> expiry <= cur_time) {
01314                 state_init (client);
01315                 return;
01316         }
01317 
01318         /* We are in the rebooting state. */
01319         client -> state = S_REBOOTING;
01320 
01321         /*
01322          * make_request doesn't initialize xid because it normally comes
01323          * from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
01324          * so pick an xid now.
01325          */
01326         client -> xid = random ();
01327 
01328         /*
01329          * Make a DHCPREQUEST packet, and set
01330          * appropriate per-interface flags.
01331          */
01332         make_request (client, client -> active);
01333         client -> destination = iaddr_broadcast;
01334         client -> first_sending = cur_time;
01335         client -> interval = client -> config -> initial_interval;
01336 
01337         /* Zap the medium list... */
01338         client -> medium = NULL;
01339 
01340         /* Send out the first DHCPREQUEST packet. */
01341         send_request (client);
01342 }
01343 
01344 /* Called when a lease has completely expired and we've been unable to
01345    renew it. */
01346 
01347 void state_init (cpp)
01348         void *cpp;
01349 {
01350         struct client_state *client = cpp;
01351         enum dhcp_state init_state = client->state;
01352         struct timeval tv;
01353 
01354         ASSERT_STATE(state, S_INIT);
01355 
01356         /* Make a DHCPDISCOVER packet, and set appropriate per-interface
01357            flags. */
01358         make_discover (client, client -> active);
01359         client -> xid = client -> packet.xid;
01360         client -> destination = iaddr_broadcast;
01361         client -> state = S_SELECTING;
01362         client -> first_sending = cur_time;
01363         client -> interval = client -> config -> initial_interval;
01364 
01365         if (init_state != S_DECLINED) {
01366                 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
01367                    to go out. */
01368                 send_discover(client);
01369         } else {
01370                 /* We've received an OFFER and it has been DECLINEd by dhclient-script.
01371                  * wait for a random time between 1 and backoff_cutoff seconds before
01372                  * trying again. */
01373                 tv . tv_sec = cur_time + ((1 + (random() >> 2)) %  client->config->backoff_cutoff);
01374                 tv . tv_usec = 0;
01375                 add_timeout(&tv, send_discover, client, 0, 0);
01376         }
01377 }
01378 
01379 /*
01380  * state_selecting is called when one or more DHCPOFFER packets have been
01381  * received and a configurable period of time has passed.
01382  */
01383 
01384 void state_selecting (cpp)
01385         void *cpp;
01386 {
01387         struct client_state *client = cpp;
01388         struct client_lease *lp, *next, *picked;
01389 
01390 
01391         ASSERT_STATE(state, S_SELECTING);
01392 
01393         /*
01394          * Cancel state_selecting and send_discover timeouts, since either
01395          * one could have got us here.
01396          */
01397         cancel_timeout (state_selecting, client);
01398         cancel_timeout (send_discover, client);
01399 
01400         /*
01401          * We have received one or more DHCPOFFER packets.   Currently,
01402          * the only criterion by which we judge leases is whether or
01403          * not we get a response when we arp for them.
01404          */
01405         picked = NULL;
01406         for (lp = client -> offered_leases; lp; lp = next) {
01407                 next = lp -> next;
01408 
01409                 /*
01410                  * Check to see if we got an ARPREPLY for the address
01411                  * in this particular lease.
01412                  */
01413                 if (!picked) {
01414                         picked = lp;
01415                         picked -> next = NULL;
01416                 } else {
01417                         destroy_client_lease (lp);
01418                 }
01419         }
01420         client -> offered_leases = NULL;
01421 
01422         /*
01423          * If we just tossed all the leases we were offered, go back
01424          * to square one.
01425          */
01426         if (!picked) {
01427                 client -> state = S_INIT;
01428                 state_init (client);
01429                 return;
01430         }
01431 
01432         /* If it was a BOOTREPLY, we can just take the address right now. */
01433         if (picked -> is_bootp) {
01434                 client -> new = picked;
01435 
01436                 /* Make up some lease expiry times
01437                    XXX these should be configurable. */
01438                 client -> new -> expiry = cur_time + 12000;
01439                 client -> new -> renewal += cur_time + 8000;
01440                 client -> new -> rebind += cur_time + 10000;
01441 
01442                 client -> state = S_REQUESTING;
01443 
01444                 /* Bind to the address we received. */
01445                 bind_lease (client, NULL);
01446                 return;
01447         }
01448 
01449         /* Go to the REQUESTING state. */
01450         client -> destination = iaddr_broadcast;
01451         client -> state = S_REQUESTING;
01452         client -> first_sending = cur_time;
01453         client -> interval = client -> config -> initial_interval;
01454 
01455         /* Make a DHCPREQUEST packet from the lease we picked. */
01456         make_request (client, picked);
01457         client -> xid = client -> packet.xid;
01458 
01459         /* Toss the lease we picked - we'll get it back in a DHCPACK. */
01460         destroy_client_lease (picked);
01461 
01462         /* Add an immediate timeout to send the first DHCPREQUEST packet. */
01463         send_request (client);
01464 }
01465 
01466 /* state_requesting is called when we receive a DHCPACK message after
01467    having sent out one or more DHCPREQUEST packets. */
01468 
01469 void dhcpack (packet)
01470         struct packet *packet;
01471 {
01472         struct interface_info *ip = packet -> interface;
01473         struct client_state *client;
01474         struct client_lease *lease;
01475         struct option_cache *oc;
01476         struct data_string ds;
01477 
01478         /* If we're not receptive to an offer right now, or if the offer
01479            has an unrecognizable transaction id, then just drop it. */
01480         for (client = ip -> client; client; client = client -> next) {
01481                 if (client -> xid == packet -> raw -> xid)
01482                         break;
01483         }
01484         if (!client ||
01485             (packet -> interface -> hw_address.hlen - 1 !=
01486              packet -> raw -> hlen) ||
01487             (memcmp (&packet -> interface -> hw_address.hbuf [1],
01488                      packet -> raw -> chaddr, packet -> raw -> hlen))) {
01489 #if defined (DEBUG)
01490                 log_debug ("DHCPACK in wrong transaction.");
01491 #endif
01492                 return;
01493         }
01494 
01495         if (client -> state != S_REBOOTING &&
01496             client -> state != S_REQUESTING &&
01497             client -> state != S_RENEWING &&
01498             client -> state != S_REBINDING) {
01499 #if defined (DEBUG)
01500                 log_debug ("DHCPACK in wrong state.");
01501 #endif
01502                 return;
01503         }
01504 
01505         log_info ("DHCPACK from %s (xid=0x%x)", piaddr (packet -> client_addr), client -> xid);
01506 
01507         lease = packet_to_lease (packet, client);
01508         if (!lease) {
01509                 log_info ("packet_to_lease failed.");
01510                 return;
01511         }
01512 
01513         client -> new = lease;
01514 
01515         /* Stop resending DHCPREQUEST. */
01516         cancel_timeout (send_request, client);
01517 
01518         /* Figure out the lease time. */
01519         oc = lookup_option (&dhcp_universe, client -> new -> options,
01520                             DHO_DHCP_LEASE_TIME);
01521         memset (&ds, 0, sizeof ds);
01522         if (oc &&
01523             evaluate_option_cache (&ds, packet, (struct lease *)0, client,
01524                                    packet -> options, client -> new -> options,
01525                                    &global_scope, oc, MDL)) {
01526                 if (ds.len > 3)
01527                         client -> new -> expiry = getULong (ds.data);
01528                 else
01529                         client -> new -> expiry = 0;
01530                 data_string_forget (&ds, MDL);
01531         } else
01532                         client -> new -> expiry = 0;
01533 
01534         if (client->new->expiry == 0) {
01535                 struct timeval tv;
01536 
01537                 log_error ("no expiry time on offered lease.");
01538 
01539                 /* Quench this (broken) server.  Return to INIT to reselect. */
01540                 add_reject(packet);
01541 
01542                 /* 1/2 second delay to restart at INIT. */
01543                 tv.tv_sec = cur_tv.tv_sec;
01544                 tv.tv_usec = cur_tv.tv_usec + 500000;
01545 
01546                 if (tv.tv_usec >= 1000000) {
01547                         tv.tv_sec++;
01548                         tv.tv_usec -= 1000000;
01549                 }
01550 
01551                 add_timeout(&tv, state_init, client, 0, 0);
01552                 return;
01553         }
01554 
01555         /*
01556          * A number that looks negative here is really just very large,
01557          * because the lease expiry offset is unsigned.
01558          */
01559         if (client->new->expiry < 0)
01560                 client->new->expiry = TIME_MAX;
01561 
01562         /* Take the server-provided renewal time if there is one. */
01563         oc = lookup_option (&dhcp_universe, client -> new -> options,
01564                             DHO_DHCP_RENEWAL_TIME);
01565         if (oc &&
01566             evaluate_option_cache (&ds, packet, (struct lease *)0, client,
01567                                    packet -> options, client -> new -> options,
01568                                    &global_scope, oc, MDL)) {
01569                 if (ds.len > 3)
01570                         client -> new -> renewal = getULong (ds.data);
01571                 else
01572                         client -> new -> renewal = 0;
01573                 data_string_forget (&ds, MDL);
01574         } else
01575                         client -> new -> renewal = 0;
01576 
01577         /* If it wasn't specified by the server, calculate it. */
01578         if (!client -> new -> renewal)
01579                 client -> new -> renewal = client -> new -> expiry / 2 + 1;
01580 
01581         if (client -> new -> renewal <= 0)
01582                 client -> new -> renewal = TIME_MAX;
01583 
01584         /* Now introduce some randomness to the renewal time: */
01585         if (client->new->renewal <= ((TIME_MAX / 3) - 3))
01586                 client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
01587                                 (((random() % client->new->renewal) + 3) / 4);
01588 
01589         /* Same deal with the rebind time. */
01590         oc = lookup_option (&dhcp_universe, client -> new -> options,
01591                             DHO_DHCP_REBINDING_TIME);
01592         if (oc &&
01593             evaluate_option_cache (&ds, packet, (struct lease *)0, client,
01594                                    packet -> options, client -> new -> options,
01595                                    &global_scope, oc, MDL)) {
01596                 if (ds.len > 3)
01597                         client -> new -> rebind = getULong (ds.data);
01598                 else
01599                         client -> new -> rebind = 0;
01600                 data_string_forget (&ds, MDL);
01601         } else
01602                         client -> new -> rebind = 0;
01603 
01604         if (client -> new -> rebind <= 0) {
01605                 if (client -> new -> expiry <= TIME_MAX / 7)
01606                         client -> new -> rebind =
01607                                         client -> new -> expiry * 7 / 8;
01608                 else
01609                         client -> new -> rebind =
01610                                         client -> new -> expiry / 8 * 7;
01611         }
01612 
01613         /* Make sure our randomness didn't run the renewal time past the
01614            rebind time. */
01615         if (client -> new -> renewal > client -> new -> rebind) {
01616                 if (client -> new -> rebind <= TIME_MAX / 3)
01617                         client -> new -> renewal =
01618                                         client -> new -> rebind * 3 / 4;
01619                 else
01620                         client -> new -> renewal =
01621                                         client -> new -> rebind / 4 * 3;
01622         }
01623 
01624         client -> new -> expiry += cur_time;
01625         /* Lease lengths can never be negative. */
01626         if (client -> new -> expiry < cur_time)
01627                 client -> new -> expiry = TIME_MAX;
01628         client -> new -> renewal += cur_time;
01629         if (client -> new -> renewal < cur_time)
01630                 client -> new -> renewal = TIME_MAX;
01631         client -> new -> rebind += cur_time;
01632         if (client -> new -> rebind < cur_time)
01633                 client -> new -> rebind = TIME_MAX;
01634 
01635         bind_lease (client, &packet -> raw -> siaddr);
01636 }
01637 
01638 void bind_lease (client, siaddr)
01639         struct client_state *client;
01640         struct in_addr *siaddr;
01641 {
01642         struct timeval tv;
01643 
01644         /* Remember the medium. */
01645         client -> new -> medium = client -> medium;
01646 
01647         /* Run the client script with the new parameters. */
01648         script_init (client, (client -> state == S_REQUESTING
01649                           ? "BOUND"
01650                           : (client -> state == S_RENEWING
01651                              ? "RENEW"
01652                              : (client -> state == S_REBOOTING
01653                                 ? "REBOOT" : "REBIND"))),
01654                      client -> new -> medium);
01655         if (client -> active && client -> state != S_REBOOTING)
01656                 script_write_params (client, "old_", client -> active);
01657         script_write_params (client, "new_", client -> new);
01658         script_write_requested(client);
01659         if (client -> alias)
01660                 script_write_params (client, "alias_", client -> alias);
01661 
01662         if (siaddr) {
01663                 char buf[INET_ADDRSTRLEN];
01664 
01665                 if (inet_ntop (AF_INET, (void *) siaddr, buf, sizeof (buf)))
01666                         client_envadd (client, "new_", "next_server", "%s", buf);
01667         }
01668 
01669         /* If the BOUND/RENEW code detects another machine using the
01670            offered address, it exits nonzero.  We need to send a
01671            DHCPDECLINE and toss the lease. */
01672         if (script_go (client)) {
01673                 make_decline (client, client -> new);
01674                 send_decline (client);
01675                 if (onetry) {
01676                         if (!quiet)
01677                           log_info ("Unable to obtain a lease on first try.%s",
01678                                         "  Exiting.");
01679                         exit (2);
01680                 } else {
01681                         destroy_client_lease (client -> new);
01682                         client -> new = (struct client_lease *)0;
01683                         client -> state = S_DECLINED;
01684                         state_init (client);
01685                         return;
01686                 }
01687         }
01688 
01689         /* Write out the new lease if it has been long enough. */
01690         if (!client->last_write ||
01691             (cur_time - client->last_write) >= MIN_LEASE_WRITE)
01692                 write_client_lease(client, client->new, 0, 0);
01693 
01694         /* Replace the old active lease with the new one. */
01695         if (client -> active)
01696                 destroy_client_lease (client -> active);
01697         client -> active = client -> new;
01698         client -> new = (struct client_lease *)0;
01699 
01700         /* Set up a timeout to start the renewal process. */
01701         tv.tv_sec = client->active->renewal;
01702         tv.tv_usec = ((client->active->renewal - cur_tv.tv_sec) > 1) ?
01703                         random() % 1000000 : cur_tv.tv_usec;
01704         add_timeout(&tv, state_bound, client, 0, 0);
01705 
01706         log_info ("bound to %s -- renewal in %ld seconds.",
01707               piaddr (client -> active -> address),
01708               (long)(client -> active -> renewal - cur_time));
01709         client -> state = S_BOUND;
01710         reinitialize_interfaces ();
01711         go_daemon ();
01712 #if defined (NSUPDATE)
01713         if (client->config->do_forward_update)
01714                 dhclient_schedule_updates(client, &client->active->address, 1);
01715 #endif
01716 }
01717 
01718 /* state_bound is called when we've successfully bound to a particular
01719    lease, but the renewal time on that lease has expired.   We are
01720    expected to unicast a DHCPREQUEST to the server that gave us our
01721    original lease. */
01722 
01723 void state_bound (cpp)
01724         void *cpp;
01725 {
01726         struct client_state *client = cpp;
01727         struct option_cache *oc;
01728         struct data_string ds;
01729 
01730         ASSERT_STATE(state, S_BOUND);
01731 
01732         /* T1 has expired. */
01733         make_request (client, client -> active);
01734         client -> xid = client -> packet.xid;
01735 
01736         memset (&ds, 0, sizeof ds);
01737         oc = lookup_option (&dhcp_universe, client -> active -> options,
01738                             DHO_DHCP_SERVER_IDENTIFIER);
01739         if (oc &&
01740             evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
01741                                    client, (struct option_state *)0,
01742                                    client -> active -> options,
01743                                    &global_scope, oc, MDL)) {
01744                 if (ds.len > 3) {
01745                         memcpy (client -> destination.iabuf, ds.data, 4);
01746                         client -> destination.len = 4;
01747                 } else
01748                         client -> destination = iaddr_broadcast;
01749 
01750                 data_string_forget (&ds, MDL);
01751         } else
01752                 client -> destination = iaddr_broadcast;
01753 
01754         client -> first_sending = cur_time;
01755         client -> interval = client -> config -> initial_interval;
01756         client -> state = S_RENEWING;
01757 
01758         /* Send the first packet immediately. */
01759         send_request (client);
01760 }
01761 
01762 /* state_stop is called when we've been told to shut down.   We unconfigure
01763    the interfaces, and then stop operating until told otherwise. */
01764 
01765 void state_stop (cpp)
01766         void *cpp;
01767 {
01768         struct client_state *client = cpp;
01769 
01770         /* Cancel all timeouts. */
01771         cancel_timeout(state_selecting, client);
01772         cancel_timeout(send_discover, client);
01773         cancel_timeout(send_request, client);
01774         cancel_timeout(state_bound, client);
01775 
01776         /* If we have an address, unconfigure it. */
01777         if (client->active) {
01778                 script_init(client, "STOP", client->active->medium);
01779                 script_write_params(client, "old_", client->active);
01780                 script_write_requested(client);
01781                 if (client->alias)
01782                         script_write_params(client, "alias_", client->alias);
01783                 script_go(client);
01784         }
01785 }
01786 
01787 int commit_leases ()
01788 {
01789         return 0;
01790 }
01791 
01792 int write_lease (lease)
01793         struct lease *lease;
01794 {
01795         return 0;
01796 }
01797 
01798 int write_host (host)
01799         struct host_decl *host;
01800 {
01801         return 0;
01802 }
01803 
01804 void bootp (packet)
01805         struct packet *packet;
01806 {
01807         struct iaddrmatchlist *ap;
01808         char addrbuf[4*16];
01809         char maskbuf[4*16];
01810 
01811         if (packet -> raw -> op != BOOTREPLY)
01812                 return;
01813 
01814         /* If there's a reject list, make sure this packet's sender isn't
01815            on it. */
01816         for (ap = packet -> interface -> client -> config -> reject_list;
01817              ap; ap = ap -> next) {
01818                 if (addr_match(&packet->client_addr, &ap->match)) {
01819 
01820                         /* piaddr() returns its result in a static
01821                            buffer sized 4*16 (see common/inet.c). */
01822 
01823                         strcpy(addrbuf, piaddr(ap->match.addr));
01824                         strcpy(maskbuf, piaddr(ap->match.mask));
01825 
01826                         log_info("BOOTREPLY from %s rejected by rule %s "
01827                                  "mask %s.", piaddr(packet->client_addr),
01828                                  addrbuf, maskbuf);
01829                         return;
01830                 }
01831         }
01832 
01833         dhcpoffer (packet);
01834 
01835 }
01836 
01837 void dhcp (packet)
01838         struct packet *packet;
01839 {
01840         struct iaddrmatchlist *ap;
01841         void (*handler) (struct packet *);
01842         const char *type;
01843         char addrbuf[4*16];
01844         char maskbuf[4*16];
01845 
01846         switch (packet -> packet_type) {
01847               case DHCPOFFER:
01848                 handler = dhcpoffer;
01849                 type = "DHCPOFFER";
01850                 break;
01851 
01852               case DHCPNAK:
01853                 handler = dhcpnak;
01854                 type = "DHCPNACK";
01855                 break;
01856 
01857               case DHCPACK:
01858                 handler = dhcpack;
01859                 type = "DHCPACK";
01860                 break;
01861 
01862               default:
01863                 return;
01864         }
01865 
01866         /* If there's a reject list, make sure this packet's sender isn't
01867            on it. */
01868         for (ap = packet -> interface -> client -> config -> reject_list;
01869              ap; ap = ap -> next) {
01870                 if (addr_match(&packet->client_addr, &ap->match)) {
01871 
01872                         /* piaddr() returns its result in a static
01873                            buffer sized 4*16 (see common/inet.c). */
01874 
01875                         strcpy(addrbuf, piaddr(ap->match.addr));
01876                         strcpy(maskbuf, piaddr(ap->match.mask));
01877 
01878                         log_info("%s from %s rejected by rule %s mask %s.",
01879                                  type, piaddr(packet->client_addr),
01880                                  addrbuf, maskbuf);
01881                         return;
01882                 }
01883         }
01884         (*handler) (packet);
01885 }
01886 
01887 #ifdef DHCPv6
01888 void
01889 dhcpv6(struct packet *packet) {
01890         struct iaddrmatchlist *ap;
01891         struct client_state *client;
01892         char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
01893 
01894         /* Silently drop bogus messages. */
01895         if (packet->dhcpv6_msg_type >= dhcpv6_type_name_max)
01896                 return;
01897 
01898         /* Discard, with log, packets from quenched sources. */
01899         for (ap = packet->interface->client->config->reject_list ;
01900              ap ; ap = ap->next) {
01901                 if (addr_match(&packet->client_addr, &ap->match)) {
01902                         strcpy(addrbuf, piaddr(packet->client_addr));
01903                         log_info("%s from %s rejected by rule %s",
01904                                  dhcpv6_type_names[packet->dhcpv6_msg_type],
01905                                  addrbuf,
01906                                  piaddrmask(&ap->match.addr, &ap->match.mask));
01907                         return;
01908                 }
01909         }
01910 
01911         /* Screen out nonsensical messages. */
01912         switch(packet->dhcpv6_msg_type) {
01913               case DHCPV6_ADVERTISE:
01914               case DHCPV6_RECONFIGURE:
01915                 if (stateless)
01916                   return;
01917               /* Falls through */
01918               case DHCPV6_REPLY:
01919                 log_info("RCV: %s message on %s from %s.",
01920                          dhcpv6_type_names[packet->dhcpv6_msg_type],
01921                          packet->interface->name, piaddr(packet->client_addr));
01922                 break;
01923 
01924               default:
01925                 return;
01926         }
01927 
01928         /* Find a client state that matches the incoming XID. */
01929         for (client = packet->interface->client ; client ;
01930              client = client->next) {
01931                 if (memcmp(&client->dhcpv6_transaction_id,
01932                            packet->dhcpv6_transaction_id, 3) == 0) {
01933                         client->v6_handler(packet, client);
01934                         return;
01935                 }
01936         }
01937 
01938         /* XXX: temporary log for debugging */
01939         log_info("Packet received, but nothing done with it.");
01940 }
01941 #endif /* DHCPv6 */
01942 
01943 void dhcpoffer (packet)
01944         struct packet *packet;
01945 {
01946         struct interface_info *ip = packet -> interface;
01947         struct client_state *client;
01948         struct client_lease *lease, *lp;
01949         struct option **req;
01950         int i;
01951         int stop_selecting;
01952         const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY";
01953         char obuf [1024];
01954         struct timeval tv;
01955 
01956 #ifdef DEBUG_PACKET
01957         dump_packet (packet);
01958 #endif
01959 
01960         /* Find a client state that matches the xid... */
01961         for (client = ip -> client; client; client = client -> next)
01962                 if (client -> xid == packet -> raw -> xid)
01963                         break;
01964 
01965         /* If we're not receptive to an offer right now, or if the offer
01966            has an unrecognizable transaction id, then just drop it. */
01967         if (!client ||
01968             client -> state != S_SELECTING ||
01969             (packet -> interface -> hw_address.hlen - 1 !=
01970              packet -> raw -> hlen) ||
01971             (memcmp (&packet -> interface -> hw_address.hbuf [1],
01972                      packet -> raw -> chaddr, packet -> raw -> hlen))) {
01973 #if defined (DEBUG)
01974                 log_debug ("%s in wrong transaction.", name);
01975 #endif
01976                 return;
01977         }
01978 
01979         sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
01980 
01981 
01982         /* If this lease doesn't supply the minimum required DHCPv4 parameters,
01983          * ignore it.
01984          */
01985         req = client->config->required_options;
01986         if (req != NULL) {
01987                 for (i = 0 ; req[i] != NULL ; i++) {
01988                         if ((req[i]->universe == &dhcp_universe) &&
01989                             !lookup_option(&dhcp_universe, packet->options,
01990                                            req[i]->code)) {
01991                                 struct option *option = NULL;
01992                                 unsigned code = req[i]->code;
01993 
01994                                 option_code_hash_lookup(&option,
01995                                                         dhcp_universe.code_hash,
01996                                                         &code, 0, MDL);
01997 
01998                                 if (option)
01999                                         log_info("%s: no %s option.", obuf,
02000                                                  option->name);
02001                                 else
02002                                         log_info("%s: no unknown-%u option.",
02003                                                  obuf, code);
02004 
02005                                 option_dereference(&option, MDL);
02006 
02007                                 return;
02008                         }
02009                 }
02010         }
02011 
02012         /* If we've already seen this lease, don't record it again. */
02013         for (lease = client -> offered_leases; lease; lease = lease -> next) {
02014                 if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
02015                     !memcmp (lease -> address.iabuf,
02016                              &packet -> raw -> yiaddr, lease -> address.len)) {
02017                         log_debug ("%s: already seen.", obuf);
02018                         return;
02019                 }
02020         }
02021 
02022         lease = packet_to_lease (packet, client);
02023         if (!lease) {
02024                 log_info ("%s: packet_to_lease failed.", obuf);
02025                 return;
02026         }
02027 
02028         /* If this lease was acquired through a BOOTREPLY, record that
02029            fact. */
02030         if (!packet -> options_valid || !packet -> packet_type)
02031                 lease -> is_bootp = 1;
02032 
02033         /* Record the medium under which this lease was offered. */
02034         lease -> medium = client -> medium;
02035 
02036         /* Figure out when we're supposed to stop selecting. */
02037         stop_selecting = (client -> first_sending +
02038                           client -> config -> select_interval);
02039 
02040         /* If this is the lease we asked for, put it at the head of the
02041            list, and don't mess with the arp request timeout. */
02042         if (lease -> address.len == client -> requested_address.len &&
02043             !memcmp (lease -> address.iabuf,
02044                      client -> requested_address.iabuf,
02045                      client -> requested_address.len)) {
02046                 lease -> next = client -> offered_leases;
02047                 client -> offered_leases = lease;
02048         } else {
02049                 /* Put the lease at the end of the list. */
02050                 lease -> next = (struct client_lease *)0;
02051                 if (!client -> offered_leases)
02052                         client -> offered_leases = lease;
02053                 else {
02054                         for (lp = client -> offered_leases; lp -> next;
02055                              lp = lp -> next)
02056                                 ;
02057                         lp -> next = lease;
02058                 }
02059         }
02060 
02061         /* If the selecting interval has expired, go immediately to
02062            state_selecting().  Otherwise, time out into
02063            state_selecting at the select interval. */
02064         if (stop_selecting <= cur_tv.tv_sec)
02065                 state_selecting (client);
02066         else {
02067                 tv.tv_sec = stop_selecting;
02068                 tv.tv_usec = cur_tv.tv_usec;
02069                 add_timeout(&tv, state_selecting, client, 0, 0);
02070                 cancel_timeout(send_discover, client);
02071         }
02072         log_info("%s", obuf);
02073 }
02074 
02075 /* Allocate a client_lease structure and initialize it from the parameters
02076    in the specified packet. */
02077 
02078 struct client_lease *packet_to_lease (packet, client)
02079         struct packet *packet;
02080         struct client_state *client;
02081 {
02082         struct client_lease *lease;
02083         unsigned i;
02084         struct option_cache *oc;
02085         struct option *option = NULL;
02086         struct data_string data;
02087 
02088         lease = (struct client_lease *)new_client_lease (MDL);
02089 
02090         if (!lease) {
02091                 log_error ("packet_to_lease: no memory to record lease.\n");
02092                 return (struct client_lease *)0;
02093         }
02094 
02095         memset (lease, 0, sizeof *lease);
02096 
02097         /* Copy the lease options. */
02098         option_state_reference (&lease -> options, packet -> options, MDL);
02099 
02100         lease -> address.len = sizeof (packet -> raw -> yiaddr);
02101         memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
02102                 lease -> address.len);
02103 
02104         memset (&data, 0, sizeof data);
02105 
02106         if (client -> config -> vendor_space_name) {
02107                 i = DHO_VENDOR_ENCAPSULATED_OPTIONS;
02108 
02109                 /* See if there was a vendor encapsulation option. */
02110                 oc = lookup_option (&dhcp_universe, lease -> options, i);
02111                 if (oc &&
02112                     client -> config -> vendor_space_name &&
02113                     evaluate_option_cache (&data, packet,
02114                                            (struct lease *)0, client,
02115                                            packet -> options, lease -> options,
02116                                            &global_scope, oc, MDL)) {
02117                         if (data.len) {
02118                                 if (!option_code_hash_lookup(&option,
02119                                                 dhcp_universe.code_hash,
02120                                                 &i, 0, MDL))
02121                                         log_fatal("Unable to find VENDOR "
02122                                                   "option (%s:%d).", MDL);
02123                                 parse_encapsulated_suboptions
02124                                         (packet -> options, option,
02125                                          data.data, data.len, &dhcp_universe,
02126                                          client -> config -> vendor_space_name
02127                                                 );
02128 
02129                                 option_dereference(&option, MDL);
02130                         }
02131                         data_string_forget (&data, MDL);
02132                 }
02133         } else
02134                 i = 0;
02135 
02136         /* Figure out the overload flag. */
02137         oc = lookup_option (&dhcp_universe, lease -> options,
02138                             DHO_DHCP_OPTION_OVERLOAD);
02139         if (oc &&
02140             evaluate_option_cache (&data, packet, (struct lease *)0, client,
02141                                    packet -> options, lease -> options,
02142                                    &global_scope, oc, MDL)) {
02143                 if (data.len > 0)
02144                         i = data.data [0];
02145                 else
02146                         i = 0;
02147                 data_string_forget (&data, MDL);
02148         } else
02149                 i = 0;
02150 
02151         /* If the server name was filled out, copy it. */
02152         if (!(i & 2) && packet -> raw -> sname [0]) {
02153                 unsigned len;
02154                 /* Don't count on the NUL terminator. */
02155                 for (len = 0; len < DHCP_SNAME_LEN; len++)
02156                         if (!packet -> raw -> sname [len])
02157                                 break;
02158                 lease -> server_name = dmalloc (len + 1, MDL);
02159                 if (!lease -> server_name) {
02160                         log_error ("dhcpoffer: no memory for server name.\n");
02161                         destroy_client_lease (lease);
02162                         return (struct client_lease *)0;
02163                 } else {
02164                         memcpy (lease -> server_name,
02165                                 packet -> raw -> sname, len);
02166                         lease -> server_name [len] = 0;
02167                 }
02168         }
02169 
02170         /* Ditto for the filename. */
02171         if (!(i & 1) && packet -> raw -> file [0]) {
02172                 unsigned len;
02173                 /* Don't count on the NUL terminator. */
02174                 for (len = 0; len < DHCP_FILE_LEN; len++)
02175                         if (!packet -> raw -> file [len])
02176                                 break;
02177                 lease -> filename = dmalloc (len + 1, MDL);
02178                 if (!lease -> filename) {
02179                         log_error ("dhcpoffer: no memory for filename.\n");
02180                         destroy_client_lease (lease);
02181                         return (struct client_lease *)0;
02182                 } else {
02183                         memcpy (lease -> filename,
02184                                 packet -> raw -> file, len);
02185                         lease -> filename [len] = 0;
02186                 }
02187         }
02188 
02189         execute_statements_in_scope(NULL, (struct packet *)packet, NULL,
02190                                     client, lease->options, lease->options,
02191                                     &global_scope, client->config->on_receipt,
02192                                     NULL, NULL);
02193 
02194         return lease;
02195 }
02196 
02197 void dhcpnak (packet)
02198         struct packet *packet;
02199 {
02200         struct interface_info *ip = packet -> interface;
02201         struct client_state *client;
02202 
02203         /* Find a client state that matches the xid... */
02204         for (client = ip -> client; client; client = client -> next)
02205                 if (client -> xid == packet -> raw -> xid)
02206                         break;
02207 
02208         /* If we're not receptive to an offer right now, or if the offer
02209            has an unrecognizable transaction id, then just drop it. */
02210         if (!client ||
02211             (packet -> interface -> hw_address.hlen - 1 !=
02212              packet -> raw -> hlen) ||
02213             (memcmp (&packet -> interface -> hw_address.hbuf [1],
02214                      packet -> raw -> chaddr, packet -> raw -> hlen))) {
02215 #if defined (DEBUG)
02216                 log_debug ("DHCPNAK in wrong transaction.");
02217 #endif
02218                 return;
02219         }
02220 
02221         if (client -> state != S_REBOOTING &&
02222             client -> state != S_REQUESTING &&
02223             client -> state != S_RENEWING &&
02224             client -> state != S_REBINDING) {
02225 #if defined (DEBUG)
02226                 log_debug ("DHCPNAK in wrong state.");
02227 #endif
02228                 return;
02229         }
02230 
02231         log_info ("DHCPNAK from %s (xid=0x%x)", piaddr (packet -> client_addr), client -> xid);
02232 
02233         if (!client -> active) {
02234 #if defined (DEBUG)
02235                 log_info ("DHCPNAK with no active lease.\n");
02236 #endif
02237                 return;
02238         }
02239 
02240         /* If we get a DHCPNAK, we use the EXPIRE dhclient-script state
02241          * to indicate that we want all old bindings to be removed.  (It
02242          * is possible that we may get a NAK while in the RENEW state,
02243          * so we might have bindings active at that time)
02244          */
02245         script_init(client, "EXPIRE", NULL);
02246         script_write_params(client, "old_", client->active);
02247         script_write_requested(client);
02248         if (client->alias)
02249                 script_write_params(client, "alias_", client->alias);
02250         script_go(client);
02251 
02252         destroy_client_lease (client -> active);
02253         client -> active = (struct client_lease *)0;
02254 
02255         /* Stop sending DHCPREQUEST packets... */
02256         cancel_timeout (send_request, client);
02257 
02258         /* On some scripts, 'EXPIRE' causes the interface to be ifconfig'd
02259          * down (this expunges any routes and arp cache).  This makes the
02260          * interface unusable by state_init(), which we call next.  So, we
02261          * need to 'PREINIT' the interface to bring it back up.
02262          */
02263         script_init(client, "PREINIT", NULL);
02264         if (client->alias)
02265                 script_write_params(client, "alias_", client->alias);
02266         script_go(client);
02267 
02268         client -> state = S_INIT;
02269         state_init (client);
02270 }
02271 
02272 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
02273    one after the right interval has expired.  If we don't get an offer by
02274    the time we reach the panic interval, call the panic function. */
02275 
02276 void send_discover (cpp)
02277         void *cpp;
02278 {
02279         struct client_state *client = cpp;
02280 
02281         int result;
02282         int interval;
02283         int increase = 1;
02284         struct timeval tv;
02285 
02286         /* Figure out how long it's been since we started transmitting. */
02287         interval = cur_time - client -> first_sending;
02288 
02289         /* If we're past the panic timeout, call the script and tell it
02290            we haven't found anything for this interface yet. */
02291         if (interval > client -> config -> timeout) {
02292                 state_panic (client);
02293                 return;
02294         }
02295 
02296         /* If we're selecting media, try the whole list before doing
02297            the exponential backoff, but if we've already received an
02298            offer, stop looping, because we obviously have it right. */
02299         if (!client -> offered_leases &&
02300             client -> config -> media) {
02301                 int fail = 0;
02302               again:
02303                 if (client -> medium) {
02304                         client -> medium = client -> medium -> next;
02305                         increase = 0;
02306                 }
02307                 if (!client -> medium) {
02308                         if (fail)
02309                                 log_fatal ("No valid media types for %s!",
02310                                        client -> interface -> name);
02311                         client -> medium =
02312                                 client -> config -> media;
02313                         increase = 1;
02314                 }
02315 
02316                 log_info ("Trying medium \"%s\" %d",
02317                           client -> medium -> string, increase);
02318                 script_init (client, "MEDIUM", client -> medium);
02319                 if (script_go (client)) {
02320                         fail = 1;
02321                         goto again;
02322                 }
02323         }
02324 
02325         /* If we're supposed to increase the interval, do so.  If it's
02326            currently zero (i.e., we haven't sent any packets yet), set
02327            it to initial_interval; otherwise, add to it a random number
02328            between zero and two times itself.  On average, this means
02329            that it will double with every transmission. */
02330         if (increase) {
02331                 if (!client->interval)
02332                         client->interval = client->config->initial_interval;
02333                 else
02334                         client->interval += random() % (2 * client->interval);
02335 
02336                 /* Don't backoff past cutoff. */
02337                 if (client->interval > client->config->backoff_cutoff)
02338                         client->interval = (client->config->backoff_cutoff / 2)
02339                                  + (random() % client->config->backoff_cutoff);
02340         } else if (!client->interval)
02341                 client->interval = client->config->initial_interval;
02342 
02343         /* If the backoff would take us to the panic timeout, just use that
02344            as the interval. */
02345         if (cur_time + client -> interval >
02346             client -> first_sending + client -> config -> timeout)
02347                 client -> interval =
02348                         (client -> first_sending +
02349                          client -> config -> timeout) - cur_time + 1;
02350 
02351         /* Record the number of seconds since we started sending. */
02352         if (interval < 65536)
02353                 client -> packet.secs = htons (interval);
02354         else
02355                 client -> packet.secs = htons (65535);
02356         client -> secs = client -> packet.secs;
02357 
02358         log_info ("DHCPDISCOVER on %s to %s port %d interval %ld (xid=0x%x)",
02359               client -> name ? client -> name : client -> interface -> name,
02360               inet_ntoa (sockaddr_broadcast.sin_addr),
02361               ntohs (sockaddr_broadcast.sin_port), (long)(client -> interval), client -> xid);
02362 
02363         /* Send out a packet. */
02364         result = send_packet(client->interface, NULL, &client->packet,
02365                              client->packet_length, inaddr_any,
02366                              &sockaddr_broadcast, NULL);
02367         if (result < 0) {
02368                 log_error("%s:%d: Failed to send %d byte long packet over %s "
02369                           "interface.", MDL, client->packet_length,
02370                           client->interface->name);
02371         }
02372 
02373         /*
02374          * If we used 0 microseconds here, and there were other clients on the
02375          * same network with a synchronized local clock (ntp), and a similar
02376          * zero-microsecond-scheduler behavior, then we could be participating
02377          * in a sub-second DOS ttck.
02378          */
02379         tv.tv_sec = cur_tv.tv_sec + client->interval;
02380         tv.tv_usec = client->interval > 1 ? random() % 1000000 : cur_tv.tv_usec;
02381         add_timeout(&tv, send_discover, client, 0, 0);
02382 }
02383 
02384 /* state_panic gets called if we haven't received any offers in a preset
02385    amount of time.   When this happens, we try to use existing leases that
02386    haven't yet expired, and failing that, we call the client script and
02387    hope it can do something. */
02388 
02389 void state_panic (cpp)
02390         void *cpp;
02391 {
02392         struct client_state *client = cpp;
02393         struct client_lease *loop;
02394         struct client_lease *lp;
02395         struct timeval tv;
02396 
02397         loop = lp = client -> active;
02398 
02399         log_info ("No DHCPOFFERS received.");
02400 
02401         /* We may not have an active lease, but we may have some
02402            predefined leases that we can try. */
02403         if (!client -> active && client -> leases)
02404                 goto activate_next;
02405 
02406         /* Run through the list of leases and see if one can be used. */
02407         while (client -> active) {
02408                 if (client -> active -> expiry > cur_time) {
02409                         log_info ("Trying recorded lease %s",
02410                               piaddr (client -> active -> address));
02411                         /* Run the client script with the existing
02412                            parameters. */
02413                         script_init (client, "TIMEOUT",
02414                                      client -> active -> medium);
02415                         script_write_params (client, "new_", client -> active);
02416                         script_write_requested(client);
02417                         if (client -> alias)
02418                                 script_write_params (client, "alias_",
02419                                                      client -> alias);
02420 
02421                         /* If the old lease is still good and doesn't
02422                            yet need renewal, go into BOUND state and
02423                            timeout at the renewal time. */
02424                         if (!script_go (client)) {
02425                             if (cur_time < client -> active -> renewal) {
02426                                 client -> state = S_BOUND;
02427                                 log_info ("bound: renewal in %ld %s.",
02428                                           (long)(client -> active -> renewal -
02429                                                  cur_time), "seconds");
02430                                 tv.tv_sec = client->active->renewal;
02431                                 tv.tv_usec = ((client->active->renewal -
02432                                                     cur_time) > 1) ?
02433                                                 random() % 1000000 :
02434                                                 cur_tv.tv_usec;
02435                                 add_timeout(&tv, state_bound, client, 0, 0);
02436                             } else {
02437                                 client -> state = S_BOUND;
02438                                 log_info ("bound: immediate renewal.");
02439                                 state_bound (client);
02440                             }
02441                             reinitialize_interfaces ();
02442                             go_daemon ();
02443                             return;
02444                         }
02445                 }
02446 
02447                 /* If there are no other leases, give up. */
02448                 if (!client -> leases) {
02449                         client -> leases = client -> active;
02450                         client -> active = (struct client_lease *)0;
02451                         break;
02452                 }
02453 
02454         activate_next:
02455                 /* Otherwise, put the active lease at the end of the
02456                    lease list, and try another lease.. */
02457                 for (lp = client -> leases; lp -> next; lp = lp -> next)
02458                         ;
02459                 lp -> next = client -> active;
02460                 if (lp -> next) {
02461                         lp -> next -> next = (struct client_lease *)0;
02462                 }
02463                 client -> active = client -> leases;
02464                 client -> leases = client -> leases -> next;
02465 
02466                 /* If we already tried this lease, we've exhausted the
02467                    set of leases, so we might as well give up for
02468                    now. */
02469                 if (client -> active == loop)
02470                         break;
02471                 else if (!loop)
02472                         loop = client -> active;
02473         }
02474 
02475         /* No leases were available, or what was available didn't work, so
02476            tell the shell script that we failed to allocate an address,
02477            and try again later. */
02478         if (onetry) {
02479                 if (!quiet)
02480                         log_info ("Unable to obtain a lease on first try.%s",
02481                                   "  Exiting.");
02482                 exit (2);
02483         }
02484 
02485         log_info ("No working leases in persistent database - sleeping.");
02486         script_init (client, "FAIL", (struct string_list *)0);
02487         if (client -> alias)
02488                 script_write_params (client, "alias_", client -> alias);
02489         script_go (client);
02490         client -> state = S_INIT;
02491         tv.tv_sec = cur_tv.tv_sec + ((client->config->retry_interval + 1) / 2 +
02492                     (random() % client->config->retry_interval));
02493         tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
02494                         random() % 1000000 : cur_tv.tv_usec;
02495         add_timeout(&tv, state_init, client, 0, 0);
02496         go_daemon ();
02497 }
02498 
02499 void send_request (cpp)
02500         void *cpp;
02501 {
02502         struct client_state *client = cpp;
02503 
02504         int result;
02505         int interval;
02506         struct sockaddr_in destination;
02507         struct in_addr from;
02508         struct timeval tv;
02509 
02510         /* Figure out how long it's been since we started transmitting. */
02511         interval = cur_time - client -> first_sending;
02512 
02513         /* If we're in the INIT-REBOOT or REQUESTING state and we're
02514            past the reboot timeout, go to INIT and see if we can
02515            DISCOVER an address... */
02516         /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
02517            means either that we're on a network with no DHCP server,
02518            or that our server is down.  In the latter case, assuming
02519            that there is a backup DHCP server, DHCPDISCOVER will get
02520            us a new address, but we could also have successfully
02521            reused our old address.  In the former case, we're hosed
02522            anyway.  This is not a win-prone situation. */
02523         if ((client -> state == S_REBOOTING ||
02524              client -> state == S_REQUESTING) &&
02525             interval > client -> config -> reboot_timeout) {
02526         cancel:
02527                 client -> state = S_INIT;
02528                 cancel_timeout (send_request, client);
02529                 state_init (client);
02530                 return;
02531         }
02532 
02533         /* If we're in the reboot state, make sure the media is set up
02534            correctly. */
02535         if (client -> state == S_REBOOTING &&
02536             !client -> medium &&
02537             client -> active -> medium ) {
02538                 script_init (client, "MEDIUM", client -> active -> medium);
02539 
02540                 /* If the medium we chose won't fly, go to INIT state. */
02541                 if (script_go (client))
02542                         goto cancel;
02543 
02544                 /* Record the medium. */
02545                 client -> medium = client -> active -> medium;
02546         }
02547 
02548         /* If the lease has expired, relinquish the address and go back
02549            to the INIT state. */
02550         if (client -> state != S_REQUESTING &&
02551             cur_time > client -> active -> expiry) {
02552                 /* Run the client script with the new parameters. */
02553                 script_init (client, "EXPIRE", (struct string_list *)0);
02554                 script_write_params (client, "old_", client -> active);
02555                 script_write_requested(client);
02556                 if (client -> alias)
02557                         script_write_params (client, "alias_",
02558                                              client -> alias);
02559                 script_go (client);
02560 
02561                 /* Now do a preinit on the interface so that we can
02562                    discover a new address. */
02563                 script_init (client, "PREINIT", (struct string_list *)0);
02564                 if (client -> alias)
02565                         script_write_params (client, "alias_",
02566                                              client -> alias);
02567                 script_go (client);
02568 
02569                 client -> state = S_INIT;
02570                 state_init (client);
02571                 return;
02572         }
02573 
02574         /* Do the exponential backoff... */
02575         if (!client -> interval)
02576                 client -> interval = client -> config -> initial_interval;
02577         else {
02578                 client -> interval += ((random () >> 2) %
02579                                        (2 * client -> interval));
02580         }
02581 
02582         /* Don't backoff past cutoff. */
02583         if (client -> interval >
02584             client -> config -> backoff_cutoff)
02585                 client -> interval =
02586                         ((client -> config -> backoff_cutoff / 2)
02587                          + ((random () >> 2) %
02588                                         client -> config -> backoff_cutoff));
02589 
02590         /* If the backoff would take us to the expiry time, just set the
02591            timeout to the expiry time. */
02592         if (client -> state != S_REQUESTING &&
02593             cur_time + client -> interval > client -> active -> expiry)
02594                 client -> interval =
02595                         client -> active -> expiry - cur_time + 1;
02596 
02597         /* If the lease T2 time has elapsed, or if we're not yet bound,
02598            broadcast the DHCPREQUEST rather than unicasting. */
02599         if (client -> state == S_REQUESTING ||
02600             client -> state == S_REBOOTING ||
02601             cur_time > client -> active -> rebind)
02602                 destination.sin_addr = sockaddr_broadcast.sin_addr;
02603         else
02604                 memcpy (&destination.sin_addr.s_addr,
02605                         client -> destination.iabuf,
02606                         sizeof destination.sin_addr.s_addr);
02607         destination.sin_port = remote_port;
02608         destination.sin_family = AF_INET;
02609 #ifdef HAVE_SA_LEN
02610         destination.sin_len = sizeof destination;
02611 #endif
02612 
02613         if (client -> state == S_RENEWING ||
02614             client -> state == S_REBINDING)
02615                 memcpy (&from, client -> active -> address.iabuf,
02616                         sizeof from);
02617         else
02618                 from.s_addr = INADDR_ANY;
02619 
02620         /* Record the number of seconds since we started sending. */
02621         if (client -> state == S_REQUESTING)
02622                 client -> packet.secs = client -> secs;
02623         else {
02624                 if (interval < 65536)
02625                         client -> packet.secs = htons (interval);
02626                 else
02627                         client -> packet.secs = htons (65535);
02628         }
02629 
02630         log_info ("DHCPREQUEST on %s to %s port %d (xid=0x%x)",
02631               client -> name ? client -> name : client -> interface -> name,
02632               inet_ntoa (destination.sin_addr),
02633               ntohs (destination.sin_port), client -> xid);
02634 
02635         if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
02636             fallback_interface) {
02637                 result = send_packet(fallback_interface, NULL, &client->packet,
02638                                      client->packet_length, from, &destination,
02639                                      NULL);
02640                 if (result < 0) {
02641                         log_error("%s:%d: Failed to send %d byte long packet "
02642                                   "over %s interface.", MDL,
02643                                   client->packet_length,
02644                                   fallback_interface->name);
02645                 }
02646         }
02647         else {
02648                 /* Send out a packet. */
02649                 result = send_packet(client->interface, NULL, &client->packet,
02650                                      client->packet_length, from, &destination,
02651                                      NULL);
02652                 if (result < 0) {
02653                         log_error("%s:%d: Failed to send %d byte long packet"
02654                                   " over %s interface.", MDL,
02655                                   client->packet_length,
02656                                   client->interface->name);
02657                 }
02658         }
02659 
02660         tv.tv_sec = cur_tv.tv_sec + client->interval;
02661         tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
02662                         random() % 1000000 : cur_tv.tv_usec;
02663         add_timeout(&tv, send_request, client, 0, 0);
02664 }
02665 
02666 void send_decline (cpp)
02667         void *cpp;
02668 {
02669         struct client_state *client = cpp;
02670 
02671         int result;
02672 
02673         log_info ("DHCPDECLINE on %s to %s port %d (xid=0x%x)",
02674               client->name ? client->name : client->interface->name,
02675               inet_ntoa(sockaddr_broadcast.sin_addr),
02676               ntohs(sockaddr_broadcast.sin_port), client -> xid);
02677 
02678         /* Send out a packet. */
02679         result = send_packet(client->interface, NULL, &client->packet,
02680                              client->packet_length, inaddr_any,
02681                              &sockaddr_broadcast, NULL);
02682         if (result < 0) {
02683                 log_error("%s:%d: Failed to send %d byte long packet over %s"
02684                           " interface.", MDL, client->packet_length,
02685                           client->interface->name);
02686         }
02687 }
02688 
02689 void send_release (cpp)
02690         void *cpp;
02691 {
02692         struct client_state *client = cpp;
02693 
02694         int result;
02695         struct sockaddr_in destination;
02696         struct in_addr from;
02697 
02698         memcpy (&from, client -> active -> address.iabuf,
02699                 sizeof from);
02700         memcpy (&destination.sin_addr.s_addr,
02701                 client -> destination.iabuf,
02702                 sizeof destination.sin_addr.s_addr);
02703         destination.sin_port = remote_port;
02704         destination.sin_family = AF_INET;
02705 #ifdef HAVE_SA_LEN
02706         destination.sin_len = sizeof destination;
02707 #endif
02708 
02709         /* Set the lease to end now, so that we don't accidentally
02710            reuse it if we restart before the old expiry time. */
02711         client -> active -> expiry =
02712                 client -> active -> renewal =
02713                 client -> active -> rebind = cur_time;
02714         if (!write_client_lease (client, client -> active, 1, 1)) {
02715                 log_error ("Can't release lease: lease write failed.");
02716                 return;
02717         }
02718 
02719         log_info ("DHCPRELEASE on %s to %s port %d (xid=0x%x)",
02720               client -> name ? client -> name : client -> interface -> name,
02721               inet_ntoa (destination.sin_addr),
02722               ntohs (destination.sin_port), client -> xid);
02723 
02724         if (fallback_interface) {
02725                 result = send_packet(fallback_interface, NULL, &client->packet,
02726                                       client->packet_length, from, &destination,
02727                                       NULL);
02728                 if (result < 0) {
02729                         log_error("%s:%d: Failed to send %d byte long packet"
02730                                   " over %s interface.", MDL,
02731                                   client->packet_length,
02732                                   fallback_interface->name);
02733                 }
02734         } else {
02735                 /* Send out a packet. */
02736                 result = send_packet(client->interface, NULL, &client->packet,
02737                                       client->packet_length, from, &destination,
02738                                       NULL);
02739                 if (result < 0) {
02740                         log_error ("%s:%d: Failed to send %d byte long packet"
02741                                    " over %s interface.", MDL,
02742                                    client->packet_length,
02743                                    client->interface->name);
02744                 }
02745 
02746         }
02747 }
02748 
02749 void
02750 make_client_options(struct client_state *client, struct client_lease *lease,
02751                     u_int8_t *type, struct option_cache *sid,
02752                     struct iaddr *rip, struct option **prl,
02753                     struct option_state **op)
02754 {
02755         unsigned i;
02756         struct option_cache *oc;
02757         struct option *option = NULL;
02758         struct buffer *bp = NULL;
02759 
02760         /* If there are any leftover options, get rid of them. */
02761         if (*op)
02762                 option_state_dereference(op, MDL);
02763 
02764         /* Allocate space for options. */
02765         option_state_allocate(op, MDL);
02766 
02767         /* Send the server identifier if provided. */
02768         if (sid)
02769                 save_option(&dhcp_universe, *op, sid);
02770 
02771         oc = NULL;
02772 
02773         /* Send the requested address if provided. */
02774         if (rip) {
02775                 client->requested_address = *rip;
02776                 i = DHO_DHCP_REQUESTED_ADDRESS;
02777                 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
02778                                               &i, 0, MDL) &&
02779                       make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
02780                                               option, MDL)))
02781                         log_error ("can't make requested address cache.");
02782                 else {
02783                         save_option(&dhcp_universe, *op, oc);
02784                         option_cache_dereference(&oc, MDL);
02785                 }
02786                 option_dereference(&option, MDL);
02787         } else {
02788                 client->requested_address.len = 0;
02789         }
02790 
02791         i = DHO_DHCP_MESSAGE_TYPE;
02792         if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
02793                                       MDL) &&
02794               make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
02795                 log_error("can't make message type.");
02796         else {
02797                 save_option(&dhcp_universe, *op, oc);
02798                 option_cache_dereference(&oc, MDL);
02799         }
02800         option_dereference(&option, MDL);
02801 
02802         if (prl) {
02803                 int len;
02804 
02805                 /* Probe the length of the list. */
02806                 len = 0;
02807                 for (i = 0 ; prl[i] != NULL ; i++)
02808                         if (prl[i]->universe == &dhcp_universe)
02809                                 len++;
02810 
02811                 if (!buffer_allocate(&bp, len, MDL))
02812                         log_error("can't make parameter list buffer.");
02813                 else {
02814                         unsigned code = DHO_DHCP_PARAMETER_REQUEST_LIST;
02815 
02816                         len = 0;
02817                         for (i = 0 ; prl[i] != NULL ; i++)
02818                                 if (prl[i]->universe == &dhcp_universe)
02819                                         bp->data[len++] = prl[i]->code;
02820 
02821                         if (!(option_code_hash_lookup(&option,
02822                                                       dhcp_universe.code_hash,
02823                                                       &code, 0, MDL) &&
02824                               make_const_option_cache(&oc, &bp, NULL, len,
02825                                                       option, MDL)))
02826                                 log_error("can't make option cache");
02827                         else {
02828                                 save_option(&dhcp_universe, *op, oc);
02829                                 option_cache_dereference(&oc, MDL);
02830                         }
02831                         option_dereference(&option, MDL);
02832                 }
02833         }
02834 
02835         /*
02836          * If requested (duid_v4 == 1) add an RFC4361 compliant client-identifier
02837          * This can be overridden by including a client id in the configuration
02838          * file.
02839          */
02840         if (duid_v4 == 1) {
02841                 struct data_string client_identifier;
02842                 int hw_idx, hw_len;
02843 
02844                 memset(&client_identifier, 0, sizeof(client_identifier));
02845                 client_identifier.len = 1 + 4 + default_duid.len;
02846                 if (!buffer_allocate(&client_identifier.buffer,
02847                                      client_identifier.len, MDL))
02848                         log_fatal("no memory for default DUID!");
02849                 client_identifier.data = client_identifier.buffer->data;
02850 
02851                 i = DHO_DHCP_CLIENT_IDENTIFIER;
02852 
02853                 /* Client-identifier type : 1 byte */
02854                 *client_identifier.buffer->data = 255;
02855                 
02856                 /* IAID : 4 bytes
02857                  * we use the low 4 bytes from the interface address
02858                  */
02859                 if (client->interface->hw_address.hlen > 4) {
02860                         hw_idx = client->interface->hw_address.hlen - 4;
02861                         hw_len = 4;
02862                 } else {
02863                         hw_idx = 0;
02864                         hw_len = client->interface->hw_address.hlen;
02865                 }
02866                 memcpy(&client_identifier.buffer->data + 5 - hw_len,
02867                        client->interface->hw_address.hbuf + hw_idx,
02868                        hw_len);
02869         
02870                 /* Add the default duid */
02871                 memcpy(&client_identifier.buffer->data+(1+4),
02872                        default_duid.data, default_duid.len);
02873 
02874                 /* And save the option */
02875                 if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
02876                                               &i, 0, MDL) &&
02877                       make_const_option_cache(&oc, NULL,
02878                                               (u_int8_t *)client_identifier.data,
02879                                               client_identifier.len,
02880                                               option, MDL)))
02881                         log_error ("can't make requested client id cache..");
02882                 else {
02883                         save_option (&dhcp_universe, *op, oc);
02884                         option_cache_dereference (&oc, MDL);
02885                 }
02886                 option_dereference(&option, MDL);
02887         }
02888 
02889         /* Run statements that need to be run on transmission. */
02890         if (client->config->on_transmission)
02891                 execute_statements_in_scope(NULL, NULL, NULL, client,
02892                                             (lease ? lease->options : NULL),
02893                                             *op, &global_scope,
02894                                             client->config->on_transmission,
02895                                             NULL, NULL);
02896 }
02897 
02898 void make_discover (client, lease)
02899         struct client_state *client;
02900         struct client_lease *lease;
02901 {
02902         unsigned char discover = DHCPDISCOVER;
02903         struct option_state *options = (struct option_state *)0;
02904 
02905         memset (&client -> packet, 0, sizeof (client -> packet));
02906 
02907         make_client_options (client,
02908                              lease, &discover, (struct option_cache *)0,
02909                              lease ? &lease -> address : (struct iaddr *)0,
02910                              client -> config -> requested_options,
02911                              &options);
02912 
02913         /* Set up the option buffer... */
02914         client -> packet_length =
02915                 cons_options ((struct packet *)0, &client -> packet,
02916                               (struct lease *)0, client,
02917                               /* maximum packet size */1500,
02918                               (struct option_state *)0,
02919                               options,
02920                               /* scope */ &global_scope,
02921                               /* overload */ 0,
02922                               /* terminate */0,
02923                               /* bootpp    */0,
02924                               (struct data_string *)0,
02925                               client -> config -> vendor_space_name);
02926 
02927         option_state_dereference (&options, MDL);
02928         if (client -> packet_length < BOOTP_MIN_LEN)
02929                 client -> packet_length = BOOTP_MIN_LEN;
02930 
02931         client -> packet.op = BOOTREQUEST;
02932         client -> packet.htype = client -> interface -> hw_address.hbuf [0];
02933         client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
02934         client -> packet.hops = 0;
02935         client -> packet.xid = random ();
02936         client -> packet.secs = 0; /* filled in by send_discover. */
02937 
02938         if ((!(bootp_broadcast_always || client->config->bootp_broadcast_always))
02939             && can_receive_unicast_unconfigured(client->interface))
02940                 client -> packet.flags = 0;
02941         else
02942                 client -> packet.flags = htons (BOOTP_BROADCAST);
02943 
02944         memset (&(client -> packet.ciaddr),
02945                 0, sizeof client -> packet.ciaddr);
02946         memset (&(client -> packet.yiaddr),
02947                 0, sizeof client -> packet.yiaddr);
02948         memset (&(client -> packet.siaddr),
02949                 0, sizeof client -> packet.siaddr);
02950         client -> packet.giaddr = giaddr;
02951         if (client -> interface -> hw_address.hlen > 0)
02952             memcpy (client -> packet.chaddr,
02953                     &client -> interface -> hw_address.hbuf [1],
02954                     (unsigned)(client -> interface -> hw_address.hlen - 1));
02955 
02956 #ifdef DEBUG_PACKET
02957         dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
02958 #endif
02959 }
02960 
02961 
02962 void make_request (client, lease)
02963         struct client_state *client;
02964         struct client_lease *lease;
02965 {
02966         unsigned char request = DHCPREQUEST;
02967         struct option_cache *oc;
02968 
02969         memset (&client -> packet, 0, sizeof (client -> packet));
02970 
02971         if (client -> state == S_REQUESTING)
02972                 oc = lookup_option (&dhcp_universe, lease -> options,
02973                                     DHO_DHCP_SERVER_IDENTIFIER);
02974         else
02975                 oc = (struct option_cache *)0;
02976 
02977         if (client -> sent_options)
02978                 option_state_dereference (&client -> sent_options, MDL);
02979 
02980         make_client_options (client, lease, &request, oc,
02981                              ((client -> state == S_REQUESTING ||
02982                                client -> state == S_REBOOTING)
02983                               ? &lease -> address
02984                               : (struct iaddr *)0),
02985                              client -> config -> requested_options,
02986                              &client -> sent_options);
02987 
02988         /* Set up the option buffer... */
02989         client -> packet_length =
02990                 cons_options ((struct packet *)0, &client -> packet,
02991                               (struct lease *)0, client,
02992                               /* maximum packet size */1500,
02993                               (struct option_state *)0,
02994                               client -> sent_options,
02995                               /* scope */ &global_scope,
02996                               /* overload */ 0,
02997                               /* terminate */0,
02998                               /* bootpp    */0,
02999                               (struct data_string *)0,
03000                               client -> config -> vendor_space_name);
03001 
03002         if (client -> packet_length < BOOTP_MIN_LEN)
03003                 client -> packet_length = BOOTP_MIN_LEN;
03004 
03005         client -> packet.op = BOOTREQUEST;
03006         client -> packet.htype = client -> interface -> hw_address.hbuf [0];
03007         client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
03008         client -> packet.hops = 0;
03009         client -> packet.xid = client -> xid;
03010         client -> packet.secs = 0; /* Filled in by send_request. */
03011 
03012         /* If we own the address we're requesting, put it in ciaddr;
03013            otherwise set ciaddr to zero. */
03014         if (client -> state == S_BOUND ||
03015             client -> state == S_RENEWING ||
03016             client -> state == S_REBINDING) {
03017                 memcpy (&client -> packet.ciaddr,
03018                         lease -> address.iabuf, lease -> address.len);
03019                 client -> packet.flags = 0;
03020         } else {
03021                 memset (&client -> packet.ciaddr, 0,
03022                         sizeof client -> packet.ciaddr);
03023                 if ((!(bootp_broadcast_always ||
03024                     client ->config->bootp_broadcast_always)) &&
03025                     can_receive_unicast_unconfigured (client -> interface))
03026                         client -> packet.flags = 0;
03027                 else
03028                         client -> packet.flags = htons (BOOTP_BROADCAST);
03029         }
03030 
03031         memset (&client -> packet.yiaddr, 0,
03032                 sizeof client -> packet.yiaddr);
03033         memset (&client -> packet.siaddr, 0,
03034                 sizeof client -> packet.siaddr);
03035         if (client -> state != S_BOUND &&
03036             client -> state != S_RENEWING)
03037                 client -> packet.giaddr = giaddr;
03038         else
03039                 memset (&client -> packet.giaddr, 0,
03040                         sizeof client -> packet.giaddr);
03041         if (client -> interface -> hw_address.hlen > 0)
03042             memcpy (client -> packet.chaddr,
03043                     &client -> interface -> hw_address.hbuf [1],
03044                     (unsigned)(client -> interface -> hw_address.hlen - 1));
03045 
03046 #ifdef DEBUG_PACKET
03047         dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
03048 #endif
03049 }
03050 
03051 void make_decline (client, lease)
03052         struct client_state *client;
03053         struct client_lease *lease;
03054 {
03055         unsigned char decline = DHCPDECLINE;
03056         struct option_cache *oc;
03057 
03058         struct option_state *options = (struct option_state *)0;
03059 
03060         /* Create the options cache. */
03061         oc = lookup_option (&dhcp_universe, lease -> options,
03062                             DHO_DHCP_SERVER_IDENTIFIER);
03063         make_client_options(client, lease, &decline, oc, &lease->address,
03064                             NULL, &options);
03065 
03066         /* Consume the options cache into the option buffer. */
03067         memset (&client -> packet, 0, sizeof (client -> packet));
03068         client -> packet_length =
03069                 cons_options ((struct packet *)0, &client -> packet,
03070                               (struct lease *)0, client, 0,
03071                               (struct option_state *)0, options,
03072                               &global_scope, 0, 0, 0, (struct data_string *)0,
03073                               client -> config -> vendor_space_name);
03074 
03075         /* Destroy the options cache. */
03076         option_state_dereference (&options, MDL);
03077 
03078         if (client -> packet_length < BOOTP_MIN_LEN)
03079                 client -> packet_length = BOOTP_MIN_LEN;
03080 
03081         client -> packet.op = BOOTREQUEST;
03082         client -> packet.htype = client -> interface -> hw_address.hbuf [0];
03083         client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
03084         client -> packet.hops = 0;
03085         client -> packet.xid = client -> xid;
03086         client -> packet.secs = 0; /* Filled in by send_request. */
03087         if ((!(bootp_broadcast_always || client->config-> bootp_broadcast_always))
03088             && can_receive_unicast_unconfigured (client->interface))
03089                 client -> packet.flags = 0;
03090         else
03091                 client -> packet.flags = htons (BOOTP_BROADCAST);
03092 
03093         /* ciaddr must always be zero. */
03094         memset (&client -> packet.ciaddr, 0,
03095                 sizeof client -> packet.ciaddr);
03096         memset (&client -> packet.yiaddr, 0,
03097                 sizeof client -> packet.yiaddr);
03098         memset (&client -> packet.siaddr, 0,
03099                 sizeof client -> packet.siaddr);
03100         client -> packet.giaddr = giaddr;
03101         memcpy (client -> packet.chaddr,
03102                 &client -> interface -> hw_address.hbuf [1],
03103                 client -> interface -> hw_address.hlen);
03104 
03105 #ifdef DEBUG_PACKET
03106         dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
03107 #endif
03108 }
03109 
03110 void make_release (client, lease)
03111         struct client_state *client;
03112         struct client_lease *lease;
03113 {
03114         unsigned char request = DHCPRELEASE;
03115         struct option_cache *oc;
03116 
03117         struct option_state *options = (struct option_state *)0;
03118 
03119         memset (&client -> packet, 0, sizeof (client -> packet));
03120 
03121         oc = lookup_option (&dhcp_universe, lease -> options,
03122                             DHO_DHCP_SERVER_IDENTIFIER);
03123         make_client_options(client, lease, &request, oc, NULL, NULL, &options);
03124 
03125         /* Set up the option buffer... */
03126         client -> packet_length =
03127                 cons_options ((struct packet *)0, &client -> packet,
03128                               (struct lease *)0, client,
03129                               /* maximum packet size */1500,
03130                               (struct option_state *)0,
03131                               options,
03132                               /* scope */ &global_scope,
03133                               /* overload */ 0,
03134                               /* terminate */0,
03135                               /* bootpp    */0,
03136                               (struct data_string *)0,
03137                               client -> config -> vendor_space_name);
03138 
03139         if (client -> packet_length < BOOTP_MIN_LEN)
03140                 client -> packet_length = BOOTP_MIN_LEN;
03141         option_state_dereference (&options, MDL);
03142 
03143         client -> packet.op = BOOTREQUEST;
03144         client -> packet.htype = client -> interface -> hw_address.hbuf [0];
03145         client -> packet.hlen = client -> interface -> hw_address.hlen - 1;
03146         client -> packet.hops = 0;
03147         client -> packet.xid = random ();
03148         client -> packet.secs = 0;
03149         client -> packet.flags = 0;
03150         memcpy (&client -> packet.ciaddr,
03151                 lease -> address.iabuf, lease -> address.len);
03152         memset (&client -> packet.yiaddr, 0,
03153                 sizeof client -> packet.yiaddr);
03154         memset (&client -> packet.siaddr, 0,
03155                 sizeof client -> packet.siaddr);
03156         client -> packet.giaddr = giaddr;
03157         memcpy (client -> packet.chaddr,
03158                 &client -> interface -> hw_address.hbuf [1],
03159                 client -> interface -> hw_address.hlen);
03160 
03161 #ifdef DEBUG_PACKET
03162         dump_raw ((unsigned char *)&client -> packet, client -> packet_length);
03163 #endif
03164 }
03165 
03166 void destroy_client_lease (lease)
03167         struct client_lease *lease;
03168 {
03169         if (lease -> server_name)
03170                 dfree (lease -> server_name, MDL);
03171         if (lease -> filename)
03172                 dfree (lease -> filename, MDL);
03173         option_state_dereference (&lease -> options, MDL);
03174         free_client_lease (lease, MDL);
03175 }
03176 
03177 FILE *leaseFile = NULL;
03178 int leases_written = 0;
03179 
03180 void rewrite_client_leases ()
03181 {
03182         struct interface_info *ip;
03183         struct client_state *client;
03184         struct client_lease *lp;
03185 
03186         if (leaseFile != NULL)
03187                 fclose (leaseFile);
03188         leaseFile = fopen (path_dhclient_db, "we");
03189         if (leaseFile == NULL) {
03190                 log_error ("can't create %s: %m", path_dhclient_db);
03191                 return;
03192         }
03193 
03194         /* If there is a default duid, write it out. */
03195         if (default_duid.len != 0)
03196                 write_duid(&default_duid);
03197 
03198         /* Write out all the leases attached to configured interfaces that
03199            we know about. */
03200         for (ip = interfaces; ip; ip = ip -> next) {
03201                 for (client = ip -> client; client; client = client -> next) {
03202                         for (lp = client -> leases; lp; lp = lp -> next) {
03203                                 write_client_lease (client, lp, 1, 0);
03204                         }
03205                         if (client -> active)
03206                                 write_client_lease (client,
03207                                                     client -> active, 1, 0);
03208 
03209                         if (client->active_lease != NULL)
03210                                 write_client6_lease(client,
03211                                                     client->active_lease,
03212                                                     1, 0);
03213 
03214                         /* Reset last_write after rewrites. */
03215                         client->last_write = 0;
03216                 }
03217         }
03218 
03219         /* Write out any leases that are attached to interfaces that aren't
03220            currently configured. */
03221         for (ip = dummy_interfaces; ip; ip = ip -> next) {
03222                 for (client = ip -> client; client; client = client -> next) {
03223                         for (lp = client -> leases; lp; lp = lp -> next) {
03224                                 write_client_lease (client, lp, 1, 0);
03225                         }
03226                         if (client -> active)
03227                                 write_client_lease (client,
03228                                                     client -> active, 1, 0);
03229 
03230                         if (client->active_lease != NULL)
03231                                 write_client6_lease(client,
03232                                                     client->active_lease,
03233                                                     1, 0);
03234 
03235                         /* Reset last_write after rewrites. */
03236                         client->last_write = 0;
03237                 }
03238         }
03239         fflush (leaseFile);
03240 }
03241 
03242 void write_lease_option (struct option_cache *oc,
03243                          struct packet *packet, struct lease *lease,
03244                          struct client_state *client_state,
03245                          struct option_state *in_options,
03246                          struct option_state *cfg_options,
03247                          struct binding_scope **scope,
03248                          struct universe *u, void *stuff)
03249 {
03250         const char *name, *dot;
03251         struct data_string ds;
03252         char *preamble = stuff;
03253 
03254         memset (&ds, 0, sizeof ds);
03255 
03256         if (u != &dhcp_universe) {
03257                 name = u -> name;
03258                 dot = ".";
03259         } else {
03260                 name = "";
03261                 dot = "";
03262         }
03263         if (evaluate_option_cache (&ds, packet, lease, client_state,
03264                                    in_options, cfg_options, scope, oc, MDL)) {
03265                 /* The option name */
03266                 fprintf(leaseFile, "%soption %s%s%s", preamble,
03267                         name, dot, oc->option->name);
03268 
03269                 /* The option value if there is one */
03270                 if ((oc->option->format == NULL) ||
03271                     (oc->option->format[0] != 'Z')) {
03272                         fprintf(leaseFile, " %s",
03273                                 pretty_print_option(oc->option, ds.data,
03274                                                     ds.len, 1, 1));
03275                 }
03276 
03277                 /* The closing semi-colon and newline */
03278                 fprintf(leaseFile, ";\n");
03279 
03280                 data_string_forget (&ds, MDL);
03281         }
03282 }
03283 
03284 /* Write an option cache to the lease store. */
03285 static void
03286 write_options(struct client_state *client, struct option_state *options,
03287               const char *preamble)
03288 {
03289         int i;
03290 
03291         for (i = 0; i < options->universe_count; i++) {
03292                 option_space_foreach(NULL, NULL, client, NULL, options,
03293                                      &global_scope, universes[i],
03294                                      (char *)preamble, write_lease_option);
03295         }
03296 }
03297 
03298 /*
03299  * The "best" default DUID, since we cannot predict any information
03300  * about the system (such as whether or not the hardware addresses are
03301  * integrated into the motherboard or similar), is the "LLT", link local
03302  * plus time, DUID. For real stateless "LL" is better.
03303  *
03304  * Once generated, this duid is stored into the state database, and
03305  * retained across restarts.
03306  *
03307  * For the time being, there is probably a different state database for
03308  * every daemon, so this winds up being a per-interface identifier...which
03309  * is not how it is intended.  Upcoming rearchitecting the client should
03310  * address this "one daemon model."
03311  */
03312 isc_result_t
03313 form_duid(struct data_string *duid, const char *file, int line)
03314 {
03315         struct interface_info *ip;
03316         int len;
03317         unsigned hlen;
03318 
03319         /* For now, just use the first interface on the list. */
03320         ip = interfaces;
03321 
03322         if (ip == NULL)
03323                 log_fatal("Impossible condition at %s:%d.", MDL);
03324 
03325         while (ip && ip->hw_address.hbuf[0] == HTYPE_RESERVED) {
03326                 /* Try the other interfaces */
03327                 log_debug("Cannot form default DUID from interface %s.", ip->name);
03328                 ip = ip->next;
03329         }
03330         if (ip == NULL) {
03331                 return ISC_R_UNEXPECTED;
03332         }
03333 
03334         if ((ip->hw_address.hlen == 0) ||
03335             (ip->hw_address.hlen > sizeof(ip->hw_address.hbuf)))
03336                 log_fatal("Impossible hardware address length at %s:%d.", MDL);
03337 
03338         if (duid_type == 0)
03339                 duid_type = stateless ? DUID_LL : DUID_LLT;
03340 
03341         if (ip->hw_address.hbuf[0] == HTYPE_INFINIBAND)
03342                 hlen = 9;
03343         else
03344                 hlen = ip->hw_address.hlen;
03345 
03346         /*
03347          * 2 bytes for the 'duid type' field.
03348          * 2 bytes for the 'htype' field.
03349          * (DUID_LLT) 4 bytes for the 'current time'.
03350          * enough bytes for the hardware address (note that hw_address has
03351          * the 'htype' on byte zero).
03352          */
03353         len = 4 + (hlen - 1);
03354         if (duid_type == DUID_LLT)
03355                 len += 4;
03356         if (!buffer_allocate(&duid->buffer, len, MDL))
03357                 log_fatal("no memory for default DUID!");
03358         duid->data = duid->buffer->data;
03359         duid->len = len;
03360 
03361         /* Basic Link Local Address type of DUID. */
03362         if (duid_type == DUID_LLT) {
03363                 putUShort(duid->buffer->data, DUID_LLT);
03364                 putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
03365                 putULong(duid->buffer->data + 4, cur_time - DUID_TIME_EPOCH);
03366                 memcpy(duid->buffer->data + 8, ip->hw_address.hbuf + 1,
03367                        hlen - 1);
03368         } else {
03369                 putUShort(duid->buffer->data, DUID_LL);
03370                 putUShort(duid->buffer->data + 2, ip->hw_address.hbuf[0]);
03371                 memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
03372                        hlen - 1);
03373         }
03374         
03375         return ISC_R_SUCCESS;
03376 }
03377 
03378 /* Write the default DUID to the lease store. */
03379 static isc_result_t
03380 write_duid(struct data_string *duid)
03381 {
03382         char *str;
03383         int stat;
03384 
03385         if ((duid == NULL) || (duid->len <= 2))
03386                 return DHCP_R_INVALIDARG;
03387 
03388         if (leaseFile == NULL) {        /* XXX? */
03389                 leaseFile = fopen(path_dhclient_db, "we");
03390                 if (leaseFile == NULL) {
03391                         log_error("can't create %s: %m", path_dhclient_db);
03392                         return ISC_R_IOERROR;
03393                 }
03394         }
03395 
03396         /* It would make more sense to write this as a hex string,
03397          * but our function to do that (print_hex_n) uses a fixed
03398          * length buffer...and we can't guarantee a duid would be
03399          * less than the fixed length.
03400          */
03401         str = quotify_buf(duid->data, duid->len, MDL);
03402         if (str == NULL)
03403                 return ISC_R_NOMEMORY;
03404 
03405         stat = fprintf(leaseFile, "default-duid \"%s\";\n", str);
03406         dfree(str, MDL);
03407         if (stat <= 0)
03408                 return ISC_R_IOERROR;
03409 
03410         if (fflush(leaseFile) != 0)
03411                 return ISC_R_IOERROR;
03412 
03413         return ISC_R_SUCCESS;
03414 }
03415 
03416 /* Write a DHCPv6 lease to the store. */
03417 isc_result_t
03418 write_client6_lease(struct client_state *client, struct dhc6_lease *lease,
03419                     int rewrite, int sync)
03420 {
03421         struct dhc6_ia *ia;
03422         struct dhc6_addr *addr;
03423         int stat;
03424         const char *ianame;
03425 
03426         /* This should include the current lease. */
03427         if (!rewrite && (leases_written++ > 20)) {
03428                 rewrite_client_leases();
03429                 leases_written = 0;
03430                 return ISC_R_SUCCESS;
03431         }
03432 
03433         if (client == NULL || lease == NULL)
03434                 return DHCP_R_INVALIDARG;
03435 
03436         if (leaseFile == NULL) {        /* XXX? */
03437                 leaseFile = fopen(path_dhclient_db, "w");
03438                 if (leaseFile == NULL) {
03439                         log_error("can't create %s: %m", path_dhclient_db);
03440                         return ISC_R_IOERROR;
03441                 }
03442         }
03443 
03444         stat = fprintf(leaseFile, "lease6 {\n");
03445         if (stat <= 0)
03446                 return ISC_R_IOERROR;
03447 
03448         stat = fprintf(leaseFile, "  interface \"%s\";\n",
03449                        client->interface->name);
03450         if (stat <= 0)
03451                 return ISC_R_IOERROR;
03452 
03453         for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
03454                 switch (ia->ia_type) {
03455                         case D6O_IA_NA:
03456                         default:
03457                                 ianame = "ia-na";
03458                                 break;
03459                         case D6O_IA_TA:
03460                                 ianame = "ia-ta";
03461                                 break;
03462                         case D6O_IA_PD:
03463                                 ianame = "ia-pd";
03464                                 break;
03465                 }
03466                 stat = fprintf(leaseFile, "  %s %s {\n",
03467                                ianame, print_hex_1(4, ia->iaid, 12));
03468                 if (stat <= 0)
03469                         return ISC_R_IOERROR;
03470 
03471                 if (ia->ia_type != D6O_IA_TA)
03472                         stat = fprintf(leaseFile, "    starts %d;\n"
03473                                                   "    renew %u;\n"
03474                                                   "    rebind %u;\n",
03475                                        (int)ia->starts, ia->renew, ia->rebind);
03476                 else
03477                         stat = fprintf(leaseFile, "    starts %d;\n",
03478                                        (int)ia->starts);
03479                 if (stat <= 0)
03480                         return ISC_R_IOERROR;
03481 
03482                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
03483                         if (ia->ia_type != D6O_IA_PD)
03484                                 stat = fprintf(leaseFile,
03485                                                "    iaaddr %s {\n",
03486                                                piaddr(addr->address));
03487                         else
03488                                 stat = fprintf(leaseFile,
03489                                                "    iaprefix %s/%d {\n",
03490                                                piaddr(addr->address),
03491                                                (int)addr->plen);
03492                         if (stat <= 0)
03493                                 return ISC_R_IOERROR;
03494 
03495                         stat = fprintf(leaseFile, "      starts %d;\n"
03496                                                   "      preferred-life %u;\n"
03497                                                   "      max-life %u;\n",
03498                                        (int)addr->starts, addr->preferred_life,
03499                                        addr->max_life);
03500                         if (stat <= 0)
03501                                 return ISC_R_IOERROR;
03502 
03503                         if (addr->options != NULL)
03504                                 write_options(client, addr->options, "      ");
03505 
03506                         stat = fprintf(leaseFile, "    }\n");
03507                         if (stat <= 0)
03508                                 return ISC_R_IOERROR;
03509                 }
03510 
03511                 if (ia->options != NULL)
03512                         write_options(client, ia->options, "    ");
03513 
03514                 stat = fprintf(leaseFile, "  }\n");
03515                 if (stat <= 0)
03516                         return ISC_R_IOERROR;
03517         }
03518 
03519         if (lease->released) {
03520                 stat = fprintf(leaseFile, "  released;\n");
03521                 if (stat <= 0)
03522                         return ISC_R_IOERROR;
03523         }
03524 
03525         if (lease->options != NULL)
03526                 write_options(client, lease->options, "  ");
03527 
03528         stat = fprintf(leaseFile, "}\n");
03529         if (stat <= 0)
03530                 return ISC_R_IOERROR;
03531 
03532         if (fflush(leaseFile) != 0)
03533                 return ISC_R_IOERROR;
03534 
03535         if (sync) {
03536                 if (fsync(fileno(leaseFile)) < 0) {
03537                         log_error("write_client_lease: fsync(): %m");
03538                         return ISC_R_IOERROR;
03539                 }
03540         }
03541 
03542         return ISC_R_SUCCESS;
03543 }
03544 
03545 int write_client_lease (client, lease, rewrite, makesure)
03546         struct client_state *client;
03547         struct client_lease *lease;
03548         int rewrite;
03549         int makesure;
03550 {
03551         struct data_string ds;
03552         int errors = 0;
03553         char *s;
03554         const char *tval;
03555 
03556         if (!rewrite) {
03557                 if (leases_written++ > 20) {
03558                         rewrite_client_leases ();
03559                         leases_written = 0;
03560                 }
03561         }
03562 
03563         /* If the lease came from the config file, we don't need to stash
03564            a copy in the lease database. */
03565         if (lease -> is_static)
03566                 return 1;
03567 
03568         if (leaseFile == NULL) {        /* XXX */
03569                 leaseFile = fopen (path_dhclient_db, "we");
03570                 if (leaseFile == NULL) {
03571                         log_error ("can't create %s: %m", path_dhclient_db);
03572                         return 0;
03573                 }
03574         }
03575 
03576         errno = 0;
03577         fprintf (leaseFile, "lease {\n");
03578         if (lease -> is_bootp) {
03579                 fprintf (leaseFile, "  bootp;\n");
03580                 if (errno) {
03581                         ++errors;
03582                         errno = 0;
03583                 }
03584         }
03585         fprintf (leaseFile, "  interface \"%s\";\n",
03586                  client -> interface -> name);
03587         if (errno) {
03588                 ++errors;
03589                 errno = 0;
03590         }
03591         if (client -> name) {
03592                 fprintf (leaseFile, "  name \"%s\";\n", client -> name);
03593                 if (errno) {
03594                         ++errors;
03595                         errno = 0;
03596                 }
03597         }
03598         fprintf (leaseFile, "  fixed-address %s;\n",
03599                  piaddr (lease -> address));
03600         if (errno) {
03601                 ++errors;
03602                 errno = 0;
03603         }
03604         if (lease -> filename) {
03605                 s = quotify_string (lease -> filename, MDL);
03606                 if (s) {
03607                         fprintf (leaseFile, "  filename \"%s\";\n", s);
03608                         if (errno) {
03609                                 ++errors;
03610                                 errno = 0;
03611                         }
03612                         dfree (s, MDL);
03613                 } else
03614                         errors++;
03615 
03616         }
03617         if (lease->server_name != NULL) {
03618                 s = quotify_string(lease->server_name, MDL);
03619                 if (s != NULL) {
03620                         fprintf(leaseFile, "  server-name \"%s\";\n", s);
03621                         if (errno) {
03622                                 ++errors;
03623                                 errno = 0;
03624                         }
03625                         dfree(s, MDL);
03626                 } else
03627                         ++errors;
03628         }
03629         if (lease -> medium) {
03630                 s = quotify_string (lease -> medium -> string, MDL);
03631                 if (s) {
03632                         fprintf (leaseFile, "  medium \"%s\";\n", s);
03633                         if (errno) {
03634                                 ++errors;
03635                                 errno = 0;
03636                         }
03637                         dfree (s, MDL);
03638                 } else
03639                         errors++;
03640         }
03641         if (errno != 0) {
03642                 errors++;
03643                 errno = 0;
03644         }
03645 
03646         memset (&ds, 0, sizeof ds);
03647 
03648         write_options(client, lease->options, "  ");
03649 
03650         tval = print_time(lease->renewal);
03651         if (tval == NULL ||
03652             fprintf(leaseFile, "  renew %s\n", tval) < 0)
03653                 errors++;
03654 
03655         tval = print_time(lease->rebind);
03656         if (tval == NULL ||
03657             fprintf(leaseFile, "  rebind %s\n", tval) < 0)
03658                 errors++;
03659 
03660         tval = print_time(lease->expiry);
03661         if (tval == NULL ||
03662             fprintf(leaseFile, "  expire %s\n", tval) < 0)
03663                 errors++;
03664 
03665         if (fprintf(leaseFile, "}\n") < 0)
03666                 errors++;
03667 
03668         if (fflush(leaseFile) != 0)
03669                 errors++;
03670 
03671         client->last_write = cur_time;
03672 
03673         if (!errors && makesure) {
03674                 if (fsync (fileno (leaseFile)) < 0) {
03675                         log_info ("write_client_lease: %m");
03676                         return 0;
03677                 }
03678         }
03679 
03680         return errors ? 0 : 1;
03681 }
03682 
03683 /* Variables holding name of script and file pointer for writing to
03684    script.   Needless to say, this is not reentrant - only one script
03685    can be invoked at a time. */
03686 char scriptName [256];
03687 FILE *scriptFile;
03688 
03689 void script_init (client, reason, medium)
03690         struct client_state *client;
03691         const char *reason;
03692         struct string_list *medium;
03693 {
03694         struct string_list *sl, *next;
03695 
03696         if (client) {
03697                 for (sl = client -> env; sl; sl = next) {
03698                         next = sl -> next;
03699                         dfree (sl, MDL);
03700                 }
03701                 client -> env = (struct string_list *)0;
03702                 client -> envc = 0;
03703 
03704                 if (client -> interface) {
03705                         client_envadd (client, "", "interface", "%s",
03706                                        client -> interface -> name);
03707                 }
03708                 if (client -> name)
03709                         client_envadd (client,
03710                                        "", "client", "%s", client -> name);
03711                 if (medium)
03712                         client_envadd (client,
03713                                        "", "medium", "%s", medium -> string);
03714 
03715                 client_envadd (client, "", "reason", "%s", reason);
03716                 client_envadd (client, "", "pid", "%ld", (long int)getpid ());
03717         }
03718 }
03719 
03720 void client_option_envadd (struct option_cache *oc,
03721                            struct packet *packet, struct lease *lease,
03722                            struct client_state *client_state,
03723                            struct option_state *in_options,
03724                            struct option_state *cfg_options,
03725                            struct binding_scope **scope,
03726                            struct universe *u, void *stuff)
03727 {
03728         struct envadd_state *es = stuff;
03729         struct data_string data;
03730         memset (&data, 0, sizeof data);
03731 
03732         if (evaluate_option_cache (&data, packet, lease, client_state,
03733                                    in_options, cfg_options, scope, oc, MDL)) {
03734                 if (data.len) {
03735                         char name [256];
03736                         if (dhcp_option_ev_name (name, sizeof name,
03737                                                  oc->option)) {
03738                                 const char *value;
03739                                 size_t length;
03740                                 value = pretty_print_option(oc->option,
03741                                                             data.data,
03742                                                             data.len, 0, 0);
03743                                 length = strlen(value);
03744 
03745                                 if (check_option_values(oc->option->universe,
03746                                                         oc->option->code,
03747                                                         value, length) == 0) {
03748                                         client_envadd(es->client, es->prefix,
03749                                                       name, "%s", value);
03750                                 } else {
03751                                         log_error("suspect value in %s "
03752                                                   "option - discarded",
03753                                                   name);
03754                                 }
03755                                 data_string_forget (&data, MDL);
03756                         }
03757                 }
03758         }
03759 }
03760 
03761 void script_write_params (client, prefix, lease)
03762         struct client_state *client;
03763         const char *prefix;
03764         struct client_lease *lease;
03765 {
03766         int i;
03767         struct data_string data;
03768         struct option_cache *oc;
03769         struct envadd_state es;
03770 
03771         es.client = client;
03772         es.prefix = prefix;
03773 
03774         client_envadd (client,
03775                        prefix, "ip_address", "%s", piaddr (lease -> address));
03776 
03777         /* For the benefit of Linux (and operating systems which may
03778            have similar needs), compute the network address based on
03779            the supplied ip address and netmask, if provided.  Also
03780            compute the broadcast address (the host address all ones
03781            broadcast address, not the host address all zeroes
03782            broadcast address). */
03783 
03784         memset (&data, 0, sizeof data);
03785         oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
03786         if (oc && evaluate_option_cache (&data, (struct packet *)0,
03787                                          (struct lease *)0, client,
03788                                          (struct option_state *)0,
03789                                          lease -> options,
03790                                          &global_scope, oc, MDL)) {
03791                 if (data.len > 3) {
03792                         struct iaddr netmask, subnet, broadcast;
03793 
03794                         /*
03795                          * No matter the length of the subnet-mask option,
03796                          * use only the first four octets.  Note that
03797                          * subnet-mask options longer than 4 octets are not
03798                          * in conformance with RFC 2132, but servers with this
03799                          * flaw do exist.
03800                          */
03801                         memcpy(netmask.iabuf, data.data, 4);
03802                         netmask.len = 4;
03803                         data_string_forget (&data, MDL);
03804 
03805                         subnet = subnet_number (lease -> address, netmask);
03806                         if (subnet.len) {
03807                             client_envadd (client, prefix, "network_number",
03808                                            "%s", piaddr (subnet));
03809 
03810                             oc = lookup_option (&dhcp_universe,
03811                                                 lease -> options,
03812                                                 DHO_BROADCAST_ADDRESS);
03813                             if (!oc ||
03814                                 !(evaluate_option_cache
03815                                   (&data, (struct packet *)0,
03816                                    (struct lease *)0, client,
03817                                    (struct option_state *)0,
03818                                    lease -> options,
03819                                    &global_scope, oc, MDL))) {
03820                                 broadcast = broadcast_addr (subnet, netmask);
03821                                 if (broadcast.len) {
03822                                     client_envadd (client,
03823                                                    prefix, "broadcast_address",
03824                                                    "%s", piaddr (broadcast));
03825                                 }
03826                             }
03827                         }
03828                 }
03829                 data_string_forget (&data, MDL);
03830         }
03831 
03832         if (lease->filename) {
03833                 if (check_option_values(NULL, DHO_ROOT_PATH,
03834                                         lease->filename,
03835                                         strlen(lease->filename)) == 0) {
03836                         client_envadd(client, prefix, "filename",
03837                                       "%s", lease->filename);
03838                 } else {
03839                         log_error("suspect value in %s "
03840                                   "option - discarded",
03841                                   lease->filename);
03842                 }
03843         }
03844 
03845         if (lease->server_name) {
03846                 if (check_option_values(NULL, DHO_HOST_NAME,
03847                                         lease->server_name,
03848                                         strlen(lease->server_name)) == 0 ) {
03849                         client_envadd (client, prefix, "server_name",
03850                                        "%s", lease->server_name);
03851                 } else {
03852                         log_error("suspect value in %s "
03853                                   "option - discarded",
03854                                   lease->server_name);
03855                 }
03856         }
03857 
03858         for (i = 0; i < lease -> options -> universe_count; i++) {
03859                 option_space_foreach ((struct packet *)0, (struct lease *)0,
03860                                       client, (struct option_state *)0,
03861                                       lease -> options, &global_scope,
03862                                       universes [i],
03863                                       &es, client_option_envadd);
03864         }
03865         client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry));
03866 }
03867 
03868 /*
03869  * Write out the environment variables for the objects that the
03870  * client requested.  If the object was requested the variable will be:
03871  * requested_<option_name>=1
03872  * If it wasn't requested there won't be a variable.
03873  */
03874 void script_write_requested(client)
03875         struct client_state *client;
03876 {
03877         int i;
03878         struct option **req;
03879         char name[256];
03880         req = client->config->requested_options;
03881 
03882         if (req == NULL)
03883                 return;
03884 
03885         for (i = 0 ; req[i] != NULL ; i++) {
03886                 if ((req[i]->universe == &dhcp_universe) &&
03887                     dhcp_option_ev_name(name, sizeof(name), req[i])) {
03888                         client_envadd(client, "requested_", name, "%d", 1);
03889                 }
03890         }
03891 }
03892 
03893 int script_go (client)
03894         struct client_state *client;
03895 {
03896         char *scriptName;
03897         char *argv [2];
03898         char **envp;
03899         char reason [] = "REASON=NBI";
03900         static char client_path [] = CLIENT_PATH;
03901         int i;
03902         struct string_list *sp, *next;
03903         int pid, wpid, wstatus;
03904 
03905         if (client)
03906                 scriptName = client -> config -> script_name;
03907         else
03908                 scriptName = top_level_config.script_name;
03909 
03910         envp = dmalloc (((client ? client -> envc : 2) +
03911                          client_env_count + 2) * sizeof (char *), MDL);
03912         if (!envp) {
03913                 log_error ("No memory for client script environment.");
03914                 return 0;
03915         }
03916         i = 0;
03917         /* Copy out the environment specified on the command line,
03918            if any. */
03919         for (sp = client_env; sp; sp = sp -> next) {
03920                 envp [i++] = sp -> string;
03921         }
03922         /* Copy out the environment specified by dhclient. */
03923         if (client) {
03924                 for (sp = client -> env; sp; sp = sp -> next) {
03925                         envp [i++] = sp -> string;
03926                 }
03927         } else {
03928                 envp [i++] = reason;
03929         }
03930         /* Set $PATH. */
03931         envp [i++] = client_path;
03932         envp [i] = (char *)0;
03933 
03934         argv [0] = scriptName;
03935         argv [1] = (char *)0;
03936 
03937         pid = fork ();
03938         if (pid < 0) {
03939                 log_error ("fork: %m");
03940                 wstatus = 0;
03941         } else if (pid) {
03942                 do {
03943                         wpid = wait (&wstatus);
03944                 } while (wpid != pid && wpid > 0);
03945                 if (wpid < 0) {
03946                         log_error ("wait: %m");
03947                         wstatus = 0;
03948                 }
03949         } else {
03950                 /* We don't want to pass an open file descriptor for
03951                  * dhclient.leases when executing dhclient-script.
03952                  */
03953                 if (leaseFile != NULL)
03954                         fclose(leaseFile);
03955                 execve (scriptName, argv, envp);
03956                 log_error ("execve (%s, ...): %m", scriptName);
03957                 exit (0);
03958         }
03959 
03960         if (client) {
03961                 for (sp = client -> env; sp; sp = next) {
03962                         next = sp -> next;
03963                         dfree (sp, MDL);
03964                 }
03965                 client -> env = (struct string_list *)0;
03966                 client -> envc = 0;
03967         }
03968         dfree (envp, MDL);
03969         gettimeofday(&cur_tv, NULL);
03970         return (WIFEXITED (wstatus) ?
03971                 WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
03972 }
03973 
03974 void client_envadd (struct client_state *client,
03975                     const char *prefix, const char *name, const char *fmt, ...)
03976 {
03977         char spbuf [1024];
03978         char *s;
03979         unsigned len;
03980         struct string_list *val;
03981         va_list list;
03982 
03983         va_start (list, fmt);
03984         len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
03985         va_end (list);
03986 
03987         val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
03988                        len + sizeof *val, MDL);
03989         if (!val)
03990                 return;
03991         s = val -> string;
03992         strcpy (s, prefix);
03993         strcat (s, name);
03994         s += strlen (s);
03995         *s++ = '=';
03996         if (len >= sizeof spbuf) {
03997                 va_start (list, fmt);
03998                 vsnprintf (s, len + 1, fmt, list);
03999                 va_end (list);
04000         } else
04001                 strcpy (s, spbuf);
04002         val -> next = client -> env;
04003         client -> env = val;
04004         client -> envc++;
04005 }
04006 
04007 int dhcp_option_ev_name (buf, buflen, option)
04008         char *buf;
04009         size_t buflen;
04010         struct option *option;
04011 {
04012         int i, j;
04013         const char *s;
04014 
04015         j = 0;
04016         if (option -> universe != &dhcp_universe) {
04017                 s = option -> universe -> name;
04018                 i = 0;
04019         } else {
04020                 s = option -> name;
04021                 i = 1;
04022         }
04023 
04024         do {
04025                 while (*s) {
04026                         if (j + 1 == buflen)
04027                                 return 0;
04028                         if (*s == '-')
04029                                 buf [j++] = '_';
04030                         else
04031                                 buf [j++] = *s;
04032                         ++s;
04033                 }
04034                 if (!i) {
04035                         s = option -> name;
04036                         if (j + 1 == buflen)
04037                                 return 0;
04038                         buf [j++] = '_';
04039                 }
04040                 ++i;
04041         } while (i != 2);
04042 
04043         buf [j] = 0;
04044         return 1;
04045 }
04046 
04047 void go_daemon ()
04048 {
04049         static int state = 0;
04050         int pid;
04051 
04052         /* Don't become a daemon if the user requested otherwise. */
04053         if (no_daemon) {
04054                 write_client_pid_file ();
04055                 return;
04056         }
04057 
04058         /* Only do it once. */
04059         if (state)
04060                 return;
04061         state = 1;
04062 
04063         /* Stop logging to stderr... */
04064         log_perror = 0;
04065 
04066         /* Become a daemon... */
04067         if ((pid = fork ()) < 0)
04068                 log_fatal ("Can't fork daemon: %m");
04069         else if (pid)
04070                 exit (0);
04071         /* Become session leader and get pid... */
04072         (void) setsid ();
04073 
04074         /* Close standard I/O descriptors. */
04075         (void) close(0);
04076         (void) close(1);
04077         (void) close(2);
04078 
04079         /* Reopen them on /dev/null. */
04080         (void) open("/dev/null", O_RDWR | O_CLOEXEC);
04081         (void) open("/dev/null", O_RDWR | O_CLOEXEC);
04082         (void) open("/dev/null", O_RDWR | O_CLOEXEC);
04083 
04084         write_client_pid_file ();
04085 
04086         IGNORE_RET (chdir("/"));
04087 }
04088 
04089 void write_client_pid_file ()
04090 {
04091         FILE *pf;
04092         int pfdesc;
04093 
04094         /* nothing to do if the user doesn't want a pid file */
04095         if (no_pid_file == ISC_TRUE) {
04096                 return;
04097         }
04098 
04099         pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
04100 
04101         if (pfdesc < 0) {
04102                 log_error ("Can't create %s: %m", path_dhclient_pid);
04103                 return;
04104         }
04105 
04106         pf = fdopen (pfdesc, "we");
04107         if (!pf) {
04108                 close(pfdesc);
04109                 log_error ("Can't fdopen %s: %m", path_dhclient_pid);
04110         } else {
04111                 fprintf (pf, "%ld\n", (long)getpid ());
04112                 fclose (pf);
04113         }
04114 }
04115 
04116 void client_location_changed ()
04117 {
04118         struct interface_info *ip;
04119         struct client_state *client;
04120 
04121         for (ip = interfaces; ip; ip = ip -> next) {
04122                 for (client = ip -> client; client; client = client -> next) {
04123                         switch (client -> state) {
04124                               case S_SELECTING:
04125                                 cancel_timeout (send_discover, client);
04126                                 break;
04127 
04128                               case S_BOUND:
04129                                 cancel_timeout (state_bound, client);
04130                                 break;
04131 
04132                               case S_REBOOTING:
04133                               case S_REQUESTING:
04134                               case S_RENEWING:
04135                                 cancel_timeout (send_request, client);
04136                                 break;
04137 
04138                               case S_INIT:
04139                               case S_REBINDING:
04140                               case S_STOPPED:
04141                               case S_DECLINED:
04142                                 break;
04143                         }
04144                         client -> state = S_INIT;
04145                         state_reboot (client);
04146                 }
04147         }
04148 }
04149 
04150 void do_release(client)
04151         struct client_state *client;
04152 {
04153         struct data_string ds;
04154         struct option_cache *oc;
04155 
04156         /* Pick a random xid. */
04157         client -> xid = random ();
04158 
04159         /* is there even a lease to release? */
04160         if (client -> active) {
04161                 /* Make a DHCPRELEASE packet, and set appropriate per-interface
04162                    flags. */
04163                 make_release (client, client -> active);
04164 
04165                 memset (&ds, 0, sizeof ds);
04166                 oc = lookup_option (&dhcp_universe,
04167                                     client -> active -> options,
04168                                     DHO_DHCP_SERVER_IDENTIFIER);
04169                 if (oc &&
04170                     evaluate_option_cache (&ds, (struct packet *)0,
04171                                            (struct lease *)0, client,
04172                                            (struct option_state *)0,
04173                                            client -> active -> options,
04174                                            &global_scope, oc, MDL)) {
04175                         if (ds.len > 3) {
04176                                 memcpy (client -> destination.iabuf,
04177                                         ds.data, 4);
04178                                 client -> destination.len = 4;
04179                         } else
04180                                 client -> destination = iaddr_broadcast;
04181 
04182                         data_string_forget (&ds, MDL);
04183                 } else
04184                         client -> destination = iaddr_broadcast;
04185                 client -> first_sending = cur_time;
04186                 client -> interval = client -> config -> initial_interval;
04187 
04188                 /* Zap the medium list... */
04189                 client -> medium = (struct string_list *)0;
04190 
04191                 /* Send out the first and only DHCPRELEASE packet. */
04192                 send_release (client);
04193 
04194                 /* Do the client script RELEASE operation. */
04195                 script_init (client,
04196                              "RELEASE", (struct string_list *)0);
04197                 if (client -> alias)
04198                         script_write_params (client, "alias_",
04199                                              client -> alias);
04200                 script_write_params (client, "old_", client -> active);
04201                 script_write_requested(client);
04202                 script_go (client);
04203         }
04204 
04205         /* Cancel any timeouts. */
04206         cancel_timeout (state_bound, client);
04207         cancel_timeout (send_discover, client);
04208         cancel_timeout (state_init, client);
04209         cancel_timeout (send_request, client);
04210         cancel_timeout (state_reboot, client);
04211         client -> state = S_STOPPED;
04212 }
04213 
04214 int dhclient_interface_shutdown_hook (struct interface_info *interface)
04215 {
04216         do_release (interface -> client);
04217 
04218         return 1;
04219 }
04220 
04221 int dhclient_interface_discovery_hook (struct interface_info *tmp)
04222 {
04223         struct interface_info *last, *ip;
04224         /* See if we can find the client from dummy_interfaces */
04225         last = 0;
04226         for (ip = dummy_interfaces; ip; ip = ip -> next) {
04227                 if (!strcmp (ip -> name, tmp -> name)) {
04228                         /* Remove from dummy_interfaces */
04229                         if (last) {
04230                                 ip = (struct interface_info *)0;
04231                                 interface_reference (&ip, last -> next, MDL);
04232                                 interface_dereference (&last -> next, MDL);
04233                                 if (ip -> next) {
04234                                         interface_reference (&last -> next,
04235                                                              ip -> next, MDL);
04236                                         interface_dereference (&ip -> next,
04237                                                                MDL);
04238                                 }
04239                         } else {
04240                                 ip = (struct interface_info *)0;
04241                                 interface_reference (&ip,
04242                                                      dummy_interfaces, MDL);
04243                                 interface_dereference (&dummy_interfaces, MDL);
04244                                 if (ip -> next) {
04245                                         interface_reference (&dummy_interfaces,
04246                                                              ip -> next, MDL);
04247                                         interface_dereference (&ip -> next,
04248                                                                MDL);
04249                                 }
04250                         }
04251                         /* Copy "client" to tmp */
04252                         if (ip -> client) {
04253                                 tmp -> client = ip -> client;
04254                                 tmp -> client -> interface = tmp;
04255                         }
04256                         interface_dereference (&ip, MDL);
04257                         break;
04258                 }
04259                 last = ip;
04260         }
04261         return 1;
04262 }
04263 
04264 isc_result_t dhclient_interface_startup_hook (struct interface_info *interface)
04265 {
04266         struct interface_info *ip;
04267         struct client_state *client;
04268 
04269         /* This code needs some rethinking.   It doesn't test against
04270            a signal name, and it just kind of bulls into doing something
04271            that may or may not be appropriate. */
04272 
04273         if (interfaces) {
04274                 interface_reference (&interface -> next, interfaces, MDL);
04275                 interface_dereference (&interfaces, MDL);
04276         }
04277         interface_reference (&interfaces, interface, MDL);
04278 
04279         discover_interfaces (DISCOVER_UNCONFIGURED);
04280 
04281         for (ip = interfaces; ip; ip = ip -> next) {
04282                 /* If interfaces were specified, don't configure
04283                    interfaces that weren't specified! */
04284                 if (ip -> flags & INTERFACE_RUNNING ||
04285                    (ip -> flags & (INTERFACE_REQUESTED |
04286                                      INTERFACE_AUTOMATIC)) !=
04287                      INTERFACE_REQUESTED)
04288                         continue;
04289                 script_init (ip -> client,
04290                              "PREINIT", (struct string_list *)0);
04291                 if (ip -> client -> alias)
04292                         script_write_params (ip -> client, "alias_",
04293                                              ip -> client -> alias);
04294                 script_go (ip -> client);
04295         }
04296 
04297         discover_interfaces (interfaces_requested != 0
04298                              ? DISCOVER_REQUESTED
04299                              : DISCOVER_RUNNING);
04300 
04301         for (ip = interfaces; ip; ip = ip -> next) {
04302                 if (ip -> flags & INTERFACE_RUNNING)
04303                         continue;
04304                 ip -> flags |= INTERFACE_RUNNING;
04305                 for (client = ip->client ; client ; client = client->next) {
04306                         client->state = S_INIT;
04307                         state_reboot(client);
04308                 }
04309         }
04310         return ISC_R_SUCCESS;
04311 }
04312 
04313 /* The client should never receive a relay agent information option,
04314    so if it does, log it and discard it. */
04315 
04316 int parse_agent_information_option (packet, len, data)
04317         struct packet *packet;
04318         int len;
04319         u_int8_t *data;
04320 {
04321         return 1;
04322 }
04323 
04324 /* The client never sends relay agent information options. */
04325 
04326 unsigned cons_agent_information_options (cfg_options, outpacket,
04327                                          agentix, length)
04328         struct option_state *cfg_options;
04329         struct dhcp_packet *outpacket;
04330         unsigned agentix;
04331         unsigned length;
04332 {
04333         return length;
04334 }
04335 
04336 static void shutdown_exit (void *foo)
04337 {
04338         exit (0);
04339 }
04340 
04341 #if defined (NSUPDATE)
04342 /*
04343  * If the first query fails, the updater MUST NOT delete the DNS name.  It
04344  * may be that the host whose lease on the server has expired has moved
04345  * to another network and obtained a lease from a different server,
04346  * which has caused the client's A RR to be replaced. It may also be
04347  * that some other client has been configured with a name that matches
04348  * the name of the DHCP client, and the policy was that the last client
04349  * to specify the name would get the name.  In this case, the DHCID RR
04350  * will no longer match the updater's notion of the client-identity of
04351  * the host pointed to by the DNS name.
04352  *   -- "Interaction between DHCP and DNS"
04353  */
04354 
04355 /* The first and second stages are pretty similar so we combine them */
04356 void
04357 client_dns_remove_action(dhcp_ddns_cb_t *ddns_cb,
04358                          isc_result_t    eresult)
04359 {
04360 
04361         isc_result_t result;
04362 
04363         if ((eresult == ISC_R_SUCCESS) &&
04364             (ddns_cb->state == DDNS_STATE_REM_FW_YXDHCID)) {
04365                 /* Do the second stage of the FWD removal */
04366                 ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
04367 
04368                 result = ddns_modify_fwd(ddns_cb, MDL);
04369                 if (result == ISC_R_SUCCESS) {
04370                         return;
04371                 }
04372         }
04373 
04374         /* If we are done or have an error clean up */
04375         ddns_cb_free(ddns_cb, MDL);
04376         return;
04377 }
04378 
04379 void
04380 client_dns_remove(struct client_state *client,
04381                   struct iaddr        *addr)
04382 {
04383         dhcp_ddns_cb_t *ddns_cb;
04384         isc_result_t result;
04385 
04386         /* if we have an old ddns request for this client, cancel it */
04387         if (client->ddns_cb != NULL) {
04388                 ddns_cancel(client->ddns_cb, MDL);
04389                 client->ddns_cb = NULL;
04390         }
04391         
04392         ddns_cb = ddns_cb_alloc(MDL);
04393         if (ddns_cb != NULL) {
04394                 ddns_cb->address = *addr;
04395                 ddns_cb->timeout = 0;
04396 
04397                 ddns_cb->state = DDNS_STATE_REM_FW_YXDHCID;
04398                 ddns_cb->flags = DDNS_UPDATE_ADDR;
04399                 ddns_cb->cur_func = client_dns_remove_action;
04400 
04401                 result = client_dns_update(client, ddns_cb);
04402 
04403                 if (result != ISC_R_TIMEDOUT) {
04404                         ddns_cb_free(ddns_cb, MDL);
04405                 }
04406         }
04407 }
04408 #endif
04409 
04410 isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
04411                                      control_object_state_t newstate)
04412 {
04413         struct interface_info *ip;
04414         struct client_state *client;
04415         struct timeval tv;
04416 
04417         if (newstate == server_shutdown) {
04418                 /* Re-entry */
04419                 if (shutdown_signal == SIGUSR1)
04420                         return ISC_R_SUCCESS;
04421                 /* Log shutdown on signal. */
04422                 if ((shutdown_signal == SIGINT) ||
04423                     (shutdown_signal == SIGTERM)) {
04424                         log_info("Received signal %d, initiating shutdown.",
04425                                  shutdown_signal);
04426                 }
04427                 /* Mark it was called. */
04428                 shutdown_signal = SIGUSR1;
04429         }
04430 
04431         /* Do the right thing for each interface. */
04432         for (ip = interfaces; ip; ip = ip -> next) {
04433             for (client = ip -> client; client; client = client -> next) {
04434                 switch (newstate) {
04435                   case server_startup:
04436                     return ISC_R_SUCCESS;
04437 
04438                   case server_running:
04439                     return ISC_R_SUCCESS;
04440 
04441                   case server_shutdown:
04442                     if (client -> active &&
04443                         client -> active -> expiry > cur_time) {
04444 #if defined (NSUPDATE)
04445                             if (client->config->do_forward_update) {
04446                                     client_dns_remove(client,
04447                                                       &client->active->address);
04448                             }
04449 #endif
04450                             do_release (client);
04451                     }
04452                     break;
04453 
04454                   case server_hibernate:
04455                     state_stop (client);
04456                     break;
04457 
04458                   case server_awaken:
04459                     state_reboot (client);
04460                     break;
04461                 }
04462             }
04463         }
04464 
04465         if (newstate == server_shutdown) {
04466                 tv.tv_sec = cur_tv.tv_sec;
04467                 tv.tv_usec = cur_tv.tv_usec + 1;
04468                 add_timeout(&tv, shutdown_exit, 0, 0, 0);
04469         }
04470         return ISC_R_SUCCESS;
04471 }
04472 
04473 #if defined (NSUPDATE)
04474 /*
04475  * Called after a timeout if the DNS update failed on the previous try.
04476  * Starts the retry process.  If the retry times out it will schedule
04477  * this routine to run again after a 10x wait.
04478  */
04479 void
04480 client_dns_update_timeout (void *cp)
04481 {
04482         dhcp_ddns_cb_t *ddns_cb = (dhcp_ddns_cb_t *)cp;
04483         struct client_state *client = (struct client_state *)ddns_cb->lease;
04484         isc_result_t status = ISC_R_FAILURE;
04485 
04486         if ((client != NULL) &&
04487             ((client->active != NULL) ||
04488              (client->active_lease != NULL)))
04489                 status = client_dns_update(client, ddns_cb);
04490 
04491         /*
04492          * A status of timedout indicates that we started the update and
04493          * have released control of the control block.  Any other status
04494          * indicates that we should clean up the control block.  We either
04495          * got a success which indicates that we didn't really need to
04496          * send an update or some other error in which case we weren't able
04497          * to start the update process.  In both cases we still own
04498          * the control block and should free it.
04499          */
04500         if (status != ISC_R_TIMEDOUT) {
04501                 if (client != NULL) {
04502                         client->ddns_cb = NULL;
04503                 }
04504                 ddns_cb_free(ddns_cb, MDL);
04505         }
04506 }
04507 
04508 /*
04509  * If the first query succeeds, the updater can conclude that it
04510  * has added a new name whose only RRs are the A and DHCID RR records.
04511  * The A RR update is now complete (and a client updater is finished,
04512  * while a server might proceed to perform a PTR RR update).
04513  *   -- "Interaction between DHCP and DNS"
04514  *
04515  * If the second query succeeds, the updater can conclude that the current
04516  * client was the last client associated with the domain name, and that
04517  * the name now contains the updated A RR. The A RR update is now
04518  * complete (and a client updater is finished, while a server would
04519  * then proceed to perform a PTR RR update).
04520  *   -- "Interaction between DHCP and DNS"
04521  *
04522  * If the second query fails with NXRRSET, the updater must conclude
04523  * that the client's desired name is in use by another host.  At this
04524  * juncture, the updater can decide (based on some administrative
04525  * configuration outside of the scope of this document) whether to let
04526  * the existing owner of the name keep that name, and to (possibly)
04527  * perform some name disambiguation operation on behalf of the current
04528  * client, or to replace the RRs on the name with RRs that represent
04529  * the current client. If the configured policy allows replacement of
04530  * existing records, the updater submits a query that deletes the
04531  * existing A RR and the existing DHCID RR, adding A and DHCID RRs that
04532  * represent the IP address and client-identity of the new client.
04533  *   -- "Interaction between DHCP and DNS"
04534  */
04535 
04536 /* The first and second stages are pretty similar so we combine them */
04537 void
04538 client_dns_update_action(dhcp_ddns_cb_t *ddns_cb,
04539                          isc_result_t    eresult)
04540 {
04541         isc_result_t result;
04542         struct timeval tv;
04543 
04544         switch(eresult) {
04545         case ISC_R_SUCCESS:
04546         default:
04547                 /* Either we succeeded or broke in a bad way, clean up */
04548                 break;
04549 
04550         case DNS_R_YXRRSET:
04551                 /*
04552                  * This is the only difference between the two stages,
04553                  * check to see if it is the first stage, in which case
04554                  * start the second stage
04555                  */
04556                 if (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) {
04557                         ddns_cb->state = DDNS_STATE_ADD_FW_YXDHCID;
04558                         ddns_cb->cur_func = client_dns_update_action;
04559 
04560                         result = ddns_modify_fwd(ddns_cb, MDL);
04561                         if (result == ISC_R_SUCCESS) {
04562                                 return;
04563                         }
04564                 }
04565                 break;
04566 
04567         case ISC_R_TIMEDOUT:
04568                 /*
04569                  * We got a timeout response from the DNS module.  Schedule
04570                  * another attempt for later.  We forget the name, dhcid and
04571                  * zone so if it gets changed we will get the new information.
04572                  */
04573                 data_string_forget(&ddns_cb->fwd_name, MDL);
04574                 data_string_forget(&ddns_cb->dhcid, MDL);
04575                 if (ddns_cb->zone != NULL) {
04576                         forget_zone((struct dns_zone **)&ddns_cb->zone);
04577                 }
04578 
04579                 /* Reset to doing the first stage */
04580                 ddns_cb->state    = DDNS_STATE_ADD_FW_NXDOMAIN;
04581                 ddns_cb->cur_func = client_dns_update_action;
04582 
04583                 /* and update our timer */
04584                 if (ddns_cb->timeout < 3600)
04585                         ddns_cb->timeout *= 10;
04586                 tv.tv_sec = cur_tv.tv_sec + ddns_cb->timeout;
04587                 tv.tv_usec = cur_tv.tv_usec;
04588                 add_timeout(&tv, client_dns_update_timeout,
04589                             ddns_cb, NULL, NULL);
04590                 return;
04591         }
04592 
04593         ddns_cb_free(ddns_cb, MDL);
04594         return;
04595 }
04596 
04597 /* See if we should do a DNS update, and if so, do it. */
04598 
04599 isc_result_t
04600 client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
04601 {
04602         struct data_string client_identifier;
04603         struct option_cache *oc;
04604         int ignorep;
04605         int result;
04606         int ddns_v4_type;
04607         isc_result_t rcode;
04608 
04609         /* If we didn't send an FQDN option, we certainly aren't going to
04610            be doing an update. */
04611         if (!client -> sent_options)
04612                 return ISC_R_SUCCESS;
04613 
04614         /* If we don't have a lease, we can't do an update. */
04615         if ((client->active == NULL) && (client->active_lease == NULL))
04616                 return ISC_R_SUCCESS;
04617 
04618         /* If we set the no client update flag, don't do the update. */
04619         if ((oc = lookup_option (&fqdn_universe, client -> sent_options,
04620                                   FQDN_NO_CLIENT_UPDATE)) &&
04621             evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
04622                                            (struct lease *)0, client,
04623                                            client -> sent_options,
04624                                            (struct option_state *)0,
04625                                            &global_scope, oc, MDL))
04626                 return ISC_R_SUCCESS;
04627 
04628         /* If we set the "server, please update" flag, or didn't set it
04629            to false, don't do the update. */
04630         if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
04631                                   FQDN_SERVER_UPDATE)) ||
04632             evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
04633                                            (struct lease *)0, client,
04634                                            client -> sent_options,
04635                                            (struct option_state *)0,
04636                                            &global_scope, oc, MDL))
04637                 return ISC_R_SUCCESS;
04638 
04639         /* If no FQDN option was supplied, don't do the update. */
04640         if (!(oc = lookup_option (&fqdn_universe, client -> sent_options,
04641                                   FQDN_FQDN)) ||
04642             !evaluate_option_cache (&ddns_cb->fwd_name, (struct packet *)0,
04643                                     (struct lease *)0, client,
04644                                     client -> sent_options,
04645                                     (struct option_state *)0,
04646                                     &global_scope, oc, MDL))
04647                 return ISC_R_SUCCESS;
04648 
04649         /*
04650          * Construct the DHCID value for use in the DDNS update process
04651          * We have the newer standard version and the older interim version
04652          * chosen by the '-I' option.  The interim version is left as is
04653          * for backwards compatibility.  The standard version is based on
04654          * RFC 4701 section 3.3
04655          */
04656 
04657         result = 0;
04658         POST(result);
04659         memset(&client_identifier, 0, sizeof(client_identifier));
04660 
04661         if (std_dhcid == 1) {
04662                 /* standard style */
04663                 ddns_cb->dhcid_class = dns_rdatatype_dhcid;
04664                 ddns_v4_type = 1;
04665         } else {
04666                 /* interim style */
04667                 ddns_cb->dhcid_class = dns_rdatatype_txt;
04668                 /* for backwards compatibility */
04669                 ddns_v4_type = DHO_DHCP_CLIENT_IDENTIFIER;
04670         }
04671         if (client->active_lease != NULL) {
04672                 /* V6 request, get the client identifier, then
04673                  * construct the dhcid for either standard 
04674                  * or interim */
04675                 if (((oc = lookup_option(&dhcpv6_universe,
04676                                          client->sent_options,
04677                                          D6O_CLIENTID)) != NULL) &&
04678                     evaluate_option_cache(&client_identifier, NULL,
04679                                           NULL, client,
04680                                           client->sent_options, NULL,
04681                                           &global_scope, oc, MDL)) {
04682                         result = get_dhcid(ddns_cb, 2,
04683                                            client_identifier.data,
04684                                            client_identifier.len);
04685                         data_string_forget(&client_identifier, MDL);
04686                 } else
04687                         log_fatal("Impossible condition at %s:%d.", MDL);
04688         } else {
04689                 /*
04690                  * V4 request, use the client id if there is one or the
04691                  * mac address if there isn't.  If we have a client id
04692                  * we check to see if it is an embedded DUID.
04693                  */
04694                 if (((oc = lookup_option(&dhcp_universe,
04695                                          client->sent_options,
04696                                          DHO_DHCP_CLIENT_IDENTIFIER)) != NULL) &&
04697                     evaluate_option_cache(&client_identifier, NULL,
04698                                           NULL, client,
04699                                           client->sent_options, NULL,
04700                                           &global_scope, oc, MDL)) {
04701                         if ((std_dhcid == 1) && (duid_v4 == 1) &&
04702                             (client_identifier.data[0] == 255)) {
04703                                 /*
04704                                  * This appears to be an embedded DUID,
04705                                  * extract it and treat it as such
04706                                  */
04707                                 if (client_identifier.len <= 5)
04708                                         log_fatal("Impossible condition at %s:%d.",
04709                                                   MDL);
04710                                 result = get_dhcid(ddns_cb, 2,
04711                                                    client_identifier.data + 5,
04712                                                    client_identifier.len - 5);
04713                         } else {
04714                                 result = get_dhcid(ddns_cb, ddns_v4_type,
04715                                                    client_identifier.data,
04716                                                    client_identifier.len);
04717                         }
04718                         data_string_forget(&client_identifier, MDL);
04719                 } else
04720                         result = get_dhcid(ddns_cb, 0,
04721                                            client->interface->hw_address.hbuf,
04722                                            client->interface->hw_address.hlen);
04723         }
04724 
04725         if (!result) {
04726                 return ISC_R_SUCCESS;
04727         }
04728 
04729         /*
04730          * Perform updates.
04731          */
04732         if (ddns_cb->fwd_name.len && ddns_cb->dhcid.len) {
04733                 rcode = ddns_modify_fwd(ddns_cb, MDL);
04734         } else
04735                 rcode = ISC_R_FAILURE;
04736 
04737         /*
04738          * A success from the modify routine means we are performing
04739          * async processing, for which we use the timedout error message.
04740          */
04741         if (rcode == ISC_R_SUCCESS) {
04742                 rcode = ISC_R_TIMEDOUT;
04743         }
04744 
04745         return rcode;
04746 }
04747 
04748 
04749 /*
04750  * Schedule the first update.  They will continue to retry occasionally
04751  * until they no longer time out (or fail).
04752  */
04753 void
04754 dhclient_schedule_updates(struct client_state *client,
04755                           struct iaddr        *addr,
04756                           int                  offset)
04757 {
04758         dhcp_ddns_cb_t *ddns_cb;
04759         struct timeval tv;
04760 
04761         if (!client->config->do_forward_update)
04762                 return;
04763 
04764         /* cancel any outstanding ddns requests */
04765         if (client->ddns_cb != NULL) {
04766                 ddns_cancel(client->ddns_cb, MDL);
04767                 client->ddns_cb = NULL;
04768         }
04769 
04770         ddns_cb = ddns_cb_alloc(MDL);
04771 
04772         if (ddns_cb != NULL) {
04773                 ddns_cb->lease = (void *)client;
04774                 ddns_cb->address = *addr;
04775                 ddns_cb->timeout = 1;
04776 
04777                 /*
04778                  * XXX: DNS TTL is a problem we need to solve properly.
04779                  * Until that time, 300 is a placeholder default for
04780                  * something that is less insane than a value scaled
04781                  * by lease timeout.
04782                  */
04783                 ddns_cb->ttl = 300;
04784 
04785                 ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
04786                 ddns_cb->cur_func = client_dns_update_action;
04787                 ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_INCLUDE_RRSET;
04788 
04789                 client->ddns_cb = ddns_cb;
04790 
04791                 tv.tv_sec = cur_tv.tv_sec + offset;
04792                 tv.tv_usec = cur_tv.tv_usec;
04793                 add_timeout(&tv, client_dns_update_timeout,
04794                             ddns_cb, NULL, NULL);
04795         } else {
04796                 log_error("Unable to allocate dns update state for %s",
04797                           piaddr(*addr));
04798         }
04799 }
04800 #endif
04801 
04802 void
04803 dhcpv4_client_assignments(void)
04804 {
04805         struct servent *ent;
04806 
04807         if (path_dhclient_pid == NULL)
04808                 path_dhclient_pid = _PATH_DHCLIENT_PID;
04809         if (path_dhclient_db == NULL)
04810                 path_dhclient_db = _PATH_DHCLIENT_DB;
04811 
04812         /* Default to the DHCP/BOOTP port. */
04813         if (!local_port) {
04814                 /* If we're faking a relay agent, and we're not using loopback,
04815                    use the server port, not the client port. */
04816                 if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
04817                         local_port = htons(67);
04818                 } else {
04819                         ent = getservbyname ("dhcpc", "udp");
04820                         if (!ent)
04821                                 local_port = htons (68);
04822                         else
04823                                 local_port = ent -> s_port;
04824 #ifndef __CYGWIN32__
04825                         endservent ();
04826 #endif
04827                 }
04828         }
04829 
04830         /* If we're faking a relay agent, and we're not using loopback,
04831            we're using the server port, not the client port. */
04832         if (mockup_relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) {
04833                 remote_port = local_port;
04834         } else
04835                 remote_port = htons (ntohs (local_port) - 1);   /* XXX */
04836 }
04837 
04838 /*
04839  * The following routines are used to check that certain
04840  * strings are reasonable before we pass them to the scripts.
04841  * This avoids some problems with scripts treating the strings
04842  * as commands - see ticket 23722
04843  * The domain checking code should be done as part of assembling
04844  * the string but we are doing it here for now due to time
04845  * constraints.
04846  */
04847 
04848 static int check_domain_name(const char *ptr, size_t len, int dots)
04849 {
04850         const char *p;
04851 
04852         /* not empty or complete length not over 255 characters   */
04853         if ((len == 0) || (len > 256))
04854                 return(-1);
04855 
04856         /* consists of [[:alnum:]-]+ labels separated by [.]      */
04857         /* a [_] is against RFC but seems to be "widely used"...  */
04858         for (p=ptr; (*p != 0) && (len-- > 0); p++) {
04859                 if ((*p == '-') || (*p == '_')) {
04860                         /* not allowed at begin or end of a label */
04861                         if (((p - ptr) == 0) || (len == 0) || (p[1] == '.'))
04862                                 return(-1);
04863                 } else if (*p == '.') {
04864                         /* each label has to be 1-63 characters;
04865                            we allow [.] at the end ('foo.bar.')   */
04866                         size_t d = p - ptr;
04867                         if ((d <= 0) || (d >= 64))
04868                                 return(-1);
04869                         ptr = p + 1; /* jump to the next label    */
04870                         if ((dots > 0) && (len > 0))
04871                                 dots--;
04872                 } else if (isalnum((unsigned char)*p) == 0) {
04873                         /* also numbers at the begin are fine     */
04874                         return(-1);
04875                 }
04876         }
04877         return(dots ? -1 : 0);
04878 }
04879 
04880 static int check_domain_name_list(const char *ptr, size_t len, int dots)
04881 {
04882         const char *p;
04883         int ret = -1; /* at least one needed */
04884 
04885         if ((ptr == NULL) || (len == 0))
04886                 return(-1);
04887 
04888         for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
04889                 if (*p != ' ')
04890                         continue;
04891                 if (p > ptr) {
04892                         if (check_domain_name(ptr, p - ptr, dots) != 0)
04893                                 return(-1);
04894                         ret = 0;
04895                 }
04896                 ptr = p + 1;
04897         }
04898         if (p > ptr)
04899                 return(check_domain_name(ptr, p - ptr, dots));
04900         else
04901                 return(ret);
04902 }
04903 
04904 static int check_option_values(struct universe *universe,
04905                                unsigned int opt,
04906                                const char *ptr,
04907                                size_t len)
04908 {
04909         if (ptr == NULL)
04910                 return(-1);
04911 
04912         /* just reject options we want to protect, will be escaped anyway */
04913         if ((universe == NULL) || (universe == &dhcp_universe)) {
04914                 switch(opt) {
04915                       case DHO_DOMAIN_NAME:
04916 #ifdef ACCEPT_LIST_IN_DOMAIN_NAME
04917                               return check_domain_name_list(ptr, len, 0);
04918 #else
04919                               return check_domain_name(ptr, len, 0);
04920 #endif
04921                       case DHO_HOST_NAME:
04922                       case DHO_NIS_DOMAIN:
04923                       case DHO_NETBIOS_SCOPE:
04924                         return check_domain_name(ptr, len, 0);
04925                         break;
04926                       case DHO_DOMAIN_SEARCH:
04927                         return check_domain_name_list(ptr, len, 0);
04928                         break;
04929                       case DHO_ROOT_PATH:
04930                         if (len == 0)
04931                                 return(-1);
04932                         for (; (*ptr != 0) && (len-- > 0); ptr++) {
04933                                 if(!(isalnum((unsigned char)*ptr) ||
04934                                      *ptr == '#'  || *ptr == '%' ||
04935                                      *ptr == '+'  || *ptr == '-' ||
04936                                      *ptr == '_'  || *ptr == ':' ||
04937                                      *ptr == '.'  || *ptr == ',' ||
04938                                      *ptr == '@'  || *ptr == '~' ||
04939                                      *ptr == '\\' || *ptr == '/' ||
04940                                      *ptr == '['  || *ptr == ']' ||
04941                                      *ptr == '='  || *ptr == ' '))
04942                                         return(-1);
04943                         }
04944                         return(0);
04945                         break;
04946                 }
04947         }
04948 
04949 #ifdef DHCPv6
04950         if (universe == &dhcpv6_universe) {
04951                 switch(opt) {
04952                       case D6O_SIP_SERVERS_DNS:
04953                       case D6O_DOMAIN_SEARCH:
04954                       case D6O_NIS_DOMAIN_NAME:
04955                       case D6O_NISP_DOMAIN_NAME:
04956                         return check_domain_name_list(ptr, len, 0);
04957                         break;
04958                 }
04959         }
04960 #endif
04961 
04962         return(0);
04963 }
04964 
04965 static void
04966 add_reject(struct packet *packet) {
04967         struct iaddrmatchlist *list;
04968         
04969         list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
04970         if (!list)
04971                 log_fatal ("no memory for reject list!");
04972 
04973         /*
04974          * client_addr is misleading - it is set to source address in common
04975          * code.
04976          */
04977         list->match.addr = packet->client_addr;
04978         /* Set mask to indicate host address. */
04979         list->match.mask.len = list->match.addr.len;
04980         memset(list->match.mask.iabuf, 0xff, sizeof(list->match.mask.iabuf));
04981 
04982         /* Append to reject list for the source interface. */
04983         list->next = packet->interface->client->config->reject_list;
04984         packet->interface->client->config->reject_list = list;
04985 
04986         /*
04987          * We should inform user that we won't be accepting this server
04988          * anymore.
04989          */
04990         log_info("Server added to list of rejected servers.");
04991 }
04992 

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1