client/dhc6.c

Go to the documentation of this file.
00001 /* dhc6.c - DHCPv6 client routines. */
00002 
00003 /*
00004  * Copyright (c) 2012-2013 by Internet Systems Consortium, Inc. ("ISC")
00005  * Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
00006  *
00007  * Permission to use, copy, modify, and distribute this software for any
00008  * purpose with or without fee is hereby granted, provided that the above
00009  * copyright notice and this permission notice appear in all copies.
00010  *
00011  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00012  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00013  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00014  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00015  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00016  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00017  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00018  *
00019  *   Internet Systems Consortium, Inc.
00020  *   950 Charter Street
00021  *   Redwood City, CA 94063
00022  *   <info@isc.org>
00023  *   https://www.isc.org/
00024  */
00025 
00026 #include "dhcpd.h"
00027 
00028 #ifdef DHCPv6
00029 
00030 struct sockaddr_in6 DHCPv6DestAddr;
00031 
00032 /*
00033  * Option definition structures that are used by the software - declared
00034  * here once and assigned at startup to save lookups.
00035  */
00036 struct option *clientid_option = NULL;
00037 struct option *elapsed_option = NULL;
00038 struct option *ia_na_option = NULL;
00039 struct option *ia_ta_option = NULL;
00040 struct option *ia_pd_option = NULL;
00041 struct option *iaaddr_option = NULL;
00042 struct option *iaprefix_option = NULL;
00043 struct option *oro_option = NULL;
00044 struct option *irt_option = NULL;
00045 
00046 static struct dhc6_lease *dhc6_dup_lease(struct dhc6_lease *lease,
00047                                          const char *file, int line);
00048 static struct dhc6_ia *dhc6_dup_ia(struct dhc6_ia *ia,
00049                                    const char *file, int line);
00050 static struct dhc6_addr *dhc6_dup_addr(struct dhc6_addr *addr,
00051                                        const char *file, int line);
00052 static void dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line);
00053 static isc_result_t dhc6_parse_ia_na(struct dhc6_ia **pia,
00054                                      struct packet *packet,
00055                                      struct option_state *options);
00056 static isc_result_t dhc6_parse_ia_ta(struct dhc6_ia **pia,
00057                                      struct packet *packet,
00058                                      struct option_state *options);
00059 static isc_result_t dhc6_parse_ia_pd(struct dhc6_ia **pia,
00060                                      struct packet *packet,
00061                                      struct option_state *options);
00062 static isc_result_t dhc6_parse_addrs(struct dhc6_addr **paddr,
00063                                      struct packet *packet,
00064                                      struct option_state *options);
00065 static isc_result_t dhc6_parse_prefixes(struct dhc6_addr **ppref,
00066                                         struct packet *packet,
00067                                         struct option_state *options);
00068 static struct dhc6_ia *find_ia(struct dhc6_ia *head,
00069                                u_int16_t type, const char *id);
00070 static struct dhc6_addr *find_addr(struct dhc6_addr *head,
00071                                    struct iaddr *address);
00072 static struct dhc6_addr *find_pref(struct dhc6_addr *head,
00073                                    struct iaddr *prefix, u_int8_t plen);
00074 void init_handler(struct packet *packet, struct client_state *client);
00075 void info_request_handler(struct packet *packet, struct client_state *client);
00076 void rapid_commit_handler(struct packet *packet, struct client_state *client);
00077 void do_init6(void *input);
00078 void do_info_request6(void *input);
00079 void do_confirm6(void *input);
00080 void reply_handler(struct packet *packet, struct client_state *client);
00081 static isc_result_t dhc6_add_ia_na(struct client_state *client,
00082                                    struct data_string *packet,
00083                                    struct dhc6_lease *lease,
00084                                    u_int8_t message);
00085 static isc_result_t dhc6_add_ia_ta(struct client_state *client,
00086                                    struct data_string *packet,
00087                                    struct dhc6_lease *lease,
00088                                    u_int8_t message);
00089 static isc_result_t dhc6_add_ia_pd(struct client_state *client,
00090                                    struct data_string *packet,
00091                                    struct dhc6_lease *lease,
00092                                    u_int8_t message);
00093 static isc_boolean_t stopping_finished(void);
00094 static void dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst);
00095 void do_select6(void *input);
00096 void do_refresh6(void *input);
00097 static void do_release6(void *input);
00098 static void start_bound(struct client_state *client);
00099 static void start_decline6(struct client_state *client);
00100 static void do_decline6(void *input);
00101 static void start_informed(struct client_state *client);
00102 void informed_handler(struct packet *packet, struct client_state *client);
00103 void bound_handler(struct packet *packet, struct client_state *client);
00104 void start_renew6(void *input);
00105 void start_rebind6(void *input);
00106 void do_depref(void *input);
00107 void do_expire(void *input);
00108 static void make_client6_options(struct client_state *client,
00109                                  struct option_state **op,
00110                                  struct dhc6_lease *lease, u_int8_t message);
00111 static void script_write_params6(struct client_state *client,
00112                                  const char *prefix,
00113                                  struct option_state *options);
00114 static void script_write_requested6(struct client_state *client);
00115 static isc_boolean_t active_prefix(struct client_state *client);
00116 
00117 static int check_timing6(struct client_state *client, u_int8_t msg_type, 
00118                          char *msg_str, struct dhc6_lease *lease,
00119                          struct data_string *ds);
00120 
00121 extern int onetry;
00122 extern int stateless;
00123 
00124 /*
00125  * Assign DHCPv6 port numbers as a client.
00126  */
00127 void
00128 dhcpv6_client_assignments(void)
00129 {
00130         struct servent *ent;
00131         unsigned code;
00132 
00133         if (path_dhclient_pid == NULL)
00134                 path_dhclient_pid = _PATH_DHCLIENT6_PID;
00135         if (path_dhclient_db == NULL)
00136                 path_dhclient_db = _PATH_DHCLIENT6_DB;
00137 
00138         if (local_port == 0) {
00139                 ent = getservbyname("dhcpv6-client", "udp");
00140                 if (ent == NULL)
00141                         local_port = htons(546);
00142                 else
00143                         local_port = ent->s_port;
00144         }
00145 
00146         if (remote_port == 0) {
00147                 ent = getservbyname("dhcpv6-server", "udp");
00148                 if (ent == NULL)
00149                         remote_port = htons(547);
00150                 else
00151                         remote_port = ent->s_port;
00152         }
00153 
00154         memset(&DHCPv6DestAddr, 0, sizeof(DHCPv6DestAddr));
00155         DHCPv6DestAddr.sin6_family = AF_INET6;
00156         DHCPv6DestAddr.sin6_port = remote_port;
00157         if (inet_pton(AF_INET6, All_DHCP_Relay_Agents_and_Servers,
00158                       &DHCPv6DestAddr.sin6_addr) <= 0) {
00159                 log_fatal("Bad address %s", All_DHCP_Relay_Agents_and_Servers);
00160         }
00161 
00162         code = D6O_CLIENTID;
00163         if (!option_code_hash_lookup(&clientid_option,
00164                                      dhcpv6_universe.code_hash, &code, 0, MDL))
00165                 log_fatal("Unable to find the CLIENTID option definition.");
00166 
00167         code = D6O_ELAPSED_TIME;
00168         if (!option_code_hash_lookup(&elapsed_option,
00169                                      dhcpv6_universe.code_hash, &code, 0, MDL))
00170                 log_fatal("Unable to find the ELAPSED_TIME option definition.");
00171 
00172         code = D6O_IA_NA;
00173         if (!option_code_hash_lookup(&ia_na_option, dhcpv6_universe.code_hash,
00174                                      &code, 0, MDL))
00175                 log_fatal("Unable to find the IA_NA option definition.");
00176 
00177         code = D6O_IA_TA;
00178         if (!option_code_hash_lookup(&ia_ta_option, dhcpv6_universe.code_hash,
00179                                      &code, 0, MDL))
00180                 log_fatal("Unable to find the IA_TA option definition.");
00181 
00182         code = D6O_IA_PD;
00183         if (!option_code_hash_lookup(&ia_pd_option, dhcpv6_universe.code_hash,
00184                                      &code, 0, MDL))
00185                 log_fatal("Unable to find the IA_PD option definition.");
00186 
00187         code = D6O_IAADDR;
00188         if (!option_code_hash_lookup(&iaaddr_option, dhcpv6_universe.code_hash,
00189                                      &code, 0, MDL))
00190                 log_fatal("Unable to find the IAADDR option definition.");
00191 
00192         code = D6O_IAPREFIX;
00193         if (!option_code_hash_lookup(&iaprefix_option,
00194                                      dhcpv6_universe.code_hash,
00195                                      &code, 0, MDL))
00196                 log_fatal("Unable to find the IAPREFIX option definition.");
00197 
00198         code = D6O_ORO;
00199         if (!option_code_hash_lookup(&oro_option, dhcpv6_universe.code_hash,
00200                                      &code, 0, MDL))
00201                 log_fatal("Unable to find the ORO option definition.");
00202 
00203         code = D6O_INFORMATION_REFRESH_TIME;
00204         if (!option_code_hash_lookup(&irt_option, dhcpv6_universe.code_hash,
00205                                      &code, 0, MDL))
00206                 log_fatal("Unable to find the IRT option definition.");
00207 
00208 #ifndef __CYGWIN32__ /* XXX */
00209         endservent();
00210 #endif
00211 }
00212 
00213 /*
00214  * Instead of implementing RFC3315 RAND (section 14) as a float "between"
00215  * -0.1 and 0.1 non-inclusive, we implement it as an integer.
00216  *
00217  * The result is expected to follow this table:
00218  *
00219  *              split range answer
00220  *                  - ERROR -                 base <= 0
00221  *              0       1   0..0         1 <= base <= 10
00222  *              1       3  -1..1        11 <= base <= 20
00223  *              2       5  -2..2        21 <= base <= 30
00224  *              3       7  -3..3        31 <= base <= 40
00225  *              ...
00226  *
00227  * XXX: For this to make sense, we really need to do timing on a
00228  * XXX: usec scale...we currently can assume zero for any value less than
00229  * XXX: 11, which are very common in early stages of transmission for most
00230  * XXX: messages.
00231  */
00232 static TIME
00233 dhc6_rand(TIME base)
00234 {
00235         TIME rval;
00236         TIME range;
00237         TIME split;
00238 
00239         /*
00240          * A zero or less timeout is a bad thing...we don't want to
00241          * DHCP-flood anyone.
00242          */
00243         if (base <= 0)
00244                 log_fatal("Impossible condition at %s:%d.", MDL);
00245 
00246         /*
00247          * The first thing we do is count how many random integers we want
00248          * in either direction (best thought of as the maximum negative
00249          * integer, as we will subtract this potentially from a random 0).
00250          */
00251         split = (base - 1) / 10;
00252 
00253         /* Don't bother with the rest of the math if we know we'll get 0. */
00254         if (split == 0)
00255                 return 0;
00256 
00257         /*
00258          * Then we count the total number of integers in this set.  This
00259          * is twice the number of integers in positive and negative
00260          * directions, plus zero (-1, 0, 1 is 3, -2..2 adds 2 to 5, so forth).
00261          */
00262         range = (split * 2) + 1;
00263 
00264         /* Take a random number from [0..(range-1)]. */
00265         rval = random();
00266         rval %= range;
00267 
00268         /* Offset it to uncover potential negative values. */
00269         rval -= split;
00270 
00271         return rval;
00272 }
00273 
00274 /* Initialize message exchange timers (set RT from Initial-RT). */
00275 static void
00276 dhc6_retrans_init(struct client_state *client)
00277 {
00278         int xid;
00279 
00280         /* Initialize timers. */
00281         client->txcount = 0;
00282         client->RT = client->IRT + dhc6_rand(client->IRT);
00283 
00284         /* Generate a new random 24-bit transaction ID for this exchange. */
00285 
00286 #if (RAND_MAX >= 0x00ffffff)
00287         xid = random();
00288 #elif (RAND_MAX >= 0x0000ffff)
00289         xid = (random() << 16) ^ random();
00290 #elif (RAND_MAX >= 0x000000ff)
00291         xid = (random() << 16) ^ (random() << 8) ^ random();
00292 #else
00293 # error "Random number generator of less than 8 bits not supported."
00294 #endif
00295 
00296         client->dhcpv6_transaction_id[0] = (xid >> 16) & 0xff;
00297         client->dhcpv6_transaction_id[1] = (xid >>  8) & 0xff;
00298         client->dhcpv6_transaction_id[2] =  xid        & 0xff;
00299 }
00300 
00301 /* Advance the DHCPv6 retransmission state once. */
00302 static void
00303 dhc6_retrans_advance(struct client_state *client)
00304 {
00305         struct timeval elapsed;
00306 
00307         /* elapsed = cur - start */
00308         elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
00309         elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
00310         if (elapsed.tv_usec < 0) {
00311                 elapsed.tv_sec -= 1;
00312                 elapsed.tv_usec += 1000000;
00313         }
00314         /* retrans_advance is called after consuming client->RT. */
00315         /* elapsed += RT */
00316         elapsed.tv_sec += client->RT / 100;
00317         elapsed.tv_usec += (client->RT % 100) * 10000;
00318         if (elapsed.tv_usec >= 1000000) {
00319                 elapsed.tv_sec += 1;
00320                 elapsed.tv_usec -= 1000000;
00321         }
00322 
00323         /*
00324          * RT for each subsequent message transmission is based on the previous
00325          * value of RT:
00326          *
00327          *    RT = 2*RTprev + RAND*RTprev
00328          */
00329         client->RT += client->RT + dhc6_rand(client->RT);
00330 
00331         /*
00332          * MRT specifies an upper bound on the value of RT (disregarding the
00333          * randomization added by the use of RAND).  If MRT has a value of 0,
00334          * there is no upper limit on the value of RT.  Otherwise:
00335          *
00336          *    if (RT > MRT)
00337          *       RT = MRT + RAND*MRT
00338          */
00339         if ((client->MRT != 0) && (client->RT > client->MRT))
00340                 client->RT = client->MRT + dhc6_rand(client->MRT);
00341 
00342         /*
00343          * Further, if there's an MRD, we should wake up upon reaching
00344          * the MRD rather than at some point after it.
00345          */
00346         if (client->MRD == 0) {
00347                 /* Done. */
00348                 client->txcount++;
00349                 return;
00350         }
00351         /* elapsed += client->RT */
00352         elapsed.tv_sec += client->RT / 100;
00353         elapsed.tv_usec += (client->RT % 100) * 10000;
00354         if (elapsed.tv_usec >= 1000000) {
00355                 elapsed.tv_sec += 1;
00356                 elapsed.tv_usec -= 1000000;
00357         }
00358         if (elapsed.tv_sec >= client->MRD) {
00359                 /*
00360                  * wake at RT + cur = start + MRD
00361                  */
00362                 client->RT = client->MRD +
00363                         (client->start_time.tv_sec - cur_tv.tv_sec);
00364                 client->RT = client->RT * 100 +
00365                         (client->start_time.tv_usec - cur_tv.tv_usec) / 10000;
00366         }
00367         client->txcount++;
00368 }
00369 
00370 /* Quick validation of DHCPv6 ADVERTISE packet contents. */
00371 static int
00372 valid_reply(struct packet *packet, struct client_state *client)
00373 {
00374         struct data_string sid, cid;
00375         struct option_cache *oc;
00376         int rval = ISC_TRUE;
00377 
00378         memset(&sid, 0, sizeof(sid));
00379         memset(&cid, 0, sizeof(cid));
00380 
00381         if (!lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID)) {
00382                 log_error("Response without a server identifier received.");
00383                 rval = ISC_FALSE;
00384         }
00385 
00386         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
00387         if (!oc ||
00388             !evaluate_option_cache(&sid, packet, NULL, client, packet->options,
00389                                    client->sent_options, &global_scope, oc,
00390                                    MDL)) {
00391                 log_error("Response without a client identifier.");
00392                 rval = ISC_FALSE;
00393         }
00394 
00395         oc = lookup_option(&dhcpv6_universe, client->sent_options,
00396                            D6O_CLIENTID);
00397         if (!oc ||
00398             !evaluate_option_cache(&cid, packet, NULL, client,
00399                                    client->sent_options, NULL, &global_scope,
00400                                    oc, MDL)) {
00401                 log_error("Local client identifier is missing!");
00402                 rval = ISC_FALSE;
00403         }
00404 
00405         if (sid.len == 0 ||
00406             sid.len != cid.len ||
00407             memcmp(sid.data, cid.data, sid.len)) {
00408                 log_error("Advertise with matching transaction ID, but "
00409                           "mismatching client id.");
00410                 rval = ISC_FALSE;
00411         }
00412 
00413         return rval;
00414 }
00415 
00416 /*
00417  * Create a complete copy of a DHCPv6 lease structure.
00418  */
00419 static struct dhc6_lease *
00420 dhc6_dup_lease(struct dhc6_lease *lease, const char *file, int line)
00421 {
00422         struct dhc6_lease *copy;
00423         struct dhc6_ia **insert_ia, *ia;
00424 
00425         copy = dmalloc(sizeof(*copy), file, line);
00426         if (copy == NULL) {
00427                 log_error("Out of memory for v6 lease structure.");
00428                 return NULL;
00429         }
00430 
00431         data_string_copy(&copy->server_id, &lease->server_id, file, line);
00432         copy->pref = lease->pref;
00433 
00434         memcpy(copy->dhcpv6_transaction_id, lease->dhcpv6_transaction_id,
00435                sizeof(copy->dhcpv6_transaction_id));
00436 
00437         option_state_reference(&copy->options, lease->options, file, line);
00438 
00439         insert_ia = &copy->bindings;
00440         for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
00441                 *insert_ia = dhc6_dup_ia(ia, file, line);
00442 
00443                 if (*insert_ia == NULL) {
00444                         dhc6_lease_destroy(&copy, file, line);
00445                         return NULL;
00446                 }
00447 
00448                 insert_ia = &(*insert_ia)->next;
00449         }
00450 
00451         return copy;
00452 }
00453 
00454 /*
00455  * Duplicate an IA structure.
00456  */
00457 static struct dhc6_ia *
00458 dhc6_dup_ia(struct dhc6_ia *ia, const char *file, int line)
00459 {
00460         struct dhc6_ia *copy;
00461         struct dhc6_addr **insert_addr, *addr;
00462 
00463         copy = dmalloc(sizeof(*ia), file, line);
00464 
00465         memcpy(copy->iaid, ia->iaid, sizeof(copy->iaid));
00466 
00467         copy->ia_type = ia->ia_type;
00468         copy->starts = ia->starts;
00469         copy->renew = ia->renew;
00470         copy->rebind = ia->rebind;
00471 
00472         insert_addr = &copy->addrs;
00473         for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
00474                 *insert_addr = dhc6_dup_addr(addr, file, line);
00475 
00476                 if (*insert_addr == NULL) {
00477                         dhc6_ia_destroy(&copy, file, line);
00478                         return NULL;
00479                 }
00480 
00481                 insert_addr = &(*insert_addr)->next;
00482         }
00483 
00484         if (ia->options != NULL)
00485                 option_state_reference(&copy->options, ia->options,
00486                                        file, line);
00487 
00488         return copy;
00489 }
00490 
00491 /*
00492  * Duplicate an IAADDR or IAPREFIX structure.
00493  */
00494 static struct dhc6_addr *
00495 dhc6_dup_addr(struct dhc6_addr *addr, const char *file, int line)
00496 {
00497         struct dhc6_addr *copy;
00498 
00499         copy = dmalloc(sizeof(*addr), file, line);
00500 
00501         if (copy == NULL)
00502                 return NULL;
00503 
00504         memcpy(&copy->address, &addr->address, sizeof(copy->address));
00505 
00506         copy->plen = addr->plen;
00507         copy->flags = addr->flags;
00508         copy->starts = addr->starts;
00509         copy->preferred_life = addr->preferred_life;
00510         copy->max_life = addr->max_life;
00511 
00512         if (addr->options != NULL)
00513                 option_state_reference(&copy->options, addr->options,
00514                                        file, line);
00515 
00516         return copy;
00517 }
00518 
00519 /*
00520  * Form a DHCPv6 lease structure based upon packet contents.  Creates and
00521  * populates IA's and any IAADDR/IAPREFIX's they contain.
00522  * Parsed options are deleted in order to not save them in the lease file.
00523  */
00524 static struct dhc6_lease *
00525 dhc6_leaseify(struct packet *packet)
00526 {
00527         struct data_string ds;
00528         struct dhc6_lease *lease;
00529         struct option_cache *oc;
00530 
00531         lease = dmalloc(sizeof(*lease), MDL);
00532         if (lease == NULL) {
00533                 log_error("Out of memory for v6 lease structure.");
00534                 return NULL;
00535         }
00536 
00537         memcpy(lease->dhcpv6_transaction_id, packet->dhcpv6_transaction_id, 3);
00538         option_state_reference(&lease->options, packet->options, MDL);
00539 
00540         memset(&ds, 0, sizeof(ds));
00541 
00542         /* Determine preference (default zero). */
00543         oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
00544         if (oc &&
00545             evaluate_option_cache(&ds, packet, NULL, NULL, lease->options,
00546                                   NULL, &global_scope, oc, MDL)) {
00547                 if (ds.len != 1) {
00548                         log_error("Invalid length of DHCPv6 Preference option "
00549                                   "(%d != 1)", ds.len);
00550                         data_string_forget(&ds, MDL);
00551                         dhc6_lease_destroy(&lease, MDL);
00552                         return NULL;
00553                 } else {
00554                         lease->pref = ds.data[0];
00555                         log_debug("RCV:  X-- Preference %u.",
00556                                   (unsigned)lease->pref);
00557                 }
00558 
00559                 data_string_forget(&ds, MDL);
00560         }
00561         delete_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
00562 
00563         /*
00564          * Dig into recursive DHCPv6 pockets for IA_NA and contained IAADDR
00565          * options.
00566          */
00567         if (dhc6_parse_ia_na(&lease->bindings, packet,
00568                              lease->options) != ISC_R_SUCCESS) {
00569                 /* Error conditions are logged by the caller. */
00570                 dhc6_lease_destroy(&lease, MDL);
00571                 return NULL;
00572         }
00573         /*
00574          * Dig into recursive DHCPv6 pockets for IA_TA and contained IAADDR
00575          * options.
00576          */
00577         if (dhc6_parse_ia_ta(&lease->bindings, packet,
00578                              lease->options) != ISC_R_SUCCESS) {
00579                 /* Error conditions are logged by the caller. */
00580                 dhc6_lease_destroy(&lease, MDL);
00581                 return NULL;
00582         }
00583         /*
00584          * Dig into recursive DHCPv6 pockets for IA_PD and contained IAPREFIX
00585          * options.
00586          */
00587         if (dhc6_parse_ia_pd(&lease->bindings, packet,
00588                              lease->options) != ISC_R_SUCCESS) {
00589                 /* Error conditions are logged by the caller. */
00590                 dhc6_lease_destroy(&lease, MDL);
00591                 return NULL;
00592         }
00593 
00594         /*
00595          * This is last because in the future we may want to make a different
00596          * key based upon additional information from the packet (we may need
00597          * to allow multiple leases in one client state per server, but we're
00598          * not sure based on what additional keys now).
00599          */
00600         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
00601         if ((oc == NULL) ||
00602             !evaluate_option_cache(&lease->server_id, packet, NULL, NULL,
00603                                    lease->options, NULL, &global_scope,
00604                                    oc, MDL) ||
00605             lease->server_id.len == 0) {
00606                 /* This should be impossible due to validation checks earlier.
00607                  */
00608                 log_error("Invalid SERVERID option cache.");
00609                 dhc6_lease_destroy(&lease, MDL);
00610                 return NULL;
00611         } else {
00612                 log_debug("RCV:  X-- Server ID: %s",
00613                           print_hex_1(lease->server_id.len,
00614                                       lease->server_id.data, 52));
00615         }
00616 
00617         return lease;
00618 }
00619 
00620 static isc_result_t
00621 dhc6_parse_ia_na(struct dhc6_ia **pia, struct packet *packet,
00622                  struct option_state *options)
00623 {
00624         struct data_string ds;
00625         struct dhc6_ia *ia;
00626         struct option_cache *oc;
00627         isc_result_t result;
00628 
00629         memset(&ds, 0, sizeof(ds));
00630 
00631         oc = lookup_option(&dhcpv6_universe, options, D6O_IA_NA);
00632         for ( ; oc != NULL ; oc = oc->next) {
00633                 ia = dmalloc(sizeof(*ia), MDL);
00634                 if (ia == NULL) {
00635                         log_error("Out of memory allocating IA_NA structure.");
00636                         return ISC_R_NOMEMORY;
00637                 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
00638                                                  options, NULL,
00639                                                  &global_scope, oc, MDL) &&
00640                            ds.len >= 12) {
00641                         memcpy(ia->iaid, ds.data, 4);
00642                         ia->ia_type = D6O_IA_NA;
00643                         ia->starts = cur_time;
00644                         ia->renew = getULong(ds.data + 4);
00645                         ia->rebind = getULong(ds.data + 8);
00646 
00647                         log_debug("RCV:  X-- IA_NA %s",
00648                                   print_hex_1(4, ia->iaid, 59));
00649                         /* XXX: This should be the printed time I think. */
00650                         log_debug("RCV:  | X-- starts %u",
00651                                   (unsigned)ia->starts);
00652                         log_debug("RCV:  | X-- t1 - renew  +%u", ia->renew);
00653                         log_debug("RCV:  | X-- t2 - rebind +%u", ia->rebind);
00654 
00655                         /*
00656                          * RFC3315 section 22.4, discard IA_NA's that
00657                          * have t1 greater than t2, and both not zero.
00658                          * Since RFC3315 defines this behaviour, it is not
00659                          * an error - just normal operation.
00660                          *
00661                          * Note that RFC3315 says we MUST honor these values
00662                          * if they are not zero.  So insane values are
00663                          * totally OK.
00664                          */
00665                         if ((ia->renew > 0) && (ia->rebind > 0) &&
00666                             (ia->renew > ia->rebind)) {
00667                                 log_debug("RCV:  | !-- INVALID renew/rebind "
00668                                           "times, IA_NA discarded.");
00669                                 dfree(ia, MDL);
00670                                 data_string_forget(&ds, MDL);
00671                                 continue;
00672                         }
00673 
00674                         if (ds.len > 12) {
00675                                 log_debug("RCV:  | X-- [Options]");
00676 
00677                                 if (!option_state_allocate(&ia->options,
00678                                                            MDL)) {
00679                                         log_error("Out of memory allocating "
00680                                                   "IA_NA option state.");
00681                                         dfree(ia, MDL);
00682                                         data_string_forget(&ds, MDL);
00683                                         return ISC_R_NOMEMORY;
00684                                 }
00685 
00686                                 if (!parse_option_buffer(ia->options,
00687                                                          ds.data + 12,
00688                                                          ds.len - 12,
00689                                                          &dhcpv6_universe)) {
00690                                         log_error("Corrupt IA_NA options.");
00691                                         option_state_dereference(&ia->options,
00692                                                                  MDL);
00693                                         dfree(ia, MDL);
00694                                         data_string_forget(&ds, MDL);
00695                                         return DHCP_R_BADPARSE;
00696                                 }
00697                         }
00698                         data_string_forget(&ds, MDL);
00699 
00700                         if (ia->options != NULL) {
00701                                 result = dhc6_parse_addrs(&ia->addrs, packet,
00702                                                           ia->options);
00703                                 if (result != ISC_R_SUCCESS) {
00704                                         option_state_dereference(&ia->options,
00705                                                                  MDL);
00706                                         dfree(ia, MDL);
00707                                         return result;
00708                                 }
00709                         }
00710 
00711                         while (*pia != NULL)
00712                                 pia = &(*pia)->next;
00713                         *pia = ia;
00714                         pia = &ia->next;
00715                 } else {
00716                         log_error("Invalid IA_NA option cache.");
00717                         dfree(ia, MDL);
00718                         if (ds.len != 0)
00719                                 data_string_forget(&ds, MDL);
00720                         return ISC_R_UNEXPECTED;
00721                 }
00722         }
00723         delete_option(&dhcpv6_universe, options, D6O_IA_NA);
00724 
00725         return ISC_R_SUCCESS;
00726 }
00727 
00728 static isc_result_t
00729 dhc6_parse_ia_ta(struct dhc6_ia **pia, struct packet *packet,
00730                  struct option_state *options)
00731 {
00732         struct data_string ds;
00733         struct dhc6_ia *ia;
00734         struct option_cache *oc;
00735         isc_result_t result;
00736 
00737         memset(&ds, 0, sizeof(ds));
00738 
00739         oc = lookup_option(&dhcpv6_universe, options, D6O_IA_TA);
00740         for ( ; oc != NULL ; oc = oc->next) {
00741                 ia = dmalloc(sizeof(*ia), MDL);
00742                 if (ia == NULL) {
00743                         log_error("Out of memory allocating IA_TA structure.");
00744                         return ISC_R_NOMEMORY;
00745                 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
00746                                                  options, NULL,
00747                                                  &global_scope, oc, MDL) &&
00748                            ds.len >= 4) {
00749                         memcpy(ia->iaid, ds.data, 4);
00750                         ia->ia_type = D6O_IA_TA;
00751                         ia->starts = cur_time;
00752 
00753                         log_debug("RCV:  X-- IA_TA %s",
00754                                   print_hex_1(4, ia->iaid, 59));
00755                         /* XXX: This should be the printed time I think. */
00756                         log_debug("RCV:  | X-- starts %u",
00757                                   (unsigned)ia->starts);
00758 
00759                         if (ds.len > 4) {
00760                                 log_debug("RCV:  | X-- [Options]");
00761 
00762                                 if (!option_state_allocate(&ia->options,
00763                                                            MDL)) {
00764                                         log_error("Out of memory allocating "
00765                                                   "IA_TA option state.");
00766                                         dfree(ia, MDL);
00767                                         data_string_forget(&ds, MDL);
00768                                         return ISC_R_NOMEMORY;
00769                                 }
00770 
00771                                 if (!parse_option_buffer(ia->options,
00772                                                          ds.data + 4,
00773                                                          ds.len - 4,
00774                                                          &dhcpv6_universe)) {
00775                                         log_error("Corrupt IA_TA options.");
00776                                         option_state_dereference(&ia->options,
00777                                                                  MDL);
00778                                         dfree(ia, MDL);
00779                                         data_string_forget(&ds, MDL);
00780                                         return DHCP_R_BADPARSE;
00781                                 }
00782                         }
00783                         data_string_forget(&ds, MDL);
00784 
00785                         if (ia->options != NULL) {
00786                                 result = dhc6_parse_addrs(&ia->addrs, packet,
00787                                                           ia->options);
00788                                 if (result != ISC_R_SUCCESS) {
00789                                         option_state_dereference(&ia->options,
00790                                                                  MDL);
00791                                         dfree(ia, MDL);
00792                                         return result;
00793                                 }
00794                         }
00795 
00796                         while (*pia != NULL)
00797                                 pia = &(*pia)->next;
00798                         *pia = ia;
00799                         pia = &ia->next;
00800                 } else {
00801                         log_error("Invalid IA_TA option cache.");
00802                         dfree(ia, MDL);
00803                         if (ds.len != 0)
00804                                 data_string_forget(&ds, MDL);
00805                         return ISC_R_UNEXPECTED;
00806                 }
00807         }
00808         delete_option(&dhcpv6_universe, options, D6O_IA_TA);
00809 
00810         return ISC_R_SUCCESS;
00811 }
00812 
00813 static isc_result_t
00814 dhc6_parse_ia_pd(struct dhc6_ia **pia, struct packet *packet,
00815                  struct option_state *options)
00816 {
00817         struct data_string ds;
00818         struct dhc6_ia *ia;
00819         struct option_cache *oc;
00820         isc_result_t result;
00821 
00822         memset(&ds, 0, sizeof(ds));
00823 
00824         oc = lookup_option(&dhcpv6_universe, options, D6O_IA_PD);
00825         for ( ; oc != NULL ; oc = oc->next) {
00826                 ia = dmalloc(sizeof(*ia), MDL);
00827                 if (ia == NULL) {
00828                         log_error("Out of memory allocating IA_PD structure.");
00829                         return ISC_R_NOMEMORY;
00830                 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
00831                                                  options, NULL,
00832                                                  &global_scope, oc, MDL) &&
00833                            ds.len >= 12) {
00834                         memcpy(ia->iaid, ds.data, 4);
00835                         ia->ia_type = D6O_IA_PD;
00836                         ia->starts = cur_time;
00837                         ia->renew = getULong(ds.data + 4);
00838                         ia->rebind = getULong(ds.data + 8);
00839 
00840                         log_debug("RCV:  X-- IA_PD %s",
00841                                   print_hex_1(4, ia->iaid, 59));
00842                         /* XXX: This should be the printed time I think. */
00843                         log_debug("RCV:  | X-- starts %u",
00844                                   (unsigned)ia->starts);
00845                         log_debug("RCV:  | X-- t1 - renew  +%u", ia->renew);
00846                         log_debug("RCV:  | X-- t2 - rebind +%u", ia->rebind);
00847 
00848                         /*
00849                          * RFC3633 section 9, discard IA_PD's that
00850                          * have t1 greater than t2, and both not zero.
00851                          * Since RFC3633 defines this behaviour, it is not
00852                          * an error - just normal operation.
00853                          */
00854                         if ((ia->renew > 0) && (ia->rebind > 0) &&
00855                             (ia->renew > ia->rebind)) {
00856                                 log_debug("RCV:  | !-- INVALID renew/rebind "
00857                                           "times, IA_PD discarded.");
00858                                 dfree(ia, MDL);
00859                                 data_string_forget(&ds, MDL);
00860                                 continue;
00861                         }
00862 
00863                         if (ds.len > 12) {
00864                                 log_debug("RCV:  | X-- [Options]");
00865 
00866                                 if (!option_state_allocate(&ia->options,
00867                                                            MDL)) {
00868                                         log_error("Out of memory allocating "
00869                                                   "IA_PD option state.");
00870                                         dfree(ia, MDL);
00871                                         data_string_forget(&ds, MDL);
00872                                         return ISC_R_NOMEMORY;
00873                                 }
00874 
00875                                 if (!parse_option_buffer(ia->options,
00876                                                          ds.data + 12,
00877                                                          ds.len - 12,
00878                                                          &dhcpv6_universe)) {
00879                                         log_error("Corrupt IA_PD options.");
00880                                         option_state_dereference(&ia->options,
00881                                                                  MDL);
00882                                         dfree(ia, MDL);
00883                                         data_string_forget(&ds, MDL);
00884                                         return DHCP_R_BADPARSE;
00885                                 }
00886                         }
00887                         data_string_forget(&ds, MDL);
00888 
00889                         if (ia->options != NULL) {
00890                                 result = dhc6_parse_prefixes(&ia->addrs,
00891                                                              packet,
00892                                                              ia->options);
00893                                 if (result != ISC_R_SUCCESS) {
00894                                         option_state_dereference(&ia->options,
00895                                                                  MDL);
00896                                         dfree(ia, MDL);
00897                                         return result;
00898                                 }
00899                         }
00900 
00901                         while (*pia != NULL)
00902                                 pia = &(*pia)->next;
00903                         *pia = ia;
00904                         pia = &ia->next;
00905                 } else {
00906                         log_error("Invalid IA_PD option cache.");
00907                         dfree(ia, MDL);
00908                         if (ds.len != 0)
00909                                 data_string_forget(&ds, MDL);
00910                         return ISC_R_UNEXPECTED;
00911                 }
00912         }
00913         delete_option(&dhcpv6_universe, options, D6O_IA_PD);
00914 
00915         return ISC_R_SUCCESS;
00916 }
00917 
00918 
00919 static isc_result_t
00920 dhc6_parse_addrs(struct dhc6_addr **paddr, struct packet *packet,
00921                  struct option_state *options)
00922 {
00923         struct data_string ds;
00924         struct option_cache *oc;
00925         struct dhc6_addr *addr;
00926 
00927         memset(&ds, 0, sizeof(ds));
00928 
00929         oc = lookup_option(&dhcpv6_universe, options, D6O_IAADDR);
00930         for ( ; oc != NULL ; oc = oc->next) {
00931                 addr = dmalloc(sizeof(*addr), MDL);
00932                 if (addr == NULL) {
00933                         log_error("Out of memory allocating "
00934                                   "address structure.");
00935                         return ISC_R_NOMEMORY;
00936                 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
00937                                                  options, NULL, &global_scope,
00938                                                  oc, MDL) &&
00939                            (ds.len >= 24)) {
00940 
00941                         addr->address.len = 16;
00942                         memcpy(addr->address.iabuf, ds.data, 16);
00943                         addr->starts = cur_time;
00944                         addr->preferred_life = getULong(ds.data + 16);
00945                         addr->max_life = getULong(ds.data + 20);
00946 
00947                         log_debug("RCV:  | | X-- IAADDR %s",
00948                                   piaddr(addr->address));
00949                         log_debug("RCV:  | | | X-- Preferred lifetime %u.",
00950                                   addr->preferred_life);
00951                         log_debug("RCV:  | | | X-- Max lifetime %u.",
00952                                   addr->max_life);
00953 
00954                         /*
00955                          * RFC 3315 section 22.6 says we must discard
00956                          * addresses whose pref is later than valid.
00957                          */
00958                         if ((addr->preferred_life > addr->max_life)) {
00959                                 log_debug("RCV:  | | | !-- INVALID lifetimes, "
00960                                           "IAADDR discarded.  Check your "
00961                                           "server configuration.");
00962                                 dfree(addr, MDL);
00963                                 data_string_forget(&ds, MDL);
00964                                 continue;
00965                         }
00966 
00967                         /*
00968                          * Fortunately this is the last recursion in the
00969                          * protocol.
00970                          */
00971                         if (ds.len > 24) {
00972                                 if (!option_state_allocate(&addr->options,
00973                                                            MDL)) {
00974                                         log_error("Out of memory allocating "
00975                                                   "IAADDR option state.");
00976                                         dfree(addr, MDL);
00977                                         data_string_forget(&ds, MDL);
00978                                         return ISC_R_NOMEMORY;
00979                                 }
00980 
00981                                 if (!parse_option_buffer(addr->options,
00982                                                          ds.data + 24,
00983                                                          ds.len - 24,
00984                                                          &dhcpv6_universe)) {
00985                                         log_error("Corrupt IAADDR options.");
00986                                         option_state_dereference(&addr->options,
00987                                                                  MDL);
00988                                         dfree(addr, MDL);
00989                                         data_string_forget(&ds, MDL);
00990                                         return DHCP_R_BADPARSE;
00991                                 }
00992                         }
00993 
00994                         if (addr->options != NULL)
00995                                 log_debug("RCV:  | | | X-- "
00996                                           "[Options]");
00997 
00998                         data_string_forget(&ds, MDL);
00999 
01000                         *paddr = addr;
01001                         paddr = &addr->next;
01002                 } else {
01003                         log_error("Invalid IAADDR option cache.");
01004                         dfree(addr, MDL);
01005                         if (ds.len != 0)
01006                                 data_string_forget(&ds, MDL);
01007                         return ISC_R_UNEXPECTED;
01008                 }
01009         }
01010         delete_option(&dhcpv6_universe, options, D6O_IAADDR);
01011 
01012         return ISC_R_SUCCESS;
01013 }
01014 
01015 static isc_result_t
01016 dhc6_parse_prefixes(struct dhc6_addr **ppfx, struct packet *packet,
01017                     struct option_state *options)
01018 {
01019         struct data_string ds;
01020         struct option_cache *oc;
01021         struct dhc6_addr *pfx;
01022 
01023         memset(&ds, 0, sizeof(ds));
01024 
01025         oc = lookup_option(&dhcpv6_universe, options, D6O_IAPREFIX);
01026         for ( ; oc != NULL ; oc = oc->next) {
01027                 pfx = dmalloc(sizeof(*pfx), MDL);
01028                 if (pfx == NULL) {
01029                         log_error("Out of memory allocating "
01030                                   "prefix structure.");
01031                         return ISC_R_NOMEMORY;
01032                 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
01033                                                  options, NULL, &global_scope,
01034                                                  oc, MDL) &&
01035                            (ds.len >= 25)) {
01036 
01037                         pfx->preferred_life = getULong(ds.data);
01038                         pfx->max_life = getULong(ds.data + 4);
01039                         pfx->plen = getUChar(ds.data + 8);
01040                         pfx->address.len = 16;
01041                         memcpy(pfx->address.iabuf, ds.data + 9, 16);
01042                         pfx->starts = cur_time;
01043 
01044                         log_debug("RCV:  | | X-- IAPREFIX %s/%d",
01045                                   piaddr(pfx->address), (int)pfx->plen);
01046                         log_debug("RCV:  | | | X-- Preferred lifetime %u.",
01047                                   pfx->preferred_life);
01048                         log_debug("RCV:  | | | X-- Max lifetime %u.",
01049                                   pfx->max_life);
01050 
01051                         /* Sanity check over the prefix length */
01052                         if ((pfx->plen < 4) || (pfx->plen > 128)) {
01053                                 log_debug("RCV:  | | | !-- INVALID prefix "
01054                                           "length, IAPREFIX discarded.  "
01055                                           "Check your server configuration.");
01056                                 dfree(pfx, MDL);
01057                                 data_string_forget(&ds, MDL);
01058                                 continue;
01059                         }
01060                         /*
01061                          * RFC 3633 section 10 says we must discard
01062                          * prefixes whose pref is later than valid.
01063                          */
01064                         if ((pfx->preferred_life > pfx->max_life)) {
01065                                 log_debug("RCV:  | | | !-- INVALID lifetimes, "
01066                                           "IAPREFIX discarded.  Check your "
01067                                           "server configuration.");
01068                                 dfree(pfx, MDL);
01069                                 data_string_forget(&ds, MDL);
01070                                 continue;
01071                         }
01072 
01073                         /*
01074                          * Fortunately this is the last recursion in the
01075                          * protocol.
01076                          */
01077                         if (ds.len > 25) {
01078                                 if (!option_state_allocate(&pfx->options,
01079                                                            MDL)) {
01080                                         log_error("Out of memory allocating "
01081                                                   "IAPREFIX option state.");
01082                                         dfree(pfx, MDL);
01083                                         data_string_forget(&ds, MDL);
01084                                         return ISC_R_NOMEMORY;
01085                                 }
01086 
01087                                 if (!parse_option_buffer(pfx->options,
01088                                                          ds.data + 25,
01089                                                          ds.len - 25,
01090                                                          &dhcpv6_universe)) {
01091                                         log_error("Corrupt IAPREFIX options.");
01092                                         option_state_dereference(&pfx->options,
01093                                                                  MDL);
01094                                         dfree(pfx, MDL);
01095                                         data_string_forget(&ds, MDL);
01096                                         return DHCP_R_BADPARSE;
01097                                 }
01098                         }
01099 
01100                         if (pfx->options != NULL)
01101                                 log_debug("RCV:  | | | X-- "
01102                                           "[Options]");
01103 
01104                         data_string_forget(&ds, MDL);
01105 
01106                         *ppfx = pfx;
01107                         ppfx = &pfx->next;
01108                 } else {
01109                         log_error("Invalid IAPREFIX option cache.");
01110                         dfree(pfx, MDL);
01111                         if (ds.len != 0)
01112                                 data_string_forget(&ds, MDL);
01113                         return ISC_R_UNEXPECTED;
01114                 }
01115         }
01116         delete_option(&dhcpv6_universe, options, D6O_IAPREFIX);
01117 
01118         return ISC_R_SUCCESS;
01119 }
01120 
01121 /* Clean up a lease object, deallocate all its parts, and set it to NULL. */
01122 void
01123 dhc6_lease_destroy(struct dhc6_lease **src, const char *file, int line)
01124 {
01125         struct dhc6_ia *ia, *nia;
01126         struct dhc6_lease *lease;
01127 
01128         if (src == NULL || *src == NULL) {
01129                 log_error("Attempt to destroy null lease.");
01130                 return;
01131         }
01132         lease = *src;
01133 
01134         if (lease->server_id.len != 0)
01135                 data_string_forget(&lease->server_id, file, line);
01136 
01137         for (ia = lease->bindings ; ia != NULL ; ia = nia) {
01138                 nia = ia->next;
01139 
01140                 dhc6_ia_destroy(&ia, file, line);
01141         }
01142 
01143         if (lease->options != NULL)
01144                 option_state_dereference(&lease->options, file, line);
01145 
01146         dfree(lease, file, line);
01147         *src = NULL;
01148 }
01149 
01150 /*
01151  * Traverse the addresses list, and destroy their contents, and NULL the
01152  * list pointer.
01153  */
01154 static void
01155 dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line)
01156 {
01157         struct dhc6_addr *addr, *naddr;
01158         struct dhc6_ia *ia;
01159 
01160         if (src == NULL || *src == NULL) {
01161                 log_error("Attempt to destroy null IA.");
01162                 return;
01163         }
01164         ia = *src;
01165 
01166         for (addr = ia->addrs ; addr != NULL ; addr = naddr) {
01167                 naddr = addr->next;
01168 
01169                 if (addr->options != NULL)
01170                         option_state_dereference(&addr->options, file, line);
01171 
01172                 dfree(addr, file, line);
01173         }
01174 
01175         if (ia->options != NULL)
01176                 option_state_dereference(&ia->options, file, line);
01177 
01178         dfree(ia, file, line);
01179         *src = NULL;
01180 }
01181 
01182 /*
01183  * For a given lease, insert it into the tail of the lease list.  Upon
01184  * finding a duplicate by server id, remove it and take over its position.
01185  */
01186 static void
01187 insert_lease(struct dhc6_lease **head, struct dhc6_lease *new)
01188 {
01189         while (*head != NULL) {
01190                 if ((*head)->server_id.len == new->server_id.len &&
01191                     memcmp((*head)->server_id.data, new->server_id.data,
01192                            new->server_id.len) == 0) {
01193                         new->next = (*head)->next;
01194                         dhc6_lease_destroy(head, MDL);
01195                         break;
01196                 }
01197 
01198                 head= &(*head)->next;
01199         }
01200 
01201         *head = new;
01202         return;
01203 }
01204 
01205 /*
01206  * Not really clear what to do here yet.
01207  */
01208 static int
01209 dhc6_score_lease(struct client_state *client, struct dhc6_lease *lease)
01210 {
01211         struct dhc6_ia *ia;
01212         struct dhc6_addr *addr;
01213         struct option **req;
01214         int i;
01215 
01216         if (lease->score)
01217                 return lease->score;
01218 
01219         lease->score = 1;
01220 
01221         /* If this lease lacks a required option, dump it. */
01222         /* XXX: we should be able to cache the failure... */
01223         req = client->config->required_options;
01224         if (req != NULL) {
01225                 for (i = 0 ; req[i] != NULL ; i++) {
01226                         if (lookup_option(&dhcpv6_universe, lease->options,
01227                                           req[i]->code) == NULL) {
01228                                 lease->score = 0;
01229                                 return lease->score;
01230                         }
01231                 }
01232         }
01233 
01234         /* If this lease contains a requested option, improve its score. */
01235         req = client->config->requested_options;
01236         if (req != NULL) {
01237                 for (i = 0 ; req[i] != NULL ; i++) {
01238                         if (lookup_option(&dhcpv6_universe, lease->options,
01239                                           req[i]->code) != NULL)
01240                                 lease->score++;
01241                 }
01242         }
01243 
01244         for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
01245                 lease->score += 50;
01246 
01247                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
01248                         lease->score += 100;
01249                 }
01250         }
01251 
01252         return lease->score;
01253 }
01254 
01255 /*
01256  * start_init6() kicks off the process, transmitting a packet and
01257  * scheduling a retransmission event.
01258  */
01259 void
01260 start_init6(struct client_state *client)
01261 {
01262         struct timeval tv;
01263 
01264         log_debug("PRC: Soliciting for leases (INIT).");
01265         client->state = S_INIT;
01266 
01267         /* Initialize timers, RFC3315 section 17.1.2. */
01268         client->IRT = SOL_TIMEOUT * 100;
01269         client->MRT = SOL_MAX_RT * 100;
01270         client->MRC = 0;
01271         /* Default is 0 (no max) but -1 changes this. */
01272         if (!onetry)
01273                 client->MRD = 0;
01274         else
01275                 client->MRD = client->config->timeout;
01276 
01277         dhc6_retrans_init(client);
01278 
01279         /*
01280          * RFC3315 section 17.1.2 goes out of its way:
01281          * Also, the first RT MUST be selected to be strictly greater than IRT
01282          * by choosing RAND to be strictly greater than 0.
01283          */
01284         /* if RAND < 0 then RAND = -RAND */
01285         if (client->RT <= client->IRT)
01286                 client->RT = client->IRT + (client->IRT - client->RT);
01287         /* if RAND == 0 then RAND = 1 */
01288         if (client->RT <= client->IRT)
01289                 client->RT = client->IRT + 1;
01290 
01291         client->v6_handler = init_handler;
01292 
01293         /*
01294          * RFC3315 section 17.1.2 says we MUST start the first packet
01295          * between 0 and SOL_MAX_DELAY seconds.  The good news is
01296          * SOL_MAX_DELAY is 1.
01297          */
01298         tv.tv_sec = cur_tv.tv_sec;
01299         tv.tv_usec = cur_tv.tv_usec;
01300         tv.tv_usec += (random() % (SOL_MAX_DELAY * 100)) * 10000;
01301         if (tv.tv_usec >= 1000000) {
01302                 tv.tv_sec += 1;
01303                 tv.tv_usec -= 1000000;
01304         }
01305         add_timeout(&tv, do_init6, client, NULL, NULL);
01306 
01307         if (nowait)
01308                 go_daemon();
01309 }
01310 
01311 /*
01312  * start_info_request6() kicks off the process, transmitting an info
01313  * request packet and scheduling a retransmission event.
01314  */
01315 void
01316 start_info_request6(struct client_state *client)
01317 {
01318         struct timeval tv;
01319 
01320         log_debug("PRC: Requesting information (INIT).");
01321         client->state = S_INIT;
01322 
01323         /* Initialize timers, RFC3315 section 18.1.5. */
01324         client->IRT = INF_TIMEOUT * 100;
01325         client->MRT = INF_MAX_RT * 100;
01326         client->MRC = 0;
01327         /* Default is 0 (no max) but -1 changes this. */
01328         if (!onetry)
01329                 client->MRD = 0;
01330         else
01331                 client->MRD = client->config->timeout;
01332 
01333         dhc6_retrans_init(client);
01334 
01335         client->v6_handler = info_request_handler;
01336 
01337         /*
01338          * RFC3315 section 18.1.5 says we MUST start the first packet
01339          * between 0 and INF_MAX_DELAY seconds.  The good news is
01340          * INF_MAX_DELAY is 1.
01341          */
01342         tv.tv_sec = cur_tv.tv_sec;
01343         tv.tv_usec = cur_tv.tv_usec;
01344         tv.tv_usec += (random() % (INF_MAX_DELAY * 100)) * 10000;
01345         if (tv.tv_usec >= 1000000) {
01346                 tv.tv_sec += 1;
01347                 tv.tv_usec -= 1000000;
01348         }
01349         add_timeout(&tv, do_info_request6, client, NULL, NULL);
01350 
01351         if (nowait)
01352                 go_daemon();
01353 }
01354 
01355 /* Run through the addresses in lease and return true if there's any unexpired.
01356  * Return false otherwise.
01357  */
01358 isc_boolean_t
01359 unexpired_address_in_lease(struct dhc6_lease *lease)
01360 {
01361         struct dhc6_ia *ia;
01362         struct dhc6_addr *addr;
01363 
01364         for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
01365                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
01366                         if (addr->flags & DHC6_ADDR_EXPIRED)
01367                                 continue;
01368 
01369                         if (addr->starts + addr->max_life > cur_time) {
01370                                 return ISC_TRUE;
01371                         }
01372                 }
01373         }
01374 
01375         log_info("PRC: Previous lease is devoid of active addresses."
01376                  "  Re-initializing.");
01377 
01378         return ISC_FALSE;
01379 }
01380 
01381 /*
01382  * start_confirm6() kicks off an "init-reboot" version of the process, at
01383  * startup to find out if old bindings are 'fair' and at runtime whenever
01384  * a link cycles state we'll eventually want to do this.
01385  */
01386 void
01387 start_confirm6(struct client_state *client)
01388 {
01389         struct timeval tv;
01390 
01391         /* If there is no active lease, there is nothing to check. */
01392         if ((client->active_lease == NULL) ||
01393                 !active_prefix(client) ||
01394                 client->active_lease->released ||
01395                 !unexpired_address_in_lease(client->active_lease)) {
01396                 dhc6_lease_destroy(&client->active_lease, MDL);
01397                 start_init6(client);
01398                 return;
01399         }
01400 
01401         log_debug("PRC: Confirming active lease (INIT-REBOOT).");
01402         client->state = S_REBOOTING;
01403 
01404         /* Initialize timers, RFC3315 section 17.1.3. */
01405         client->IRT = CNF_TIMEOUT * 100;
01406         client->MRT = CNF_MAX_RT * 100;
01407         client->MRC = 0;
01408         client->MRD = CNF_MAX_RD;
01409 
01410         dhc6_retrans_init(client);
01411 
01412         client->v6_handler = reply_handler;
01413 
01414         /*
01415          * RFC3315 section 18.1.2 says we MUST start the first packet
01416          * between 0 and CNF_MAX_DELAY seconds.  The good news is
01417          * CNF_MAX_DELAY is 1.
01418          */
01419         tv.tv_sec = cur_tv.tv_sec;
01420         tv.tv_usec = cur_tv.tv_usec;
01421         tv.tv_usec += (random() % (CNF_MAX_DELAY * 100)) * 10000;
01422         if (tv.tv_usec >= 1000000) {
01423                 tv.tv_sec += 1;
01424                 tv.tv_usec -= 1000000;
01425         }
01426         if (wanted_ia_pd != 0) {
01427                 client->state = S_REBINDING;
01428                 client->refresh_type = DHCPV6_REBIND;
01429                 add_timeout(&tv, do_refresh6, client, NULL, NULL);
01430         } else
01431                 add_timeout(&tv, do_confirm6, client, NULL, NULL);
01432 }
01433 
01434 /*
01435  * check_timing6() check on the timing for sending a v6 message
01436  * and then do the basic initialization for a v6 message.
01437  */
01438 #define CHK_TIM_SUCCESS         0
01439 #define CHK_TIM_MRC_EXCEEDED    1
01440 #define CHK_TIM_MRD_EXCEEDED    2
01441 #define CHK_TIM_ALLOC_FAILURE   3
01442 
01443 int
01444 check_timing6 (struct client_state *client, u_int8_t msg_type, 
01445                char *msg_str, struct dhc6_lease *lease,
01446                struct data_string *ds)
01447 {
01448         struct timeval elapsed;
01449 
01450         /*
01451          * Start_time starts at the first transmission.
01452          */
01453         if (client->txcount == 0) {
01454                 client->start_time.tv_sec = cur_tv.tv_sec;
01455                 client->start_time.tv_usec = cur_tv.tv_usec;
01456         } else if ((client->MRC != 0) && (client->txcount > client->MRC)) {
01457                 log_info("Max retransmission count exceeded.");
01458                 return(CHK_TIM_MRC_EXCEEDED);
01459         }
01460 
01461         /* elapsed = cur - start */
01462         elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
01463         elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
01464         if (elapsed.tv_usec < 0) {
01465                 elapsed.tv_sec -= 1;
01466                 elapsed.tv_usec += 1000000;
01467         }
01468 
01469         /* Check if finished (-1 argument). */
01470         if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) {
01471                 log_info("Max retransmission duration exceeded.");
01472                 return(CHK_TIM_MRD_EXCEEDED);
01473         }
01474 
01475         memset(ds, 0, sizeof(*ds));
01476         if (!buffer_allocate(&(ds->buffer), 4, MDL)) {
01477                 log_error("Unable to allocate memory for %s.", msg_str);
01478                 return(CHK_TIM_ALLOC_FAILURE);
01479         }
01480         ds->data = ds->buffer->data;
01481         ds->len = 4;
01482 
01483         ds->buffer->data[0] = msg_type;
01484         memcpy(ds->buffer->data + 1, client->dhcpv6_transaction_id, 3);
01485 
01486         /* Form an elapsed option. */
01487         /* Maximum value is 65535 1/100s coded as 0xffff. */
01488         if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
01489             ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
01490                 client->elapsed = 0xffff;
01491         } else {
01492                 client->elapsed = elapsed.tv_sec * 100;
01493                 client->elapsed += elapsed.tv_usec / 10000;
01494         }
01495 
01496         if (client->elapsed == 0)
01497                 log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str);
01498         else
01499                 log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str,
01500                           (unsigned)client->elapsed);
01501 
01502         client->elapsed = htons(client->elapsed);
01503 
01504         make_client6_options(client, &client->sent_options, lease, msg_type);
01505 
01506         return(CHK_TIM_SUCCESS);
01507 }
01508 
01509 /*
01510  * do_init6() marshals and transmits a solicit.
01511  */
01512 void
01513 do_init6(void *input)
01514 {
01515         struct client_state *client;
01516         struct dhc6_ia *old_ia;
01517         struct dhc6_addr *old_addr;
01518         struct data_string ds;
01519         struct data_string ia;
01520         struct data_string addr;
01521         struct timeval tv;
01522         u_int32_t t1, t2;
01523         int i, idx, len, send_ret;
01524 
01525         client = input;
01526 
01527         /*
01528          * In RFC3315 section 17.1.2, the retransmission timer is
01529          * used as the selecting timer.
01530          */
01531         if (client->advertised_leases != NULL) {
01532                 start_selecting6(client);
01533                 return;
01534         }
01535 
01536         switch(check_timing6(client, DHCPV6_SOLICIT, "Solicit", NULL, &ds)) {
01537               case CHK_TIM_MRC_EXCEEDED:
01538               case CHK_TIM_ALLOC_FAILURE:
01539                 return;
01540               case CHK_TIM_MRD_EXCEEDED:
01541                 client->state = S_STOPPED;
01542                 if (client->active_lease != NULL) {
01543                         dhc6_lease_destroy(&client->active_lease, MDL);
01544                         client->active_lease = NULL;
01545                 }
01546                 /* Stop if and only if this is the last client. */
01547                 if (stopping_finished())
01548                         exit(2);
01549                 return;
01550         }
01551 
01552         /*
01553          * Fetch any configured 'sent' options (includes DUID) in wire format.
01554          */
01555         dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
01556                                     NULL, client->sent_options, &global_scope,
01557                                     &dhcpv6_universe);
01558 
01559         /* Use a specific handler with rapid-commit. */
01560         if (lookup_option(&dhcpv6_universe, client->sent_options,
01561                           D6O_RAPID_COMMIT) != NULL) {
01562                 client->v6_handler = rapid_commit_handler;
01563         }
01564 
01565         /* Append IA_NA. */
01566         for (i = 0; i < wanted_ia_na; i++) {
01567                 /*
01568                  * XXX: maybe the IA_NA('s) should be put into the sent_options
01569                  * cache.  They'd have to be pulled down as they also contain
01570                  * different option caches in the same universe...
01571                  */
01572                 memset(&ia, 0, sizeof(ia));
01573                 if (!buffer_allocate(&ia.buffer, 12, MDL)) {
01574                         log_error("Unable to allocate memory for IA_NA.");
01575                         data_string_forget(&ds, MDL);
01576                         return;
01577                 }
01578                 ia.data = ia.buffer->data;
01579                 ia.len = 12;
01580 
01581                 /*
01582                  * A simple IAID is the last 4 bytes
01583                  * of the hardware address.
01584                  */
01585                 if (client->interface->hw_address.hlen > 4) {
01586                         idx = client->interface->hw_address.hlen - 4;
01587                         len = 4;
01588                 } else {
01589                         idx = 0;
01590                         len = client->interface->hw_address.hlen;
01591                 }
01592                 memcpy(ia.buffer->data,
01593                        client->interface->hw_address.hbuf + idx,
01594                        len);
01595                 if (i)
01596                         ia.buffer->data[3] += i;
01597 
01598                 t1 = client->config->requested_lease / 2;
01599                 t2 = t1 + (t1 / 2);
01600                 putULong(ia.buffer->data + 4, t1);
01601                 putULong(ia.buffer->data + 8, t2);
01602 
01603                 log_debug("XMT:  X-- IA_NA %s",
01604                           print_hex_1(4, ia.buffer->data, 55));
01605                 log_debug("XMT:  | X-- Request renew in  +%u", (unsigned)t1);
01606                 log_debug("XMT:  | X-- Request rebind in +%u", (unsigned)t2);
01607 
01608                 if ((client->active_lease != NULL) &&
01609                     ((old_ia = find_ia(client->active_lease->bindings,
01610                                        D6O_IA_NA,
01611                                        (char *)ia.buffer->data)) != NULL)) {
01612                         /*
01613                          * For each address in the old IA_NA,
01614                          * request a binding.
01615                          */
01616                         memset(&addr, 0, sizeof(addr));
01617                         for (old_addr = old_ia->addrs ; old_addr != NULL ;
01618                              old_addr = old_addr->next) {
01619                                 if (old_addr->address.len != 16) {
01620                                         log_error("Invalid IPv6 address "
01621                                                   "length %d.  "
01622                                                   "Ignoring.  (%s:%d)",
01623                                                   old_addr->address.len,
01624                                                   MDL);
01625                                         continue;
01626                                 }
01627 
01628                                 if (!buffer_allocate(&addr.buffer, 24, MDL)) {
01629                                         log_error("Unable to allocate memory "
01630                                                   "for IAADDR.");
01631                                         data_string_forget(&ia, MDL);
01632                                         data_string_forget(&ds, MDL);
01633                                         return;
01634                                 }
01635                                 addr.data = addr.buffer->data;
01636                                 addr.len = 24;
01637 
01638                                 memcpy(addr.buffer->data,
01639                                        old_addr->address.iabuf,
01640                                        16);
01641 
01642                                 t1 = client->config->requested_lease;
01643                                 t2 = t1 + (t1 / 2);
01644                                 putULong(addr.buffer->data + 16, t1);
01645                                 putULong(addr.buffer->data + 20, t2);
01646 
01647                                 log_debug("XMT:  | X-- Request address %s.",
01648                                           piaddr(old_addr->address));
01649                                 log_debug("XMT:  | | X-- Request "
01650                                           "preferred in +%u",
01651                                           (unsigned)t1);
01652                                 log_debug("XMT:  | | X-- Request valid "
01653                                           "in     +%u",
01654                                           (unsigned)t2);
01655 
01656                                 append_option(&ia, &dhcpv6_universe,
01657                                               iaaddr_option,
01658                                               &addr);
01659 
01660                                 data_string_forget(&addr, MDL);
01661                         }
01662                 }
01663 
01664                 append_option(&ds, &dhcpv6_universe, ia_na_option, &ia);
01665                 data_string_forget(&ia, MDL);
01666         }
01667 
01668         /* Append IA_TA. */
01669         for (i = 0; i < wanted_ia_ta; i++) {
01670                 /*
01671                  * XXX: maybe the IA_TA('s) should be put into the sent_options
01672                  * cache.  They'd have to be pulled down as they also contain
01673                  * different option caches in the same universe...
01674                  */
01675                 memset(&ia, 0, sizeof(ia));
01676                 if (!buffer_allocate(&ia.buffer, 4, MDL)) {
01677                         log_error("Unable to allocate memory for IA_TA.");
01678                         data_string_forget(&ds, MDL);
01679                         return;
01680                 }
01681                 ia.data = ia.buffer->data;
01682                 ia.len = 4;
01683 
01684                 /*
01685                  * A simple IAID is the last 4 bytes
01686                  * of the hardware address.
01687                  */
01688                 if (client->interface->hw_address.hlen > 4) {
01689                         idx = client->interface->hw_address.hlen - 4;
01690                         len = 4;
01691                 } else {
01692                         idx = 0;
01693                         len = client->interface->hw_address.hlen;
01694                 }
01695                 memcpy(ia.buffer->data,
01696                        client->interface->hw_address.hbuf + idx,
01697                        len);
01698                 if (i)
01699                         ia.buffer->data[3] += i;
01700 
01701                 log_debug("XMT:  X-- IA_TA %s",
01702                           print_hex_1(4, ia.buffer->data, 55));
01703 
01704                 if ((client->active_lease != NULL) &&
01705                     ((old_ia = find_ia(client->active_lease->bindings,
01706                                        D6O_IA_TA,
01707                                        (char *)ia.buffer->data)) != NULL)) {
01708                         /*
01709                          * For each address in the old IA_TA,
01710                          * request a binding.
01711                          */
01712                         memset(&addr, 0, sizeof(addr));
01713                         for (old_addr = old_ia->addrs ; old_addr != NULL ;
01714                              old_addr = old_addr->next) {
01715                                 if (old_addr->address.len != 16) {
01716                                         log_error("Invalid IPv6 address "
01717                                                   "length %d.  "
01718                                                   "Ignoring.  (%s:%d)",
01719                                                   old_addr->address.len,
01720                                                   MDL);
01721                                         continue;
01722                                 }
01723 
01724                                 if (!buffer_allocate(&addr.buffer, 24, MDL)) {
01725                                         log_error("Unable to allocate memory "
01726                                                   "for IAADDR.");
01727                                         data_string_forget(&ia, MDL);
01728                                         data_string_forget(&ds, MDL);
01729                                         return;
01730                                 }
01731                                 addr.data = addr.buffer->data;
01732                                 addr.len = 24;
01733 
01734                                 memcpy(addr.buffer->data,
01735                                        old_addr->address.iabuf,
01736                                        16);
01737 
01738                                 t1 = client->config->requested_lease;
01739                                 t2 = t1 + (t1 / 2);
01740                                 putULong(addr.buffer->data + 16, t1);
01741                                 putULong(addr.buffer->data + 20, t2);
01742 
01743                                 log_debug("XMT:  | X-- Request address %s.",
01744                                           piaddr(old_addr->address));
01745                                 log_debug("XMT:  | | X-- Request "
01746                                           "preferred in +%u",
01747                                           (unsigned)t1);
01748                                 log_debug("XMT:  | | X-- Request valid "
01749                                           "in     +%u",
01750                                           (unsigned)t2);
01751 
01752                                 append_option(&ia, &dhcpv6_universe,
01753                                               iaaddr_option,
01754                                               &addr);
01755 
01756                                 data_string_forget(&addr, MDL);
01757                         }
01758                 }
01759 
01760                 append_option(&ds, &dhcpv6_universe, ia_ta_option, &ia);
01761                 data_string_forget(&ia, MDL);
01762         }
01763 
01764         /* Append IA_PD. */
01765         for (i = 0; i < wanted_ia_pd; i++) {
01766                 /*
01767                  * XXX: maybe the IA_PD('s) should be put into the sent_options
01768                  * cache.  They'd have to be pulled down as they also contain
01769                  * different option caches in the same universe...
01770                  */
01771                 memset(&ia, 0, sizeof(ia));
01772                 if (!buffer_allocate(&ia.buffer, 12, MDL)) {
01773                         log_error("Unable to allocate memory for IA_PD.");
01774                         data_string_forget(&ds, MDL);
01775                         return;
01776                 }
01777                 ia.data = ia.buffer->data;
01778                 ia.len = 12;
01779 
01780                 /*
01781                  * A simple IAID is the last 4 bytes
01782                  * of the hardware address.
01783                  */
01784                 if (client->interface->hw_address.hlen > 4) {
01785                         idx = client->interface->hw_address.hlen - 4;
01786                         len = 4;
01787                 } else {
01788                         idx = 0;
01789                         len = client->interface->hw_address.hlen;
01790                 }
01791                 memcpy(ia.buffer->data,
01792                        client->interface->hw_address.hbuf + idx,
01793                        len);
01794                 if (i)
01795                         ia.buffer->data[3] += i;
01796 
01797                 t1 = client->config->requested_lease / 2;
01798                 t2 = t1 + (t1 / 2);
01799                 putULong(ia.buffer->data + 4, t1);
01800                 putULong(ia.buffer->data + 8, t2);
01801 
01802                 log_debug("XMT:  X-- IA_PD %s",
01803                           print_hex_1(4, ia.buffer->data, 55));
01804                 log_debug("XMT:  | X-- Request renew in  +%u", (unsigned)t1);
01805                 log_debug("XMT:  | X-- Request rebind in +%u", (unsigned)t2);
01806 
01807                 if ((client->active_lease != NULL) &&
01808                     ((old_ia = find_ia(client->active_lease->bindings,
01809                                        D6O_IA_PD,
01810                                        (char *)ia.buffer->data)) != NULL)) {
01811                         /*
01812                          * For each prefix in the old IA_PD,
01813                          * request a binding.
01814                          */
01815                         memset(&addr, 0, sizeof(addr));
01816                         for (old_addr = old_ia->addrs ; old_addr != NULL ;
01817                              old_addr = old_addr->next) {
01818                                 if (old_addr->address.len != 16) {
01819                                         log_error("Invalid IPv6 prefix, "
01820                                                   "Ignoring.  (%s:%d)",
01821                                                   MDL);
01822                                         continue;
01823                                 }
01824 
01825                                 if (!buffer_allocate(&addr.buffer, 25, MDL)) {
01826                                         log_error("Unable to allocate memory "
01827                                                   "for IAPREFIX.");
01828                                         data_string_forget(&ia, MDL);
01829                                         data_string_forget(&ds, MDL);
01830                                         return;
01831                                 }
01832                                 addr.data = addr.buffer->data;
01833                                 addr.len = 25;
01834 
01835                                 t1 = client->config->requested_lease;
01836                                 t2 = t1 + (t1 / 2);
01837                                 putULong(addr.buffer->data, t1);
01838                                 putULong(addr.buffer->data + 4, t2);
01839 
01840                                 putUChar(addr.buffer->data + 8,
01841                                          old_addr->plen);
01842                                 memcpy(addr.buffer->data + 9,
01843                                        old_addr->address.iabuf,
01844                                        16);
01845 
01846                                 log_debug("XMT:  | X-- Request prefix %s/%u.",
01847                                           piaddr(old_addr->address),
01848                                           (unsigned) old_addr->plen);
01849                                 log_debug("XMT:  | | X-- Request "
01850                                           "preferred in +%u",
01851                                           (unsigned)t1);
01852                                 log_debug("XMT:  | | X-- Request valid "
01853                                           "in     +%u",
01854                                           (unsigned)t2);
01855 
01856                                 append_option(&ia, &dhcpv6_universe,
01857                                               iaprefix_option,
01858                                               &addr);
01859 
01860                                 data_string_forget(&addr, MDL);
01861                         }
01862                 }
01863 
01864                 append_option(&ds, &dhcpv6_universe, ia_pd_option, &ia);
01865                 data_string_forget(&ia, MDL);
01866         }
01867 
01868         /* Transmit and wait. */
01869 
01870         log_info("XMT: Solicit on %s, interval %ld0ms.",
01871                  client->name ? client->name : client->interface->name,
01872                  (long int)client->RT);
01873 
01874         send_ret = send_packet6(client->interface,
01875                                 ds.data, ds.len, &DHCPv6DestAddr);
01876         if (send_ret != ds.len) {
01877                 log_error("dhc6: send_packet6() sent %d of %d bytes",
01878                           send_ret, ds.len);
01879         }
01880 
01881         data_string_forget(&ds, MDL);
01882 
01883         /* Wait RT */
01884         tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
01885         tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
01886         if (tv.tv_usec >= 1000000) {
01887                 tv.tv_sec += 1;
01888                 tv.tv_usec -= 1000000;
01889         }
01890         add_timeout(&tv, do_init6, client, NULL, NULL);
01891 
01892         dhc6_retrans_advance(client);
01893 }
01894 
01895 /* do_info_request6() marshals and transmits an information-request. */
01896 void
01897 do_info_request6(void *input)
01898 {
01899         struct client_state *client;
01900         struct data_string ds;
01901         struct timeval tv;
01902         int send_ret;
01903 
01904         client = input;
01905 
01906         switch(check_timing6(client, DHCPV6_INFORMATION_REQUEST,
01907                              "Info-Request", NULL, &ds)) {
01908               case CHK_TIM_MRC_EXCEEDED:
01909               case CHK_TIM_ALLOC_FAILURE:
01910                 return;
01911               case CHK_TIM_MRD_EXCEEDED:
01912                 exit(2);
01913               case CHK_TIM_SUCCESS:
01914                 break;
01915         }
01916 
01917         /* Fetch any configured 'sent' options (includes DUID) in wire format.
01918          */
01919         dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
01920                                     NULL, client->sent_options, &global_scope,
01921                                     &dhcpv6_universe);
01922 
01923         /* Transmit and wait. */
01924 
01925         log_info("XMT: Info-Request on %s, interval %ld0ms.",
01926                  client->name ? client->name : client->interface->name,
01927                  (long int)client->RT);
01928 
01929         send_ret = send_packet6(client->interface,
01930                                 ds.data, ds.len, &DHCPv6DestAddr);
01931         if (send_ret != ds.len) {
01932                 log_error("dhc6: send_packet6() sent %d of %d bytes",
01933                           send_ret, ds.len);
01934         }
01935 
01936         data_string_forget(&ds, MDL);
01937 
01938         /* Wait RT */
01939         tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
01940         tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
01941         if (tv.tv_usec >= 1000000) {
01942                 tv.tv_sec += 1;
01943                 tv.tv_usec -= 1000000;
01944         }
01945         add_timeout(&tv, do_info_request6, client, NULL, NULL);
01946 
01947         dhc6_retrans_advance(client);
01948 }
01949 
01950 /* do_confirm6() creates a Confirm packet and transmits it.  This function
01951  * is called on every timeout to (re)transmit.
01952  */
01953 void
01954 do_confirm6(void *input)
01955 {
01956         struct client_state *client;
01957         struct data_string ds;
01958         int send_ret;
01959         struct timeval tv;
01960 
01961         client = input;
01962 
01963         if (client->active_lease == NULL)
01964                 log_fatal("Impossible condition at %s:%d.", MDL);
01965 
01966         /* In section 17.1.3, it is said:
01967          *
01968          *   If the client receives no responses before the message
01969          *   transmission process terminates, as described in section 14,
01970          *   the client SHOULD continue to use any IP addresses, using the
01971          *   last known lifetimes for those addresses, and SHOULD continue
01972          *   to use any other previously obtained configuration parameters.
01973          *
01974          * So if confirm times out, we go active.
01975          *
01976          * XXX: Should we reduce all IA's t1 to 0, so that we renew and
01977          * stick there until we get a reply?
01978          */
01979 
01980         switch(check_timing6(client, DHCPV6_CONFIRM, "Confirm",
01981                              client->active_lease, &ds)) {
01982               case CHK_TIM_MRC_EXCEEDED:
01983               case CHK_TIM_MRD_EXCEEDED:
01984                 start_bound(client);
01985                 return;
01986               case CHK_TIM_ALLOC_FAILURE:
01987                 return;
01988               case CHK_TIM_SUCCESS:
01989                 break;
01990         }
01991 
01992         /* Fetch any configured 'sent' options (includes DUID') in wire format.
01993          */
01994         dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
01995                                     client->sent_options, &global_scope,
01996                                     &dhcpv6_universe);
01997 
01998         /* Append IA's. */
01999         if (wanted_ia_na &&
02000             dhc6_add_ia_na(client, &ds, client->active_lease,
02001                            DHCPV6_CONFIRM) != ISC_R_SUCCESS) {
02002                 data_string_forget(&ds, MDL);
02003                 return;
02004         }
02005         if (wanted_ia_ta &&
02006             dhc6_add_ia_ta(client, &ds, client->active_lease,
02007                            DHCPV6_CONFIRM) != ISC_R_SUCCESS) {
02008                 data_string_forget(&ds, MDL);
02009                 return;
02010         }
02011 
02012         /* Transmit and wait. */
02013 
02014         log_info("XMT: Confirm on %s, interval %ld0ms.",
02015                  client->name ? client->name : client->interface->name,
02016                  (long int)client->RT);
02017 
02018         send_ret = send_packet6(client->interface, ds.data, ds.len,
02019                                 &DHCPv6DestAddr);
02020         if (send_ret != ds.len) {
02021                 log_error("dhc6: sendpacket6() sent %d of %d bytes",
02022                           send_ret, ds.len);
02023         }
02024 
02025         data_string_forget(&ds, MDL);
02026 
02027         /* Wait RT */
02028         tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
02029         tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
02030         if (tv.tv_usec >= 1000000) {
02031                 tv.tv_sec += 1;
02032                 tv.tv_usec -= 1000000;
02033         }
02034         add_timeout(&tv, do_confirm6, client, NULL, NULL);
02035 
02036         dhc6_retrans_advance(client);
02037 }
02038 
02039 /*
02040  * Release addresses.
02041  */
02042 void
02043 start_release6(struct client_state *client)
02044 {
02045         /* Cancel any pending transmissions */
02046         cancel_timeout(do_confirm6, client);
02047         cancel_timeout(do_select6, client);
02048         cancel_timeout(do_refresh6, client);
02049         cancel_timeout(do_release6, client);
02050         cancel_timeout(do_decline6, client);
02051         client->state = S_STOPPED;
02052 
02053         /*
02054          * It is written:  "The client MUST NOT use any of the addresses it
02055          * is releasing as the source address in the Release message or in
02056          * any subsequently transmitted message."  So unconfigure now.
02057          */
02058         unconfigure6(client, "RELEASE6");
02059 
02060         /* Note this in the lease file. */
02061         if (client->active_lease == NULL)
02062                 return;
02063         client->active_lease->released = ISC_TRUE;
02064         write_client6_lease(client, client->active_lease, 0, 1);
02065 
02066         /* Set timers per RFC3315 section 18.1.6. */
02067         client->IRT = REL_TIMEOUT * 100;
02068         client->MRT = 0;
02069         client->MRC = REL_MAX_RC;
02070         client->MRD = 0;
02071 
02072         dhc6_retrans_init(client);
02073         client->v6_handler = reply_handler;
02074 
02075         do_release6(client);
02076 }
02077 /*
02078  * do_release6() creates a Release packet and transmits it.
02079  */
02080 static void
02081 do_release6(void *input)
02082 {
02083         struct client_state *client;
02084         struct data_string ds;
02085         int send_ret;
02086         struct timeval tv;
02087 
02088         client = input;
02089 
02090         if ((client->active_lease == NULL) || !active_prefix(client))
02091                 return;
02092 
02093         switch(check_timing6(client, DHCPV6_RELEASE, "Release", 
02094                              client->active_lease, &ds)) {
02095               case CHK_TIM_MRC_EXCEEDED:
02096               case CHK_TIM_ALLOC_FAILURE:
02097               case CHK_TIM_MRD_EXCEEDED:
02098                 goto release_done;
02099               case CHK_TIM_SUCCESS:
02100                 break;
02101         }
02102 
02103         /*
02104          * Don't use unicast as we don't know if we still have an
02105          * available address with enough scope.
02106          */
02107 
02108         dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
02109                                     client->sent_options, &global_scope,
02110                                     &dhcpv6_universe);
02111 
02112         /* Append IA's (but don't release temporary addresses). */
02113         if (wanted_ia_na &&
02114             dhc6_add_ia_na(client, &ds, client->active_lease,
02115                            DHCPV6_RELEASE) != ISC_R_SUCCESS) {
02116                 data_string_forget(&ds, MDL);
02117                 goto release_done;
02118         }
02119         if (wanted_ia_pd &&
02120             dhc6_add_ia_pd(client, &ds, client->active_lease,
02121                            DHCPV6_RELEASE) != ISC_R_SUCCESS) {
02122                 data_string_forget(&ds, MDL);
02123                 goto release_done;
02124         }
02125 
02126         /* Transmit and wait. */
02127         log_info("XMT: Release on %s, interval %ld0ms.",
02128                  client->name ? client->name : client->interface->name,
02129                  (long int)client->RT);
02130 
02131         send_ret = send_packet6(client->interface, ds.data, ds.len,
02132                                 &DHCPv6DestAddr);
02133         if (send_ret != ds.len) {
02134                 log_error("dhc6: sendpacket6() sent %d of %d bytes",
02135                           send_ret, ds.len);
02136         }
02137 
02138         data_string_forget(&ds, MDL);
02139 
02140         /* Wait RT */
02141         tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
02142         tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
02143         if (tv.tv_usec >= 1000000) {
02144                 tv.tv_sec += 1;
02145                 tv.tv_usec -= 1000000;
02146         }
02147         add_timeout(&tv, do_release6, client, NULL, NULL);
02148         dhc6_retrans_advance(client);
02149         return;
02150 
02151       release_done:
02152         dhc6_lease_destroy(&client->active_lease, MDL);
02153         client->active_lease = NULL;
02154         if (stopping_finished())
02155                 exit(0);
02156 }
02157 
02158 /* status_log() just puts a status code into displayable form and logs it
02159  * to info level.
02160  */
02161 static void
02162 status_log(int code, const char *scope, const char *additional, int len)
02163 {
02164         const char *msg = NULL;
02165 
02166         switch(code) {
02167               case STATUS_Success:
02168                 msg = "Success";
02169                 break;
02170 
02171               case STATUS_UnspecFail:
02172                 msg = "UnspecFail";
02173                 break;
02174 
02175               case STATUS_NoAddrsAvail:
02176                 msg = "NoAddrsAvail";
02177                 break;
02178 
02179               case STATUS_NoBinding:
02180                 msg = "NoBinding";
02181                 break;
02182 
02183               case STATUS_NotOnLink:
02184                 msg = "NotOnLink";
02185                 break;
02186 
02187               case STATUS_UseMulticast:
02188                 msg = "UseMulticast";
02189                 break;
02190 
02191               case STATUS_NoPrefixAvail:
02192                 msg = "NoPrefixAvail";
02193                 break;
02194 
02195               default:
02196                 msg = "UNKNOWN";
02197                 break;
02198         }
02199 
02200         if (len > 0)
02201                 log_info("%s status code %s: %s", scope, msg,
02202                          print_hex_1(len,
02203                                      (const unsigned char *)additional, 50));
02204         else
02205                 log_info("%s status code %s.", scope, msg);
02206 }
02207 
02208 /* Acquire a status code.
02209  */
02210 static isc_result_t
02211 dhc6_get_status_code(struct option_state *options, unsigned *code,
02212                      struct data_string *msg)
02213 {
02214         struct option_cache *oc;
02215         struct data_string ds;
02216         isc_result_t rval = ISC_R_SUCCESS;
02217 
02218         if ((options == NULL) || (code == NULL))
02219                 return DHCP_R_INVALIDARG;
02220 
02221         if ((msg != NULL) && (msg->len != 0))
02222                 return DHCP_R_INVALIDARG;
02223 
02224         memset(&ds, 0, sizeof(ds));
02225 
02226         /* Assume success if there is no option. */
02227         *code = STATUS_Success;
02228 
02229         oc = lookup_option(&dhcpv6_universe, options, D6O_STATUS_CODE);
02230         if ((oc != NULL) &&
02231             evaluate_option_cache(&ds, NULL, NULL, NULL, options,
02232                                   NULL, &global_scope, oc, MDL)) {
02233                 if (ds.len < 2) {
02234                         log_error("Invalid status code length %d.", ds.len);
02235                         rval = DHCP_R_FORMERR;
02236                 } else
02237                         *code = getUShort(ds.data);
02238 
02239                 if ((msg != NULL) && (ds.len > 2)) {
02240                         data_string_copy(msg, &ds, MDL);
02241                         msg->data += 2;
02242                         msg->len -= 2;
02243                 }
02244 
02245                 data_string_forget(&ds, MDL);
02246                 return rval;
02247         }
02248 
02249         return ISC_R_NOTFOUND;
02250 }
02251 
02252 /* Look at status codes in an advertise, and reform the return value.
02253  */
02254 static isc_result_t
02255 dhc6_check_status(isc_result_t rval, struct option_state *options,
02256                   const char *scope, unsigned *code)
02257 {
02258         struct data_string msg;
02259         isc_result_t status;
02260 
02261         if ((scope == NULL) || (code == NULL))
02262                 return DHCP_R_INVALIDARG;
02263 
02264         /* If we don't find a code, we assume success. */
02265         *code = STATUS_Success;
02266 
02267         /* If there is no options cache, then there is no code. */
02268         if (options != NULL) {
02269                 memset(&msg, 0, sizeof(msg));
02270                 status = dhc6_get_status_code(options, code, &msg);
02271 
02272                 if (status == ISC_R_SUCCESS) {
02273                         status_log(*code, scope, (char *)msg.data, msg.len);
02274                         data_string_forget(&msg, MDL);
02275 
02276                         if (*code != STATUS_Success)
02277                                 rval = ISC_R_FAILURE;
02278 
02279                 } else if (status != ISC_R_NOTFOUND)
02280                         rval = status;
02281         }
02282 
02283         return rval;
02284 }
02285 
02286 /* Look in the packet, any IA's, and any IAADDR's within those IA's to find
02287  * status code options that are not SUCCESS.
02288  */
02289 static isc_result_t
02290 dhc6_check_advertise(struct dhc6_lease *lease)
02291 {
02292         struct dhc6_ia *ia;
02293         struct dhc6_addr *addr;
02294         isc_result_t rval = ISC_R_SUCCESS;
02295         int have_addrs = ISC_FALSE;
02296         unsigned code;
02297         const char *scope;
02298 
02299         rval = dhc6_check_status(rval, lease->options, "message", &code);
02300 
02301         for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
02302                 switch (ia->ia_type) {
02303                         case D6O_IA_NA:
02304                                 scope = "IA_NA";
02305                                 break;
02306                         case D6O_IA_TA:
02307                                 scope = "IA_TA";
02308                                 break;
02309                         case D6O_IA_PD:
02310                                 scope = "IA_PD";
02311                                 break;
02312                         default:
02313                                 log_error("dhc6_check_advertise: no type.");
02314                                 return ISC_R_FAILURE;
02315                 }
02316                 rval = dhc6_check_status(rval, ia->options, scope, &code);
02317 
02318                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
02319                         if (ia->ia_type != D6O_IA_PD)
02320                                 scope = "IAADDR";
02321                         else
02322                                 scope = "IAPREFIX";
02323                         rval = dhc6_check_status(rval, addr->options,
02324                                                  scope, &code);
02325                         have_addrs = ISC_TRUE;
02326                 }
02327         }
02328 
02329         if (have_addrs != ISC_TRUE)
02330                 rval = ISC_R_ADDRNOTAVAIL;
02331 
02332         return rval;
02333 }
02334 
02335 /* status code <-> action matrix for the client in INIT state
02336  * (rapid/commit).  Returns always false as no action is defined.
02337  */
02338 static isc_boolean_t
02339 dhc6_init_action(struct client_state *client, isc_result_t *rvalp,
02340                  unsigned code)
02341 {
02342         if (rvalp == NULL)
02343                 log_fatal("Impossible condition at %s:%d.", MDL);
02344 
02345         if (client == NULL) {
02346                 *rvalp = DHCP_R_INVALIDARG;
02347                 return ISC_FALSE;
02348         }
02349 
02350         if (*rvalp == ISC_R_SUCCESS)
02351                 return ISC_FALSE;
02352 
02353         /* No possible action in any case... */
02354         return ISC_FALSE;
02355 }
02356 
02357 /* status code <-> action matrix for the client in SELECT state
02358  * (request/reply).  Returns true if action was taken (and the
02359  * packet should be ignored), or false if no action was taken.
02360  */
02361 static isc_boolean_t
02362 dhc6_select_action(struct client_state *client, isc_result_t *rvalp,
02363                    unsigned code)
02364 {
02365         struct dhc6_lease *lease;
02366         isc_result_t rval;
02367 
02368         if (rvalp == NULL)
02369                 log_fatal("Impossible condition at %s:%d.", MDL);
02370 
02371         if (client == NULL) {
02372                 *rvalp = DHCP_R_INVALIDARG;
02373                 return ISC_FALSE;
02374         }
02375         rval = *rvalp;
02376 
02377         if (rval == ISC_R_SUCCESS)
02378                 return ISC_FALSE;
02379 
02380         switch (code) {
02381                 /* We may have an earlier failure status code (so no
02382                  * success rval), and a success code now.  This
02383                  * doesn't upgrade the rval to success, but it does
02384                  * mean we take no action here.
02385                  */
02386               case STATUS_Success:
02387                 /* Gimpy server, or possibly an attacker. */
02388               case STATUS_NoBinding:
02389               case STATUS_UseMulticast:
02390                 /* Take no action. */
02391                 return ISC_FALSE;
02392 
02393                 /* If the server can't deal with us, either try the
02394                  * next advertised server, or continue retrying if there
02395                  * weren't any.
02396                  */
02397               default:
02398               case STATUS_UnspecFail:
02399                 if (client->advertised_leases != NULL) {
02400                         dhc6_lease_destroy(&client->selected_lease, MDL);
02401                         client->selected_lease = NULL;
02402 
02403                         start_selecting6(client);
02404 
02405                         break;
02406                 } else /* Take no action - continue to retry. */
02407                         return ISC_FALSE;
02408 
02409                 /* If the server has no addresses, try other servers if
02410                  * we got some, otherwise go to INIT to hope for more
02411                  * servers.
02412                  */
02413               case STATUS_NoAddrsAvail:
02414               case STATUS_NoPrefixAvail:
02415                 if (client->state == S_REBOOTING)
02416                         return ISC_FALSE;
02417 
02418                 if (client->selected_lease == NULL)
02419                         log_fatal("Impossible case at %s:%d.", MDL);
02420 
02421                 dhc6_lease_destroy(&client->selected_lease, MDL);
02422                 client->selected_lease = NULL;
02423 
02424                 if (client->advertised_leases != NULL)
02425                         start_selecting6(client);
02426                 else
02427                         start_init6(client);
02428 
02429                 break;
02430 
02431                 /* If we got a NotOnLink from a Confirm, then we're not
02432                  * on link.  Kill the old-active binding and start over.
02433                  *
02434                  * If we got a NotOnLink from our Request, something weird
02435                  * happened.  Start over from scratch anyway.
02436                  */
02437               case STATUS_NotOnLink:
02438                 if (client->state == S_REBOOTING) {
02439                         if (client->active_lease == NULL)
02440                                 log_fatal("Impossible case at %s:%d.", MDL);
02441 
02442                         dhc6_lease_destroy(&client->active_lease, MDL);
02443                 } else {
02444                         if (client->selected_lease == NULL)
02445                                 log_fatal("Impossible case at %s:%d.", MDL);
02446 
02447                         dhc6_lease_destroy(&client->selected_lease, MDL);
02448                         client->selected_lease = NULL;
02449 
02450                         while (client->advertised_leases != NULL) {
02451                                 lease = client->advertised_leases;
02452                                 client->advertised_leases = lease->next;
02453 
02454                                 dhc6_lease_destroy(&lease, MDL);
02455                         }
02456                 }
02457 
02458                 start_init6(client);
02459                 break;
02460         }
02461 
02462         return ISC_TRUE;
02463 }
02464 
02465 static void
02466 dhc6_withdraw_lease(struct client_state *client)
02467 {
02468         struct dhc6_ia *ia;
02469         struct dhc6_addr *addr;
02470 
02471         if ((client == NULL) || (client->active_lease == NULL))
02472                 return;
02473 
02474         for (ia = client->active_lease->bindings ; ia != NULL ;
02475              ia = ia->next) {
02476                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
02477                         addr->max_life = addr->preferred_life = 0;
02478                 }
02479         }
02480 
02481         /* Perform expiry. */
02482         do_expire(client);
02483 }
02484 
02485 /* status code <-> action matrix for the client in BOUND state
02486  * (request/reply).  Returns true if action was taken (and the
02487  * packet should be ignored), or false if no action was taken.
02488  */
02489 static isc_boolean_t
02490 dhc6_reply_action(struct client_state *client, isc_result_t *rvalp,
02491                   unsigned code)
02492 {
02493         isc_result_t rval;
02494 
02495         if (rvalp == NULL)
02496                 log_fatal("Impossible condition at %s:%d.", MDL);
02497 
02498         if (client == NULL) {
02499                 *rvalp = DHCP_R_INVALIDARG;
02500                 return ISC_FALSE;
02501         }
02502         rval = *rvalp;
02503 
02504         if (rval == ISC_R_SUCCESS)
02505                 return ISC_FALSE;
02506 
02507         switch (code) {
02508                 /* It's possible an earlier status code set rval to a failure
02509                  * code, and we've encountered a later success.
02510                  */
02511               case STATUS_Success:
02512                 /* In "refreshes" (where we get replies), we probably
02513                  * still have a valid lease.  So "take no action" and
02514                  * the upper levels will keep retrying until the lease
02515                  * expires (or we rebind).
02516                  */
02517               case STATUS_UnspecFail:
02518                 /* For unknown codes...it's a soft (retryable) error. */
02519               default:
02520                 return ISC_FALSE;
02521 
02522                 /* The server is telling us to use a multicast address, so
02523                  * we have to delete the unicast option from the active
02524                  * lease, then allow retransmission to occur normally.
02525                  * (XXX: It might be preferable in this case to retransmit
02526                  * sooner than the current interval, but for now we don't.)
02527                  */
02528               case STATUS_UseMulticast:
02529                 if (client->active_lease != NULL)
02530                         delete_option(&dhcp_universe,
02531                                       client->active_lease->options,
02532                                       D6O_UNICAST);
02533                 return ISC_FALSE;
02534 
02535                 /* "When the client receives a NotOnLink status from the
02536                  *  server in response to a Request, the client can either
02537                  *  re-issue the Request without specifying any addresses
02538                  *  or restart the DHCP server discovery process."
02539                  *
02540                  * This is strange.  If competing server evaluation is
02541                  * useful (and therefore in the protocol), then why would
02542                  * a client's first reaction be to request from the same
02543                  * server on a different link?  Surely you'd want to
02544                  * re-evaluate your server selection.
02545                  *
02546                  * Well, I guess that's the answer.
02547                  */
02548               case STATUS_NotOnLink:
02549                 /* In this case, we need to rescind all current active
02550                  * bindings (just 'expire' them all normally, if early).
02551                  * They're no use to us on the wrong link.  Then head back
02552                  * to init, redo server selection and get new addresses.
02553                  */
02554                 dhc6_withdraw_lease(client);
02555                 break;
02556 
02557                 /* "If the status code is NoAddrsAvail, the client has
02558                  *  received no usable addresses in the IA and may choose
02559                  *  to try obtaining addresses for the IA from another
02560                  *  server."
02561                  */
02562               case STATUS_NoAddrsAvail:
02563               case STATUS_NoPrefixAvail:
02564                 /* Head back to init, keeping any active bindings (!). */
02565                 start_init6(client);
02566                 break;
02567 
02568                 /* -  sends a Request message if the IA contained a Status
02569                  *    Code option with the NoBinding status (and does not
02570                  *    send any additional Renew/Rebind messages)
02571                  */
02572               case STATUS_NoBinding:
02573                 if (client->advertised_leases != NULL)
02574                         log_fatal("Impossible condition at %s:%d.", MDL);
02575 
02576                 client->advertised_leases =
02577                                 dhc6_dup_lease(client->active_lease, MDL);
02578                 start_selecting6(client);
02579                 break;
02580         }
02581 
02582         return ISC_TRUE;
02583 }
02584 
02585 /* status code <-> action matrix for the client in STOPPED state
02586  * (release/decline).  Returns true if action was taken (and the
02587  * packet should be ignored), or false if no action was taken.
02588  * NoBinding is translated into Success.
02589  */
02590 static isc_boolean_t
02591 dhc6_stop_action(struct client_state *client, isc_result_t *rvalp,
02592                   unsigned code)
02593 {
02594         isc_result_t rval;
02595 
02596         if (rvalp == NULL)
02597                 log_fatal("Impossible condition at %s:%d.", MDL);
02598 
02599         if (client == NULL) {
02600                 *rvalp = DHCP_R_INVALIDARG;
02601                 return ISC_FALSE;
02602         }
02603         rval = *rvalp;
02604 
02605         if (rval == ISC_R_SUCCESS)
02606                 return ISC_FALSE;
02607 
02608         switch (code) {
02609                 /* It's possible an earlier status code set rval to a failure
02610                  * code, and we've encountered a later success.
02611                  */
02612               case STATUS_Success:
02613                 /* For unknown codes...it's a soft (retryable) error. */
02614               case STATUS_UnspecFail:
02615               default:
02616                 return ISC_FALSE;
02617 
02618                 /* NoBinding is not an error */
02619               case STATUS_NoBinding:
02620                 if (rval == ISC_R_FAILURE)
02621                         *rvalp = ISC_R_SUCCESS;
02622                 return ISC_FALSE;
02623 
02624                 /* Should not happen */
02625               case STATUS_NoAddrsAvail:
02626               case STATUS_NoPrefixAvail:
02627                 break;
02628 
02629                 /* Give up on it */
02630               case STATUS_NotOnLink:
02631                 break;
02632 
02633                 /* The server is telling us to use a multicast address, so
02634                  * we have to delete the unicast option from the active
02635                  * lease, then allow retransmission to occur normally.
02636                  * (XXX: It might be preferable in this case to retransmit
02637                  * sooner than the current interval, but for now we don't.)
02638                  */
02639               case STATUS_UseMulticast:
02640                 if (client->active_lease != NULL)
02641                         delete_option(&dhcp_universe,
02642                                       client->active_lease->options,
02643                                       D6O_UNICAST);
02644                 return ISC_FALSE;
02645         }
02646 
02647         return ISC_TRUE;
02648 }
02649 
02650 /* Look at a new and old lease, and make sure the new information is not
02651  * losing us any state.
02652  */
02653 static isc_result_t
02654 dhc6_check_reply(struct client_state *client, struct dhc6_lease *new)
02655 {
02656         isc_boolean_t (*action)(struct client_state *,
02657                                 isc_result_t *, unsigned);
02658         struct dhc6_ia *ia;
02659         struct dhc6_addr *addr;
02660         isc_result_t rval = ISC_R_SUCCESS;
02661         unsigned code;
02662         const char *scope;
02663         int nscore, sscore;
02664 
02665         if ((client == NULL) || (new == NULL))
02666                 return DHCP_R_INVALIDARG;
02667 
02668         switch (client->state) {
02669               case S_INIT:
02670                 action = dhc6_init_action;
02671                 break;
02672 
02673               case S_SELECTING:
02674               case S_REBOOTING:
02675                 action = dhc6_select_action;
02676                 break;
02677 
02678               case S_RENEWING:
02679               case S_REBINDING:
02680                 action = dhc6_reply_action;
02681                 break;
02682 
02683               case S_STOPPED:
02684               case S_DECLINED:
02685                 action = dhc6_stop_action;
02686                 break;
02687 
02688               default:
02689                 log_fatal("Impossible condition at %s:%d.", MDL);
02690                 return ISC_R_CANCELED;
02691         }
02692 
02693         /* If there is a code to extract, and if there is some
02694          * action to take based on that code, then take the action
02695          * and do not continue.
02696          */
02697         rval = dhc6_check_status(rval, new->options, "message", &code);
02698         if (action(client, &rval, code))
02699                 return ISC_R_CANCELED;
02700 
02701         for (ia = new->bindings ; ia != NULL ; ia = ia->next) {
02702                 switch (ia->ia_type) {
02703                         case D6O_IA_NA:
02704                                 scope = "IA_NA";
02705                                 break;
02706                         case D6O_IA_TA:
02707                                 scope = "IA_TA";
02708                                 break;
02709                         case D6O_IA_PD:
02710                                 scope = "IA_PD";
02711                                 break;
02712                         default:
02713                                 log_error("dhc6_check_reply: no type.");
02714                                 return DHCP_R_INVALIDARG;
02715                 }
02716                 rval = dhc6_check_status(rval, ia->options,
02717                                          scope, &code);
02718                 if (action(client, &rval, code))
02719                         return ISC_R_CANCELED;
02720 
02721                 for (addr = ia->addrs ; addr != NULL ;
02722                      addr = addr->next) {
02723                         if (ia->ia_type != D6O_IA_PD)
02724                                 scope = "IAADDR";
02725                         else
02726                                 scope = "IAPREFIX";
02727                         rval = dhc6_check_status(rval, addr->options,
02728                                                  scope, &code);
02729                         if (action(client, &rval, code))
02730                                 return ISC_R_CANCELED;
02731                 }
02732         }
02733 
02734         /* A Confirm->Reply is unsuitable for comparison to the old lease. */
02735         if (client->state == S_REBOOTING)
02736                 return rval;
02737 
02738         /* No old lease in rapid-commit. */
02739         if (client->state == S_INIT)
02740                 return rval;
02741 
02742         switch (client->state) {
02743               case S_SELECTING:
02744                 /* Compare the new lease with the selected lease to make
02745                  * sure there is no risky business.
02746                  */
02747                 nscore = dhc6_score_lease(client, new);
02748                 sscore = dhc6_score_lease(client, client->selected_lease);
02749                 if ((client->advertised_leases != NULL) &&
02750                     (nscore < (sscore / 2))) {
02751                         /* XXX: An attacker might reply this way to make
02752                          * XXX: sure we latch onto their configuration.
02753                          * XXX: We might want to ignore the packet and
02754                          * XXX: schedule re-selection at the next timeout?
02755                          */
02756                         log_error("PRC: BAIT AND SWITCH detected.  Score of "
02757                                   "supplied lease (%d) is substantially "
02758                                   "smaller than the advertised score (%d).  "
02759                                   "Trying other servers.",
02760                                   nscore, sscore);
02761 
02762                         dhc6_lease_destroy(&client->selected_lease, MDL);
02763                         client->selected_lease = NULL;
02764 
02765                         start_selecting6(client);
02766 
02767                         return ISC_R_CANCELED;
02768                 }
02769                 break;
02770 
02771               case S_RENEWING:
02772               case S_REBINDING:
02773                 /* This leaves one RFC3315 status check unimplemented:
02774                  *
02775                  * -  sends a Renew/Rebind if the IA is not in the Reply
02776                  *    message
02777                  *
02778                  * We rely on the scheduling system to note that the IA has
02779                  * not left Renewal/Rebinding/whatever since it still carries
02780                  * old times from the last successful binding.  So this is
02781                  * implemented actually, just not explicitly.
02782                  */
02783                 break;
02784 
02785               case S_STOPPED:
02786               case S_DECLINED:
02787                 /* Nothing critical to do at this stage. */
02788                 break;
02789 
02790               default:
02791                 log_fatal("REALLY impossible condition at %s:%d.", MDL);
02792                 return ISC_R_CANCELED;
02793         }
02794 
02795         return rval;
02796 }
02797 
02798 /* While in init state, we only collect advertisements.  If there happens
02799  * to be an advertisement with a preference option of 255, that's an
02800  * automatic exit.  Otherwise, we collect advertisements until our timeout
02801  * expires (client->RT).
02802  */
02803 void
02804 init_handler(struct packet *packet, struct client_state *client)
02805 {
02806         struct dhc6_lease *lease;
02807 
02808         /* In INIT state, we send solicits, we only expect to get
02809          * advertises (rapid commit has its own handler).
02810          */
02811         if (packet->dhcpv6_msg_type != DHCPV6_ADVERTISE)
02812                 return;
02813 
02814         /* RFC3315 section 15.3 validation (same as 15.10 since we
02815          * always include a client id).
02816          */
02817         if (!valid_reply(packet, client)) {
02818                 log_error("Invalid Advertise - rejecting.");
02819                 return;
02820         }
02821 
02822         lease = dhc6_leaseify(packet);
02823 
02824         if (dhc6_check_advertise(lease) != ISC_R_SUCCESS) {
02825                 log_debug("PRC: Lease failed to satisfy.");
02826                 dhc6_lease_destroy(&lease, MDL);
02827                 return;
02828         }
02829 
02830         insert_lease(&client->advertised_leases, lease);
02831 
02832         /* According to RFC3315 section 17.1.2, the client MUST wait for
02833          * the first RT before selecting a lease.  But on the 400th RT,
02834          * we dont' want to wait the full timeout if we finally get an
02835          * advertise.  We could probably wait a second, but ohwell,
02836          * RFC3315 doesn't say so.
02837          *
02838          * If the lease is highest possible preference, 255, RFC3315 claims
02839          * we should continue immediately even on the first RT.  We probably
02840          * should not if the advertise contains less than one IA and address.
02841          */
02842         if ((client->txcount > 1) ||
02843             ((lease->pref == 255) &&
02844             (dhc6_score_lease(client, lease) > 150))) {
02845                 log_debug("RCV:  Advertisement immediately selected.");
02846                 cancel_timeout(do_init6, client);
02847                 start_selecting6(client);
02848         } else
02849                 log_debug("RCV:  Advertisement recorded.");
02850 }
02851 
02852 /* info_request_handler() accepts a Reply to an Info-request.
02853  */
02854 void
02855 info_request_handler(struct packet *packet, struct client_state *client)
02856 {
02857         isc_result_t check_status;
02858         unsigned code;
02859 
02860         if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
02861                 return;
02862 
02863         /* RFC3315 section 15.10 validation (same as 15.3 since we
02864          * always include a client id).
02865          */
02866         if (!valid_reply(packet, client)) {
02867                 log_error("Invalid Reply - rejecting.");
02868                 return;
02869         }
02870 
02871         check_status = dhc6_check_status(ISC_R_SUCCESS, packet->options,
02872                                          "message", &code);
02873         if (check_status != ISC_R_SUCCESS) {
02874                 /* If no action was taken, but there is an error, then
02875                  * we wait for a retransmission.
02876                  */
02877                 if (check_status != ISC_R_CANCELED)
02878                         return;
02879         }
02880 
02881         /* We're done retransmitting at this point. */
02882         cancel_timeout(do_info_request6, client);
02883 
02884         /* Action was taken, so now that we've torn down our scheduled
02885          * retransmissions, return.
02886          */
02887         if (check_status == ISC_R_CANCELED)
02888                 return;
02889 
02890         /* Cleanup if a previous attempt to go bound failed. */
02891         if (client->old_lease != NULL) {
02892                 dhc6_lease_destroy(&client->old_lease, MDL);
02893                 client->old_lease = NULL;
02894         }
02895 
02896         /* Cache options in the active_lease. */
02897         if (client->active_lease != NULL)
02898                 client->old_lease = client->active_lease;
02899         client->active_lease = dmalloc(sizeof(struct dhc6_lease), MDL);
02900         if (client->active_lease == NULL)
02901                 log_fatal("Out of memory for v6 lease structure.");
02902         option_state_reference(&client->active_lease->options,
02903                                packet->options, MDL);
02904 
02905         start_informed(client);
02906 }
02907 
02908 /* Specific version of init_handler() for rapid-commit.
02909  */
02910 void
02911 rapid_commit_handler(struct packet *packet, struct client_state *client)
02912 {
02913         struct dhc6_lease *lease;
02914         isc_result_t check_status;
02915 
02916         /* On ADVERTISE just fall back to the init_handler().
02917          */
02918         if (packet->dhcpv6_msg_type == DHCPV6_ADVERTISE) {
02919                 init_handler(packet, client);
02920                 return;
02921         } else if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
02922                 return;
02923 
02924         /* RFC3315 section 15.10 validation (same as 15.3 since we
02925          * always include a client id).
02926          */
02927         if (!valid_reply(packet, client)) {
02928                 log_error("Invalid Reply - rejecting.");
02929                 return;
02930         }
02931 
02932         /* A rapid-commit option MUST be here. */
02933         if (lookup_option(&dhcpv6_universe, packet->options,
02934                           D6O_RAPID_COMMIT) == 0) {
02935                 log_error("Reply without Rapid-Commit - rejecting.");
02936                 return;
02937         }
02938 
02939         lease = dhc6_leaseify(packet);
02940 
02941         /* This is an out of memory condition...hopefully a temporary
02942          * problem.  Returning now makes us try to retransmit later.
02943          */
02944         if (lease == NULL)
02945                 return;
02946 
02947         check_status = dhc6_check_reply(client, lease);
02948         if (check_status != ISC_R_SUCCESS) {
02949                 dhc6_lease_destroy(&lease, MDL);
02950                 return;
02951         }
02952 
02953         /* Jump to the selecting state. */
02954         cancel_timeout(do_init6, client);
02955         client->state = S_SELECTING;
02956 
02957         /* Merge any bindings in the active lease (if there is one) into
02958          * the new active lease.
02959          */
02960         dhc6_merge_lease(client->active_lease, lease);
02961 
02962         /* Cleanup if a previous attempt to go bound failed. */
02963         if (client->old_lease != NULL) {
02964                 dhc6_lease_destroy(&client->old_lease, MDL);
02965                 client->old_lease = NULL;
02966         }
02967 
02968         /* Make this lease active and BIND to it. */
02969         if (client->active_lease != NULL)
02970                 client->old_lease = client->active_lease;
02971         client->active_lease = lease;
02972 
02973         /* We're done with the ADVERTISEd leases, if any. */
02974         while(client->advertised_leases != NULL) {
02975                 lease = client->advertised_leases;
02976                 client->advertised_leases = lease->next;
02977 
02978                 dhc6_lease_destroy(&lease, MDL);
02979         }
02980 
02981         start_bound(client);
02982 }
02983 
02984 /* Find the 'best' lease in the cache of advertised leases (usually).  From
02985  * RFC3315 Section 17.1.3:
02986  *
02987  *   Upon receipt of one or more valid Advertise messages, the client
02988  *   selects one or more Advertise messages based upon the following
02989  *   criteria.
02990  *
02991  *   -  Those Advertise messages with the highest server preference value
02992  *      are preferred over all other Advertise messages.
02993  *
02994  *   -  Within a group of Advertise messages with the same server
02995  *      preference value, a client MAY select those servers whose
02996  *      Advertise messages advertise information of interest to the
02997  *      client.  For example, the client may choose a server that returned
02998  *      an advertisement with configuration options of interest to the
02999  *      client.
03000  *
03001  *   -  The client MAY choose a less-preferred server if that server has a
03002  *      better set of advertised parameters, such as the available
03003  *      addresses advertised in IAs.
03004  *
03005  * Note that the first and third contradict each other.  The third should
03006  * probably be taken to mean that the client should prefer answers that
03007  * offer bindings, even if that violates the preference rule.
03008  *
03009  * The above also isn't deterministic where there are ties.  So the final
03010  * tiebreaker we add, if all other values are equal, is to compare the
03011  * server identifiers and to select the numerically lower one.
03012  */
03013 static struct dhc6_lease *
03014 dhc6_best_lease(struct client_state *client, struct dhc6_lease **head)
03015 {
03016         struct dhc6_lease **rpos, *rval, **candp, *cand;
03017         int cscore, rscore;
03018 
03019         if (head == NULL || *head == NULL)
03020                 return NULL;
03021 
03022         rpos = head;
03023         rval = *rpos;
03024         rscore = dhc6_score_lease(client, rval);
03025         candp = &rval->next;
03026         cand = *candp;
03027 
03028         log_debug("PRC: Considering best lease.");
03029         log_debug("PRC:  X-- Initial candidate %s (s: %d, p: %u).",
03030                   print_hex_1(rval->server_id.len,
03031                               rval->server_id.data, 48),
03032                   rscore, (unsigned)rval->pref);
03033 
03034         for (; cand != NULL ; candp = &cand->next, cand = *candp) {
03035                 cscore = dhc6_score_lease(client, cand);
03036 
03037                 log_debug("PRC:  X-- Candidate %s (s: %d, p: %u).",
03038                           print_hex_1(cand->server_id.len,
03039                                       cand->server_id.data, 48),
03040                           cscore, (unsigned)cand->pref);
03041 
03042                 /* Above you'll find quoted RFC3315 Section 17.1.3.
03043                  *
03044                  * The third clause tells us to give up on leases that
03045                  * have no bindings even if their preference is better.
03046                  * So where our 'selected' lease's score is less than 150
03047                  * (1 ia + 1 addr), choose any candidate >= 150.
03048                  *
03049                  * The first clause tells us to make preference the primary
03050                  * deciding factor.  So if it's lower, reject, if it's
03051                  * higher, select.
03052                  *
03053                  * The second clause tells us where the preference is
03054                  * equal, we should use 'our judgement' of what we like
03055                  * to see in an advertisement primarily.
03056                  *
03057                  * But there can still be a tie.  To make this deterministic,
03058                  * we compare the server identifiers and select the binary
03059                  * lowest.
03060                  *
03061                  * Since server id's are unique in this list, there is
03062                  * no further tie to break.
03063                  */
03064                 if ((rscore < 150) && (cscore >= 150)) {
03065                         log_debug("PRC:  | X-- Selected, has bindings.");
03066                 } else if (cand->pref < rval->pref) {
03067                         log_debug("PRC:  | X-- Rejected, lower preference.");
03068                         continue;
03069                 } else if (cand->pref > rval->pref) {
03070                         log_debug("PRC:  | X-- Selected, higher preference.");
03071                 } else if (cscore > rscore) {
03072                         log_debug("PRC:  | X-- Selected, equal preference, "
03073                                   "higher score.");
03074                 } else if (cscore < rscore) {
03075                         log_debug("PRC:  | X-- Rejected, equal preference, "
03076                                   "lower score.");
03077                         continue;
03078                 } else if ((cand->server_id.len < rval->server_id.len) ||
03079                            ((cand->server_id.len == rval->server_id.len) &&
03080                             (memcmp(cand->server_id.data,
03081                                     rval->server_id.data,
03082                                     cand->server_id.len) < 0))) {
03083                         log_debug("PRC:  | X-- Selected, equal preference, "
03084                                   "equal score, binary lesser server ID.");
03085                 } else {
03086                         log_debug("PRC:  | X-- Rejected, equal preference, "
03087                                   "equal score, binary greater server ID.");
03088                         continue;
03089                 }
03090 
03091                 rpos = candp;
03092                 rval = cand;
03093                 rscore = cscore;
03094         }
03095 
03096         /* Remove the selected lease from the chain. */
03097         *rpos = rval->next;
03098 
03099         return rval;
03100 }
03101 
03102 /* Select a lease out of the advertised leases and setup state to try and
03103  * acquire that lease.
03104  */
03105 void
03106 start_selecting6(struct client_state *client)
03107 {
03108         struct dhc6_lease *lease;
03109 
03110         if (client->advertised_leases == NULL) {
03111                 log_error("Can not enter DHCPv6 SELECTING state with no "
03112                           "leases to select from!");
03113                 return;
03114         }
03115 
03116         log_debug("PRC: Selecting best advertised lease.");
03117         client->state = S_SELECTING;
03118 
03119         lease = dhc6_best_lease(client, &client->advertised_leases);
03120 
03121         if (lease == NULL)
03122                 log_fatal("Impossible error at %s:%d.", MDL);
03123 
03124         client->selected_lease = lease;
03125 
03126         /* Set timers per RFC3315 section 18.1.1. */
03127         client->IRT = REQ_TIMEOUT * 100;
03128         client->MRT = REQ_MAX_RT * 100;
03129         client->MRC = REQ_MAX_RC;
03130         client->MRD = 0;
03131 
03132         dhc6_retrans_init(client);
03133 
03134         client->v6_handler = reply_handler;
03135 
03136         /* ("re")transmit the first packet. */
03137         do_select6(client);
03138 }
03139 
03140 /* Transmit a Request to select a lease offered in Advertisements.  In
03141  * the event of failure, either move on to the next-best advertised lease,
03142  * or head back to INIT state if there are none.
03143  */
03144 void
03145 do_select6(void *input)
03146 {
03147         struct client_state *client;
03148         struct dhc6_lease *lease;
03149         struct data_string ds;
03150         struct timeval tv;
03151         int send_ret;
03152 
03153         client = input;
03154 
03155         /* 'lease' is fewer characters to type. */
03156         lease = client->selected_lease;
03157         if (lease == NULL || lease->bindings == NULL) {
03158                 log_error("Illegal to attempt selection without selecting "
03159                           "a lease.");
03160                 return;
03161         }
03162 
03163         switch(check_timing6(client, DHCPV6_REQUEST, "Request", lease, &ds)) {
03164               case CHK_TIM_MRC_EXCEEDED:
03165               case CHK_TIM_MRD_EXCEEDED:
03166                 log_debug("PRC: Lease %s failed.",
03167                           print_hex_1(lease->server_id.len,
03168                                       lease->server_id.data, 56));
03169 
03170                 /* Get rid of the lease that timed/counted out. */
03171                 dhc6_lease_destroy(&lease, MDL);
03172                 client->selected_lease = NULL;
03173 
03174                 /* If there are more leases great.  If not, get more. */
03175                 if (client->advertised_leases != NULL)
03176                         start_selecting6(client);
03177                 else
03178                         start_init6(client);
03179                 return;
03180               case CHK_TIM_ALLOC_FAILURE:
03181                 return;
03182               case CHK_TIM_SUCCESS:
03183                 break;
03184         }
03185 
03186         /* Now make a packet that looks suspiciously like the one we
03187          * got from the server.  But different.
03188          *
03189          * XXX: I guess IAID is supposed to be something the client
03190          * indicates and uses as a key to its internal state.  It is
03191          * kind of odd to ask the server for IA's whose IAID the client
03192          * did not manufacture.  We first need a formal dhclient.conf
03193          * construct for the iaid, then we can delve into this matter
03194          * more properly.  In the time being, this will work.
03195          */
03196 
03197         /* Fetch any configured 'sent' options (includes DUID) in wire format.
03198          */
03199         dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
03200                                     NULL, client->sent_options, &global_scope,
03201                                     &dhcpv6_universe);
03202 
03203         /* Now append any IA's, and within them any IAADDR/IAPREFIXs. */
03204         if (wanted_ia_na &&
03205             dhc6_add_ia_na(client, &ds, lease,
03206                            DHCPV6_REQUEST) != ISC_R_SUCCESS) {
03207                 data_string_forget(&ds, MDL);
03208                 return;
03209         }
03210         if (wanted_ia_ta &&
03211             dhc6_add_ia_ta(client, &ds, lease,
03212                            DHCPV6_REQUEST) != ISC_R_SUCCESS) {
03213                 data_string_forget(&ds, MDL);
03214                 return;
03215         }
03216         if (wanted_ia_pd &&
03217             dhc6_add_ia_pd(client, &ds, lease,
03218                            DHCPV6_REQUEST) != ISC_R_SUCCESS) {
03219                 data_string_forget(&ds, MDL);
03220                 return;
03221         }
03222 
03223         log_info("XMT: Request on %s, interval %ld0ms.",
03224                  client->name ? client->name : client->interface->name,
03225                  (long int)client->RT);
03226 
03227         send_ret = send_packet6(client->interface,
03228                                 ds.data, ds.len, &DHCPv6DestAddr);
03229         if (send_ret != ds.len) {
03230                 log_error("dhc6: send_packet6() sent %d of %d bytes",
03231                           send_ret, ds.len);
03232         }
03233 
03234         data_string_forget(&ds, MDL);
03235 
03236         /* Wait RT */
03237         tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
03238         tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
03239         if (tv.tv_usec >= 1000000) {
03240                 tv.tv_sec += 1;
03241                 tv.tv_usec -= 1000000;
03242         }
03243         add_timeout(&tv, do_select6, client, NULL, NULL);
03244 
03245         dhc6_retrans_advance(client);
03246 }
03247 
03248 /* For each IA_NA in the lease, for each address in the IA_NA,
03249  * append that information onto the packet-so-far.
03250  */
03251 static isc_result_t
03252 dhc6_add_ia_na(struct client_state *client, struct data_string *packet,
03253                struct dhc6_lease *lease, u_int8_t message)
03254 {
03255         struct data_string iads;
03256         struct data_string addrds;
03257         struct dhc6_addr *addr;
03258         struct dhc6_ia *ia;
03259         isc_result_t rval = ISC_R_SUCCESS;
03260         TIME t1, t2;
03261 
03262         memset(&iads, 0, sizeof(iads));
03263         memset(&addrds, 0, sizeof(addrds));
03264         for (ia = lease->bindings;
03265              ia != NULL && rval == ISC_R_SUCCESS;
03266              ia = ia->next) {
03267                 if (ia->ia_type != D6O_IA_NA)
03268                         continue;
03269 
03270                 if (!buffer_allocate(&iads.buffer, 12, MDL)) {
03271                         log_error("Unable to allocate memory for IA_NA.");
03272                         rval = ISC_R_NOMEMORY;
03273                         break;
03274                 }
03275 
03276                 /* Copy the IAID into the packet buffer. */
03277                 memcpy(iads.buffer->data, ia->iaid, 4);
03278                 iads.data = iads.buffer->data;
03279                 iads.len = 12;
03280 
03281                 switch (message) {
03282                       case DHCPV6_REQUEST:
03283                       case DHCPV6_RENEW:
03284                       case DHCPV6_REBIND:
03285 
03286                         t1 = client->config->requested_lease / 2;
03287                         t2 = t1 + (t1 / 2);
03288 #if MAX_TIME > 0xffffffff
03289                         if (t1 > 0xffffffff)
03290                                 t1 = 0xffffffff;
03291                         if (t2 > 0xffffffff)
03292                                 t2 = 0xffffffff;
03293 #endif
03294                         putULong(iads.buffer->data + 4, t1);
03295                         putULong(iads.buffer->data + 8, t2);
03296 
03297                         log_debug("XMT:  X-- IA_NA %s",
03298                                   print_hex_1(4, iads.data, 59));
03299                         log_debug("XMT:  | X-- Requested renew  +%u",
03300                                   (unsigned) t1);
03301                         log_debug("XMT:  | X-- Requested rebind +%u",
03302                                   (unsigned) t2);
03303                         break;
03304 
03305                       case DHCPV6_CONFIRM:
03306                       case DHCPV6_RELEASE:
03307                       case DHCPV6_DECLINE:
03308                         /* Set t1 and t2 to zero; server will ignore them */
03309                         memset(iads.buffer->data + 4, 0, 8);
03310                         log_debug("XMT:  X-- IA_NA %s",
03311                                   print_hex_1(4, iads.buffer->data, 55));
03312 
03313                         break;
03314 
03315                       default:
03316                         log_fatal("Impossible condition at %s:%d.", MDL);
03317                 }
03318 
03319                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
03320                         /*
03321                          * Do not confirm expired addresses, do not request
03322                          * expired addresses (but we keep them around for
03323                          * solicit).
03324                          */
03325                         if (addr->flags & DHC6_ADDR_EXPIRED)
03326                                 continue;
03327 
03328                         if (addr->address.len != 16) {
03329                                 log_error("Illegal IPv6 address length (%d), "
03330                                           "ignoring.  (%s:%d)",
03331                                           addr->address.len, MDL);
03332                                 continue;
03333                         }
03334 
03335                         if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
03336                                 log_error("Unable to allocate memory for "
03337                                           "IAADDR.");
03338                                 rval = ISC_R_NOMEMORY;
03339                                 break;
03340                         }
03341 
03342                         addrds.data = addrds.buffer->data;
03343                         addrds.len = 24;
03344 
03345                         /* Copy the address into the packet buffer. */
03346                         memcpy(addrds.buffer->data, addr->address.iabuf, 16);
03347 
03348                         /* Copy in additional information as appropriate */
03349                         switch (message) {
03350                               case DHCPV6_REQUEST:
03351                               case DHCPV6_RENEW:
03352                               case DHCPV6_REBIND:
03353                                 t1 = client->config->requested_lease;
03354                                 t2 = t1 + 300;
03355                                 putULong(addrds.buffer->data + 16, t1);
03356                                 putULong(addrds.buffer->data + 20, t2);
03357 
03358                                 log_debug("XMT:  | | X-- IAADDR %s",
03359                                           piaddr(addr->address));
03360                                 log_debug("XMT:  | | | X-- Preferred "
03361                                           "lifetime +%u", (unsigned)t1);
03362                                 log_debug("XMT:  | | | X-- Max lifetime +%u",
03363                                           (unsigned)t2);
03364 
03365                                 break;
03366 
03367                               case DHCPV6_CONFIRM:
03368                                 /*
03369                                  * Set preferred and max life to zero,
03370                                  * per 17.1.3.
03371                                  */
03372                                 memset(addrds.buffer->data + 16, 0, 8);
03373                                 log_debug("XMT:  | X-- Confirm Address %s",
03374                                           piaddr(addr->address));
03375                                 break;
03376 
03377                               case DHCPV6_RELEASE:
03378                                 /* Preferred and max life are irrelevant */
03379                                 memset(addrds.buffer->data + 16, 0, 8);
03380                                 log_debug("XMT:  | X-- Release Address %s",
03381                                           piaddr(addr->address));
03382                                 break;
03383 
03384                               case DHCPV6_DECLINE:
03385                                 /* Preferred and max life are irrelevant */
03386                                 memset(addrds.buffer->data + 16, 0, 8);
03387                                 log_debug("XMT:  | X-- Decline Address %s",
03388                                           piaddr(addr->address));
03389                                 break;
03390 
03391                               default:
03392                                 log_fatal("Impossible condition at %s:%d.",
03393                                           MDL);
03394                         }
03395 
03396                         append_option(&iads, &dhcpv6_universe, iaaddr_option,
03397                                       &addrds);
03398                         data_string_forget(&addrds, MDL);
03399                 }
03400 
03401                 /*
03402                  * It doesn't make sense to make a request without an
03403                  * address.
03404                  */
03405                 if (ia->addrs == NULL) {
03406                         log_debug("!!!:  V IA_NA has no IAADDRs - removed.");
03407                         rval = ISC_R_FAILURE;
03408                 } else if (rval == ISC_R_SUCCESS) {
03409                         log_debug("XMT:  V IA_NA appended.");
03410                         append_option(packet, &dhcpv6_universe, ia_na_option,
03411                                       &iads);
03412                 }
03413 
03414                 data_string_forget(&iads, MDL);
03415         }
03416 
03417         return rval;
03418 }
03419 
03420 /* For each IA_TA in the lease, for each address in the IA_TA,
03421  * append that information onto the packet-so-far.
03422  */
03423 static isc_result_t
03424 dhc6_add_ia_ta(struct client_state *client, struct data_string *packet,
03425                struct dhc6_lease *lease, u_int8_t message)
03426 {
03427         struct data_string iads;
03428         struct data_string addrds;
03429         struct dhc6_addr *addr;
03430         struct dhc6_ia *ia;
03431         isc_result_t rval = ISC_R_SUCCESS;
03432         TIME t1, t2;
03433 
03434         memset(&iads, 0, sizeof(iads));
03435         memset(&addrds, 0, sizeof(addrds));
03436         for (ia = lease->bindings;
03437              ia != NULL && rval == ISC_R_SUCCESS;
03438              ia = ia->next) {
03439                 if (ia->ia_type != D6O_IA_TA)
03440                         continue;
03441 
03442                 if (!buffer_allocate(&iads.buffer, 4, MDL)) {
03443                         log_error("Unable to allocate memory for IA_TA.");
03444                         rval = ISC_R_NOMEMORY;
03445                         break;
03446                 }
03447 
03448                 /* Copy the IAID into the packet buffer. */
03449                 memcpy(iads.buffer->data, ia->iaid, 4);
03450                 iads.data = iads.buffer->data;
03451                 iads.len = 4;
03452 
03453                 log_debug("XMT:  X-- IA_TA %s",
03454                           print_hex_1(4, iads.buffer->data, 55));
03455 
03456                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
03457                         /*
03458                          * Do not confirm expired addresses, do not request
03459                          * expired addresses (but we keep them around for
03460                          * solicit).
03461                          */
03462                         if (addr->flags & DHC6_ADDR_EXPIRED)
03463                                 continue;
03464 
03465                         if (addr->address.len != 16) {
03466                                 log_error("Illegal IPv6 address length (%d), "
03467                                           "ignoring.  (%s:%d)",
03468                                           addr->address.len, MDL);
03469                                 continue;
03470                         }
03471 
03472                         if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
03473                                 log_error("Unable to allocate memory for "
03474                                           "IAADDR.");
03475                                 rval = ISC_R_NOMEMORY;
03476                                 break;
03477                         }
03478 
03479                         addrds.data = addrds.buffer->data;
03480                         addrds.len = 24;
03481 
03482                         /* Copy the address into the packet buffer. */
03483                         memcpy(addrds.buffer->data, addr->address.iabuf, 16);
03484 
03485                         /* Copy in additional information as appropriate */
03486                         switch (message) {
03487                               case DHCPV6_REQUEST:
03488                               case DHCPV6_RENEW:
03489                               case DHCPV6_REBIND:
03490                                 t1 = client->config->requested_lease;
03491                                 t2 = t1 + 300;
03492                                 putULong(addrds.buffer->data + 16, t1);
03493                                 putULong(addrds.buffer->data + 20, t2);
03494 
03495                                 log_debug("XMT:  | | X-- IAADDR %s",
03496                                           piaddr(addr->address));
03497                                 log_debug("XMT:  | | | X-- Preferred "
03498                                           "lifetime +%u", (unsigned)t1);
03499                                 log_debug("XMT:  | | | X-- Max lifetime +%u",
03500                                           (unsigned)t2);
03501 
03502                                 break;
03503 
03504                               case DHCPV6_CONFIRM:
03505                                 /*
03506                                  * Set preferred and max life to zero,
03507                                  * per 17.1.3.
03508                                  */
03509                                 memset(addrds.buffer->data + 16, 0, 8);
03510                                 log_debug("XMT:  | X-- Confirm Address %s",
03511                                           piaddr(addr->address));
03512                                 break;
03513 
03514                               case DHCPV6_RELEASE:
03515                                 /* Preferred and max life are irrelevant */
03516                                 memset(addrds.buffer->data + 16, 0, 8);
03517                                 log_debug("XMT:  | X-- Release Address %s",
03518                                           piaddr(addr->address));
03519                                 break;
03520 
03521                               default:
03522                                 log_fatal("Impossible condition at %s:%d.",
03523                                           MDL);
03524                         }
03525 
03526                         append_option(&iads, &dhcpv6_universe, iaaddr_option,
03527                                       &addrds);
03528                         data_string_forget(&addrds, MDL);
03529                 }
03530 
03531                 /*
03532                  * It doesn't make sense to make a request without an
03533                  * address.
03534                  */
03535                 if (ia->addrs == NULL) {
03536                         log_debug("!!!:  V IA_TA has no IAADDRs - removed.");
03537                         rval = ISC_R_FAILURE;
03538                 } else if (rval == ISC_R_SUCCESS) {
03539                         log_debug("XMT:  V IA_TA appended.");
03540                         append_option(packet, &dhcpv6_universe, ia_ta_option,
03541                                       &iads);
03542                 }
03543 
03544                 data_string_forget(&iads, MDL);
03545         }
03546 
03547         return rval;
03548 }
03549 
03550 /* For each IA_PD in the lease, for each prefix in the IA_PD,
03551  * append that information onto the packet-so-far.
03552  */
03553 static isc_result_t
03554 dhc6_add_ia_pd(struct client_state *client, struct data_string *packet,
03555                struct dhc6_lease *lease, u_int8_t message)
03556 {
03557         struct data_string iads;
03558         struct data_string prefds;
03559         struct dhc6_addr *pref;
03560         struct dhc6_ia *ia;
03561         isc_result_t rval = ISC_R_SUCCESS;
03562         TIME t1, t2;
03563 
03564         memset(&iads, 0, sizeof(iads));
03565         memset(&prefds, 0, sizeof(prefds));
03566         for (ia = lease->bindings;
03567              ia != NULL && rval == ISC_R_SUCCESS;
03568              ia = ia->next) {
03569                 if (ia->ia_type != D6O_IA_PD)
03570                         continue;
03571 
03572                 if (!buffer_allocate(&iads.buffer, 12, MDL)) {
03573                         log_error("Unable to allocate memory for IA_PD.");
03574                         rval = ISC_R_NOMEMORY;
03575                         break;
03576                 }
03577 
03578                 /* Copy the IAID into the packet buffer. */
03579                 memcpy(iads.buffer->data, ia->iaid, 4);
03580                 iads.data = iads.buffer->data;
03581                 iads.len = 12;
03582 
03583                 switch (message) {
03584                       case DHCPV6_REQUEST:
03585                       case DHCPV6_RENEW:
03586                       case DHCPV6_REBIND:
03587 
03588                         t1 = client->config->requested_lease / 2;
03589                         t2 = t1 + (t1 / 2);
03590 #if MAX_TIME > 0xffffffff
03591                         if (t1 > 0xffffffff)
03592                                 t1 = 0xffffffff;
03593                         if (t2 > 0xffffffff)
03594                                 t2 = 0xffffffff;
03595 #endif
03596                         putULong(iads.buffer->data + 4, t1);
03597                         putULong(iads.buffer->data + 8, t2);
03598 
03599                         log_debug("XMT:  X-- IA_PD %s",
03600                                   print_hex_1(4, iads.data, 59));
03601                         log_debug("XMT:  | X-- Requested renew  +%u",
03602                                   (unsigned) t1);
03603                         log_debug("XMT:  | X-- Requested rebind +%u",
03604                                   (unsigned) t2);
03605                         break;
03606 
03607                       case DHCPV6_RELEASE:
03608                         /* Set t1 and t2 to zero; server will ignore them */
03609                         memset(iads.buffer->data + 4, 0, 8);
03610                         log_debug("XMT:  X-- IA_PD %s",
03611                                   print_hex_1(4, iads.buffer->data, 55));
03612 
03613                         break;
03614 
03615                       default:
03616                         log_fatal("Impossible condition at %s:%d.", MDL);
03617                 }
03618 
03619                 for (pref = ia->addrs ; pref != NULL ; pref = pref->next) {
03620                         /*
03621                          * Do not confirm expired prefixes, do not request
03622                          * expired prefixes (but we keep them around for
03623                          * solicit).
03624                          */
03625                         if (pref->flags & DHC6_ADDR_EXPIRED)
03626                                 continue;
03627 
03628                         if (pref->address.len != 16) {
03629                                 log_error("Illegal IPv6 prefix "
03630                                           "ignoring.  (%s:%d)",
03631                                           MDL);
03632                                 continue;
03633                         }
03634 
03635                         if (pref->plen == 0) {
03636                                 log_info("Null IPv6 prefix, "
03637                                          "ignoring. (%s:%d)",
03638                                          MDL);
03639                         }
03640 
03641                         if (!buffer_allocate(&prefds.buffer, 25, MDL)) {
03642                                 log_error("Unable to allocate memory for "
03643                                           "IAPREFIX.");
03644                                 rval = ISC_R_NOMEMORY;
03645                                 break;
03646                         }
03647 
03648                         prefds.data = prefds.buffer->data;
03649                         prefds.len = 25;
03650 
03651                         /* Copy the prefix into the packet buffer. */
03652                         putUChar(prefds.buffer->data + 8, pref->plen);
03653                         memcpy(prefds.buffer->data + 9,
03654                                pref->address.iabuf,
03655                                16);
03656 
03657                         /* Copy in additional information as appropriate */
03658                         switch (message) {
03659                               case DHCPV6_REQUEST:
03660                               case DHCPV6_RENEW:
03661                               case DHCPV6_REBIND:
03662                                 t1 = client->config->requested_lease;
03663                                 t2 = t1 + 300;
03664                                 putULong(prefds.buffer->data, t1);
03665                                 putULong(prefds.buffer->data + 4, t2);
03666 
03667                                 log_debug("XMT:  | | X-- IAPREFIX %s/%u",
03668                                           piaddr(pref->address),
03669                                           (unsigned) pref->plen);
03670                                 log_debug("XMT:  | | | X-- Preferred "
03671                                           "lifetime +%u", (unsigned)t1);
03672                                 log_debug("XMT:  | | | X-- Max lifetime +%u",
03673                                           (unsigned)t2);
03674 
03675                                 break;
03676 
03677                               case DHCPV6_RELEASE:
03678                                 /* Preferred and max life are irrelevant */
03679                                 memset(prefds.buffer->data, 0, 8);
03680                                 log_debug("XMT:  | X-- Release Prefix %s/%u",
03681                                           piaddr(pref->address),
03682                                           (unsigned) pref->plen);
03683                                 break;
03684 
03685                               default:
03686                                 log_fatal("Impossible condition at %s:%d.",
03687                                           MDL);
03688                         }
03689 
03690                         append_option(&iads, &dhcpv6_universe,
03691                                       iaprefix_option, &prefds);
03692                         data_string_forget(&prefds, MDL);
03693                 }
03694 
03695                 /*
03696                  * It doesn't make sense to make a request without an
03697                  * address.
03698                  */
03699                 if (ia->addrs == NULL) {
03700                         log_debug("!!!:  V IA_PD has no IAPREFIXs - removed.");
03701                         rval = ISC_R_FAILURE;
03702                 } else if (rval == ISC_R_SUCCESS) {
03703                         log_debug("XMT:  V IA_PD appended.");
03704                         append_option(packet, &dhcpv6_universe,
03705                                       ia_pd_option, &iads);
03706                 }
03707 
03708                 data_string_forget(&iads, MDL);
03709         }
03710 
03711         return rval;
03712 }
03713 
03714 /* stopping_finished() checks if there is a remaining work to do.
03715  */
03716 static isc_boolean_t
03717 stopping_finished(void)
03718 {
03719         struct interface_info *ip;
03720         struct client_state *client;
03721 
03722         for (ip = interfaces; ip; ip = ip -> next) {
03723                 for (client = ip -> client; client; client = client -> next) {
03724                         if (client->state != S_STOPPED)
03725                                 return ISC_FALSE;
03726                         if (client->active_lease != NULL)
03727                                 return ISC_FALSE;
03728                 }
03729         }
03730         return ISC_TRUE;
03731 }
03732 
03733 /* reply_handler() accepts a Reply while we're attempting Select or Renew or
03734  * Rebind.  Basically any Reply packet.
03735  */
03736 void
03737 reply_handler(struct packet *packet, struct client_state *client)
03738 {
03739         struct dhc6_lease *lease;
03740         isc_result_t check_status;
03741 
03742         if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
03743                 return;
03744 
03745         /* RFC3315 section 15.10 validation (same as 15.3 since we
03746          * always include a client id).
03747          */
03748         if (!valid_reply(packet, client)) {
03749                 log_error("Invalid Reply - rejecting.");
03750                 return;
03751         }
03752 
03753         lease = dhc6_leaseify(packet);
03754 
03755         /* This is an out of memory condition...hopefully a temporary
03756          * problem.  Returning now makes us try to retransmit later.
03757          */
03758         if (lease == NULL)
03759                 return;
03760 
03761         check_status = dhc6_check_reply(client, lease);
03762         if (check_status != ISC_R_SUCCESS) {
03763                 dhc6_lease_destroy(&lease, MDL);
03764 
03765                 /* If no action was taken, but there is an error, then
03766                  * we wait for a retransmission.
03767                  */
03768                 if (check_status != ISC_R_CANCELED)
03769                         return;
03770         }
03771 
03772         /* We're done retransmitting at this point. */
03773         cancel_timeout(do_confirm6, client);
03774         cancel_timeout(do_select6, client);
03775         cancel_timeout(do_refresh6, client);
03776         cancel_timeout(do_release6, client);
03777         cancel_timeout(do_decline6, client);
03778 
03779         /* If this is in response to a Release/Decline, clean up and return. */
03780         if ((client->state == S_STOPPED) ||
03781             (client->state == S_DECLINED)) {
03782 
03783                 if (client->active_lease != NULL) {
03784                         dhc6_lease_destroy(&client->active_lease, MDL);
03785                         client->active_lease = NULL;
03786                         /* We should never wait for nothing!? */
03787                         if (stopping_finished())
03788                                 exit(0);
03789                 }
03790 
03791                 if (client->state == S_DECLINED)
03792                         start_init6(client);
03793 
03794                 return;
03795         }
03796 
03797         /* Action was taken, so now that we've torn down our scheduled
03798          * retransmissions, return.
03799          */
03800         if (check_status == ISC_R_CANCELED)
03801                 return;
03802 
03803         if (client->selected_lease != NULL) {
03804                 dhc6_lease_destroy(&client->selected_lease, MDL);
03805                 client->selected_lease = NULL;
03806         }
03807 
03808         /* If this is in response to a confirm, we use the lease we've
03809          * already got, not the reply we were sent.
03810          */
03811         if (client->state == S_REBOOTING) {
03812                 if (client->active_lease == NULL)
03813                         log_fatal("Impossible condition at %s:%d.", MDL);
03814 
03815                 dhc6_lease_destroy(&lease, MDL);
03816                 start_bound(client);
03817                 return;
03818         }
03819 
03820         /* Merge any bindings in the active lease (if there is one) into
03821          * the new active lease.
03822          */
03823         dhc6_merge_lease(client->active_lease, lease);
03824 
03825         /* Cleanup if a previous attempt to go bound failed. */
03826         if (client->old_lease != NULL) {
03827                 dhc6_lease_destroy(&client->old_lease, MDL);
03828                 client->old_lease = NULL;
03829         }
03830 
03831         /* Make this lease active and BIND to it. */
03832         if (client->active_lease != NULL)
03833                 client->old_lease = client->active_lease;
03834         client->active_lease = lease;
03835 
03836         /* We're done with the ADVERTISEd leases, if any. */
03837         while(client->advertised_leases != NULL) {
03838                 lease = client->advertised_leases;
03839                 client->advertised_leases = lease->next;
03840 
03841                 dhc6_lease_destroy(&lease, MDL);
03842         }
03843 
03844         start_bound(client);
03845 }
03846 
03847 /* DHCPv6 packets are a little sillier than they needed to be - the root
03848  * packet contains options, then IA's which contain options, then within
03849  * that IAADDR's which contain options.
03850  *
03851  * To sort this out at dhclient-script time (which fetches config parameters
03852  * in environment variables), start_bound() iterates over each IAADDR, and
03853  * calls this function to marshall an environment variable set that includes
03854  * the most-specific option values related to that IAADDR in particular.
03855  *
03856  * To achieve this, we load environment variables for the root options space,
03857  * then the IA, then the IAADDR.  Any duplicate option names will be
03858  * over-written by the later versions.
03859  */
03860 static void
03861 dhc6_marshall_values(const char *prefix, struct client_state *client,
03862                      struct dhc6_lease *lease, struct dhc6_ia *ia,
03863                      struct dhc6_addr *addr)
03864 {
03865         /* Option cache contents, in descending order of
03866          * scope.
03867          */
03868         if ((lease != NULL) && (lease->options != NULL))
03869                 script_write_params6(client, prefix, lease->options);
03870         if ((ia != NULL) && (ia->options != NULL))
03871                 script_write_params6(client, prefix, ia->options);
03872         if ((addr != NULL) && (addr->options != NULL))
03873                 script_write_params6(client, prefix, addr->options);
03874 
03875         /* addr fields. */
03876         if (addr != NULL) {
03877                 if ((ia != NULL) && (ia->ia_type == D6O_IA_PD)) {
03878                         client_envadd(client, prefix,
03879                                       "ip6_prefix", "%s/%u",
03880                                       piaddr(addr->address),
03881                                       (unsigned) addr->plen);
03882                 } else {
03883                         /* Current practice is that all subnets are /64's, but
03884                          * some suspect this may not be permanent.
03885                          */
03886                         client_envadd(client, prefix, "ip6_prefixlen",
03887                                       "%d", 64);
03888                         client_envadd(client, prefix, "ip6_address",
03889                                       "%s", piaddr(addr->address));
03890                 }
03891                 if ((ia != NULL) && (ia->ia_type == D6O_IA_TA)) {
03892                         client_envadd(client, prefix,
03893                                       "ip6_type", "temporary");
03894                 }
03895                 client_envadd(client, prefix, "life_starts", "%d",
03896                               (int)(addr->starts));
03897                 client_envadd(client, prefix, "preferred_life", "%d",
03898                               (int)(addr->preferred_life));
03899                 client_envadd(client, prefix, "max_life", "%d",
03900                               (int)(addr->max_life));
03901         }
03902 
03903         /* ia fields. */
03904         if (ia != NULL) {
03905                 client_envadd(client, prefix, "iaid", "%s",
03906                               print_hex_1(4, ia->iaid, 12));
03907                 client_envadd(client, prefix, "starts", "%d",
03908                               (int)(ia->starts));
03909                 client_envadd(client, prefix, "renew", "%u", ia->renew);
03910                 client_envadd(client, prefix, "rebind", "%u", ia->rebind);
03911         }
03912 }
03913 
03914 /* Look at where the client's active lease is sitting.  If it's looking to
03915  * time out on renew, rebind, depref, or expiration, do those things.
03916  */
03917 static void
03918 dhc6_check_times(struct client_state *client)
03919 {
03920         struct dhc6_lease *lease;
03921         struct dhc6_ia *ia;
03922         struct dhc6_addr *addr;
03923         TIME renew=MAX_TIME, rebind=MAX_TIME, depref=MAX_TIME,
03924              lo_expire=MAX_TIME, hi_expire=0, tmp;
03925         int has_addrs = ISC_FALSE;
03926         struct timeval tv;
03927 
03928         lease = client->active_lease;
03929 
03930         /* Bit spammy.  We should probably keep record of scheduled
03931          * events instead.
03932          */
03933         cancel_timeout(start_renew6, client);
03934         cancel_timeout(start_rebind6, client);
03935         cancel_timeout(do_depref, client);
03936         cancel_timeout(do_expire, client);
03937 
03938         for(ia = lease->bindings ; ia != NULL ; ia = ia->next) {
03939                 TIME this_ia_lo_expire, this_ia_hi_expire, use_expire;
03940 
03941                 this_ia_lo_expire = MAX_TIME;
03942                 this_ia_hi_expire = 0;
03943 
03944                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
03945                         if(!(addr->flags & DHC6_ADDR_DEPREFFED)) {
03946                                 if (addr->preferred_life == 0xffffffff)
03947                                         tmp = MAX_TIME;
03948                                 else
03949                                         tmp = addr->starts +
03950                                               addr->preferred_life;
03951 
03952                                 if (tmp < depref)
03953                                         depref = tmp;
03954                         }
03955 
03956                         if (!(addr->flags & DHC6_ADDR_EXPIRED)) {
03957                                 /* Find EPOCH-relative expiration. */
03958                                 if (addr->max_life == 0xffffffff)
03959                                         tmp = MAX_TIME;
03960                                 else
03961                                         tmp = addr->starts + addr->max_life;
03962 
03963                                 /* Make the times ia->starts relative. */
03964                                 tmp -= ia->starts;
03965 
03966                                 if (tmp > this_ia_hi_expire)
03967                                         this_ia_hi_expire = tmp;
03968                                 if (tmp < this_ia_lo_expire)
03969                                         this_ia_lo_expire = tmp;
03970 
03971                                 has_addrs = ISC_TRUE;
03972                         }
03973                 }
03974 
03975                 /* These times are ia->starts relative. */
03976                 if (this_ia_lo_expire <= (this_ia_hi_expire / 2))
03977                         use_expire = this_ia_hi_expire;
03978                 else
03979                         use_expire = this_ia_lo_expire;
03980 
03981                 /*
03982                  * If the auto-selected expiration time is "infinite", or
03983                  * zero, assert a reasonable default.
03984                  */
03985                 if ((use_expire == MAX_TIME) || (use_expire <= 1))
03986                         use_expire = client->config->requested_lease / 2;
03987                 else
03988                         use_expire /= 2;
03989 
03990                 /* Don't renew/rebind temporary addresses. */
03991                 if (ia->ia_type != D6O_IA_TA) {
03992 
03993                         if (ia->renew == 0) {
03994                                 tmp = ia->starts + use_expire;
03995                         } else if (ia->renew == 0xffffffff)
03996                                 tmp = MAX_TIME;
03997                         else
03998                                 tmp = ia->starts + ia->renew;
03999 
04000                         if (tmp < renew)
04001                                 renew = tmp;
04002 
04003                         if (ia->rebind == 0) {
04004                                 /* Set rebind to 3/4 expiration interval. */
04005                                 tmp = ia->starts;
04006                                 tmp += use_expire + (use_expire / 2);
04007                         } else if (ia->rebind == 0xffffffff)
04008                                 tmp = MAX_TIME;
04009                         else
04010                                 tmp = ia->starts + ia->rebind;
04011 
04012                         if (tmp < rebind)
04013                                 rebind = tmp;
04014                 }
04015 
04016                 /*
04017                  * Return expiration ranges to EPOCH relative for event
04018                  * scheduling (add_timeout()).
04019                  */
04020                 this_ia_hi_expire += ia->starts;
04021                 this_ia_lo_expire += ia->starts;
04022 
04023                 if (this_ia_hi_expire > hi_expire)
04024                         hi_expire = this_ia_hi_expire;
04025                 if (this_ia_lo_expire < lo_expire)
04026                         lo_expire = this_ia_lo_expire;
04027         }
04028 
04029         /* If there are no addresses, give up, go to INIT.
04030          * Note that if an address is unexpired with a date in the past,
04031          * we're scheduling an expiration event to ocurr in the past.  We
04032          * could probably optimize this to expire now (but then there's
04033          * recursion).
04034          *
04035          * In the future, we may decide that we're done here, or to
04036          * schedule a future request (using 4-pkt info-request model).
04037          */
04038         if (has_addrs == ISC_FALSE) {
04039                 dhc6_lease_destroy(&client->active_lease, MDL);
04040                 client->active_lease = NULL;
04041 
04042                 /* Go back to the beginning. */
04043                 start_init6(client);
04044                 return;
04045         }
04046 
04047         switch(client->state) {
04048               case S_BOUND:
04049                 /* We'd like to hit renewing, but if rebinding has already
04050                  * passed (time warp), head straight there.
04051                  */
04052                 if ((rebind > cur_time) && (renew < rebind)) {
04053                         log_debug("PRC: Renewal event scheduled in %d seconds, "
04054                                   "to run for %u seconds.",
04055                                   (int)(renew - cur_time),
04056                                   (unsigned)(rebind - renew));
04057                         client->next_MRD = rebind;
04058                         tv.tv_sec = renew;
04059                         tv.tv_usec = 0;
04060                         add_timeout(&tv, start_renew6, client, NULL, NULL);
04061 
04062                         break;
04063                 }
04064                 /* FALL THROUGH */
04065               case S_RENEWING:
04066                 /* While actively renewing, MRD is bounded by the time
04067                  * we stop renewing and start rebinding.  This helps us
04068                  * process the state change on time.
04069                  */
04070                 client->MRD = rebind - cur_time;
04071                 if (rebind != MAX_TIME) {
04072                         log_debug("PRC: Rebind event scheduled in %d seconds, "
04073                                   "to run for %d seconds.",
04074                                   (int)(rebind - cur_time),
04075                                   (int)(hi_expire - rebind));
04076                         client->next_MRD = hi_expire;
04077                         tv.tv_sec = rebind;
04078                         tv.tv_usec = 0;
04079                         add_timeout(&tv, start_rebind6, client, NULL, NULL);
04080                 }
04081                 break;
04082 
04083               case S_REBINDING:
04084                 /* For now, we rebind up until the last lease expires.  In
04085                  * the future, we might want to start SOLICITing when we've
04086                  * depreffed an address.
04087                  */
04088                 client->MRD = hi_expire - cur_time;
04089                 break;
04090 
04091               default:
04092                 log_fatal("Impossible condition at %s:%d.", MDL);
04093         }
04094 
04095         /* Separately, set a time at which we will depref and expire
04096          * leases.  This might happen with multiple addresses while we
04097          * keep trying to refresh.
04098          */
04099         if (depref != MAX_TIME) {
04100                 log_debug("PRC: Depreference scheduled in %d seconds.",
04101                           (int)(depref - cur_time));
04102                 tv.tv_sec = depref;
04103                 tv.tv_usec = 0;
04104                 add_timeout(&tv, do_depref, client, NULL, NULL);
04105         }
04106         if (lo_expire != MAX_TIME) {
04107                 log_debug("PRC: Expiration scheduled in %d seconds.",
04108                           (int)(lo_expire - cur_time));
04109                 tv.tv_sec = lo_expire;
04110                 tv.tv_usec = 0;
04111                 add_timeout(&tv, do_expire, client, NULL, NULL);
04112         }
04113 }
04114 
04115 /* In a given IA chain, find the IA with the same type and 'iaid'. */
04116 static struct dhc6_ia *
04117 find_ia(struct dhc6_ia *head, u_int16_t type, const char *id)
04118 {
04119         struct dhc6_ia *ia;
04120 
04121         for (ia = head ; ia != NULL ; ia = ia->next) {
04122                 if (ia->ia_type != type)
04123                         continue;
04124                 if (memcmp(ia->iaid, id, 4) == 0)
04125                         return ia;
04126         }
04127 
04128         return NULL;
04129 }
04130 
04131 /* In a given address chain, find a matching address. */
04132 static struct dhc6_addr *
04133 find_addr(struct dhc6_addr *head, struct iaddr *address)
04134 {
04135         struct dhc6_addr *addr;
04136 
04137         for (addr = head ; addr != NULL ; addr = addr->next) {
04138                 if ((addr->address.len == address->len) &&
04139                     (memcmp(addr->address.iabuf, address->iabuf,
04140                             address->len) == 0))
04141                         return addr;
04142         }
04143 
04144         return NULL;
04145 }
04146 
04147 /* In a given prefix chain, find a matching prefix. */
04148 static struct dhc6_addr *
04149 find_pref(struct dhc6_addr *head, struct iaddr *prefix, u_int8_t plen)
04150 {
04151         struct dhc6_addr *pref;
04152 
04153         for (pref = head ; pref != NULL ; pref = pref->next) {
04154                 if ((pref->address.len == prefix->len) &&
04155                     (pref->plen == plen) &&
04156                     (memcmp(pref->address.iabuf, prefix->iabuf,
04157                             prefix->len) == 0))
04158                         return pref;
04159         }
04160 
04161         return NULL;
04162 }
04163 
04164 /* Merge the bindings from the source lease into the destination lease
04165  * structure, where they are missing.  We have to copy the stateful
04166  * objects rather than move them over, because later code needs to be
04167  * able to compare new versus old if they contain any bindings.
04168  */
04169 static void
04170 dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst)
04171 {
04172         struct dhc6_ia *sia, *dia, *tia;
04173         struct dhc6_addr *saddr, *daddr, *taddr;
04174         int changes = 0;
04175 
04176         if ((dst == NULL) || (src == NULL))
04177                 return;
04178 
04179         for (sia = src->bindings ; sia != NULL ; sia = sia->next) {
04180                 dia = find_ia(dst->bindings, sia->ia_type, (char *)sia->iaid);
04181 
04182                 if (dia == NULL) {
04183                         tia = dhc6_dup_ia(sia, MDL);
04184 
04185                         if (tia == NULL)
04186                                 log_fatal("Out of memory merging lease - "
04187                                           "Unable to continue without losing "
04188                                           "state! (%s:%d)", MDL);
04189 
04190                         /* XXX: consider sorting? */
04191                         tia->next = dst->bindings;
04192                         dst->bindings = tia;
04193                         changes = 1;
04194                 } else {
04195                         for (saddr = sia->addrs ; saddr != NULL ;
04196                              saddr = saddr->next) {
04197                                 if (sia->ia_type != D6O_IA_PD)
04198                                         daddr = find_addr(dia->addrs,
04199                                                           &saddr->address);
04200                                 else
04201                                         daddr = find_pref(dia->addrs,
04202                                                           &saddr->address,
04203                                                           saddr->plen);
04204 
04205                                 if (daddr == NULL) {
04206                                         taddr = dhc6_dup_addr(saddr, MDL);
04207 
04208                                         if (taddr == NULL)
04209                                                 log_fatal("Out of memory "
04210                                                           "merging lease - "
04211                                                           "Unable to continue "
04212                                                           "without losing "
04213                                                           "state! (%s:%d)",
04214                                                           MDL);
04215 
04216                                         /* XXX: consider sorting? */
04217                                         taddr->next = dia->addrs;
04218                                         dia->addrs = taddr;
04219                                         changes = 1;
04220                                 }
04221                         }
04222                 }
04223         }
04224 
04225         /* If we made changes, reset the score to 0 so it is recalculated. */
04226         if (changes)
04227                 dst->score = 0;
04228 }
04229 
04230 /* We've either finished selecting or succeeded in Renew or Rebinding our
04231  * lease.  In all cases we got a Reply.  Give dhclient-script a tickle
04232  * to inform it about the new values, and then lay in wait for the next
04233  * event.
04234  */
04235 static void
04236 start_bound(struct client_state *client)
04237 {
04238         struct dhc6_ia *ia, *oldia;
04239         struct dhc6_addr *addr, *oldaddr;
04240         struct dhc6_lease *lease, *old;
04241         const char *reason;
04242 #if defined (NSUPDATE)
04243         TIME dns_update_offset = 1;
04244 #endif
04245 
04246         lease = client->active_lease;
04247         if (lease == NULL) {
04248                 log_error("Cannot enter bound state unless an active lease "
04249                           "is selected.");
04250                 return;
04251         }
04252         lease->released = ISC_FALSE;
04253         old = client->old_lease;
04254 
04255         client->v6_handler = bound_handler;
04256 
04257         switch (client->state) {
04258               case S_SELECTING:
04259               case S_REBOOTING: /* Pretend we got bound. */
04260                 reason = "BOUND6";
04261                 break;
04262 
04263               case S_RENEWING:
04264                 reason = "RENEW6";
04265                 break;
04266 
04267               case S_REBINDING:
04268                 reason = "REBIND6";
04269                 break;
04270 
04271               default:
04272                 log_fatal("Impossible condition at %s:%d.", MDL);
04273                 /* Silence compiler warnings. */
04274                 return;
04275         }
04276 
04277         log_debug("PRC: Bound to lease %s.",
04278                   print_hex_1(client->active_lease->server_id.len,
04279                               client->active_lease->server_id.data, 55));
04280         client->state = S_BOUND;
04281 
04282         write_client6_lease(client, lease, 0, 1);
04283 
04284         oldia = NULL;
04285         for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
04286                 if (old != NULL)
04287                         oldia = find_ia(old->bindings,
04288                                         ia->ia_type,
04289                                         (char *)ia->iaid);
04290                 else
04291                         oldia = NULL;
04292 
04293                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
04294                         if (oldia != NULL) {
04295                                 if (ia->ia_type != D6O_IA_PD)
04296                                         oldaddr = find_addr(oldia->addrs,
04297                                                             &addr->address);
04298                                 else
04299                                         oldaddr = find_pref(oldia->addrs,
04300                                                             &addr->address,
04301                                                             addr->plen);
04302                         } else
04303                                 oldaddr = NULL;
04304 
04305 #if defined (NSUPDATE)
04306                         if ((oldaddr == NULL) && (ia->ia_type == D6O_IA_NA))
04307                                 dhclient_schedule_updates(client,
04308                                                           &addr->address,
04309                                                           dns_update_offset++);
04310 #endif
04311 
04312                         /* Shell out to setup the new binding. */
04313                         script_init(client, reason, NULL);
04314 
04315                         if (old != NULL)
04316                                 dhc6_marshall_values("old_", client, old,
04317                                                      oldia, oldaddr);
04318                         dhc6_marshall_values("new_", client, lease, ia, addr);
04319                         script_write_requested6(client);
04320 
04321                         // when script returns 3, DAD failed
04322                         if (script_go(client) == 3) {
04323                                 start_decline6(client);
04324                                 return;
04325                         }
04326                 }
04327 
04328                 /* XXX: maybe we should loop on the old values instead? */
04329                 if (ia->addrs == NULL) {
04330                         script_init(client, reason, NULL);
04331 
04332                         if (old != NULL)
04333                                 dhc6_marshall_values("old_", client, old,
04334                                                      oldia,
04335                                                      oldia != NULL ?
04336                                                          oldia->addrs : NULL);
04337 
04338                         dhc6_marshall_values("new_", client, lease, ia,
04339                                              NULL);
04340                         script_write_requested6(client);
04341 
04342                         script_go(client);
04343                 }
04344         }
04345 
04346         /* XXX: maybe we should loop on the old values instead? */
04347         if (lease->bindings == NULL) {
04348                 script_init(client, reason, NULL);
04349 
04350                 if (old != NULL)
04351                         dhc6_marshall_values("old_", client, old,
04352                                              old->bindings,
04353                                              (old->bindings != NULL) ?
04354                                                 old->bindings->addrs : NULL);
04355 
04356                 dhc6_marshall_values("new_", client, lease, NULL, NULL);
04357                 script_write_requested6(client);
04358 
04359                 script_go(client);
04360         }
04361 
04362         go_daemon();
04363 
04364         if (client->old_lease != NULL) {
04365                 dhc6_lease_destroy(&client->old_lease, MDL);
04366                 client->old_lease = NULL;
04367         }
04368 
04369         /* Schedule events. */
04370         dhc6_check_times(client);
04371 }
04372 
04373 /*
04374  * Decline addresses.
04375  */
04376 void
04377 start_decline6(struct client_state *client)
04378 {
04379         /* Cancel any pending transmissions */
04380         cancel_timeout(do_confirm6, client);
04381         cancel_timeout(do_select6, client);
04382         cancel_timeout(do_refresh6, client);
04383         cancel_timeout(do_release6, client);
04384         cancel_timeout(do_decline6, client);
04385         client->state = S_DECLINED;
04386 
04387         if (client->active_lease == NULL)
04388                 return;
04389 
04390         /* Set timers per RFC3315 section 18.1.7. */
04391         client->IRT = DEC_TIMEOUT * 100;
04392         client->MRT = 0;
04393         client->MRC = DEC_MAX_RC;
04394         client->MRD = 0;
04395 
04396         dhc6_retrans_init(client);
04397         client->v6_handler = reply_handler;
04398 
04399         client->refresh_type = DHCPV6_DECLINE;
04400         do_decline6(client);
04401 }
04402 
04403 /*
04404  * do_decline6() creates a Decline packet and transmits it.
04405  */
04406 static void
04407 do_decline6(void *input)
04408 {
04409         struct client_state *client;
04410         struct data_string ds;
04411         int send_ret;
04412         struct timeval elapsed, tv;
04413 
04414         client = input;
04415 
04416         if ((client->active_lease == NULL) || !active_prefix(client))
04417                 return;
04418 
04419         if ((client->MRC != 0) && (client->txcount > client->MRC))  {
04420                 log_info("Max retransmission count exceeded.");
04421                 goto decline_done;
04422         }
04423 
04424         /*
04425          * Start_time starts at the first transmission.
04426          */
04427         if (client->txcount == 0) {
04428                 client->start_time.tv_sec = cur_tv.tv_sec;
04429                 client->start_time.tv_usec = cur_tv.tv_usec;
04430         }
04431 
04432         /* elapsed = cur - start */
04433         elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
04434         elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
04435         if (elapsed.tv_usec < 0) {
04436                 elapsed.tv_sec -= 1;
04437                 elapsed.tv_usec += 1000000;
04438         }
04439 
04440         memset(&ds, 0, sizeof(ds));
04441         if (!buffer_allocate(&ds.buffer, 4, MDL)) {
04442                 log_error("Unable to allocate memory for Decline.");
04443                 goto decline_done;
04444         }
04445 
04446         ds.data = ds.buffer->data;
04447         ds.len = 4;
04448         ds.buffer->data[0] = DHCPV6_DECLINE;
04449         memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
04450 
04451         /* Form an elapsed option. */
04452         /* Maximum value is 65535 1/100s coded as 0xffff. */
04453         if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
04454             ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
04455                 client->elapsed = 0xffff;
04456         } else {
04457                 client->elapsed = elapsed.tv_sec * 100;
04458                 client->elapsed += elapsed.tv_usec / 10000;
04459         }
04460 
04461         client->elapsed = htons(client->elapsed);
04462 
04463         log_debug("XMT: Forming Decline.");
04464         make_client6_options(client, &client->sent_options,
04465                              client->active_lease, DHCPV6_DECLINE);
04466         dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
04467                                     client->sent_options, &global_scope,
04468                                     &dhcpv6_universe);
04469 
04470         /* Append IA's (but don't release temporary addresses). */
04471         if (wanted_ia_na &&
04472             dhc6_add_ia_na(client, &ds, client->active_lease,
04473                            DHCPV6_DECLINE) != ISC_R_SUCCESS) {
04474                 data_string_forget(&ds, MDL);
04475                 goto decline_done;
04476         }
04477         if (wanted_ia_pd &&
04478             dhc6_add_ia_pd(client, &ds, client->active_lease,
04479                            DHCPV6_DECLINE) != ISC_R_SUCCESS) {
04480                 data_string_forget(&ds, MDL);
04481                 goto decline_done;
04482         }
04483 
04484         /* Transmit and wait. */
04485         log_info("XMT: Decline on %s, interval %ld0ms.",
04486                  client->name ? client->name : client->interface->name,
04487                  (long int)client->RT);
04488 
04489         send_ret = send_packet6(client->interface, ds.data, ds.len,
04490                                 &DHCPv6DestAddr);
04491         if (send_ret != ds.len) {
04492                 log_error("dhc6: sendpacket6() sent %d of %d bytes",
04493                           send_ret, ds.len);
04494         }
04495 
04496         data_string_forget(&ds, MDL);
04497 
04498         /* Wait RT */
04499         tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
04500         tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
04501         if (tv.tv_usec >= 1000000) {
04502                 tv.tv_sec += 1;
04503                 tv.tv_usec -= 1000000;
04504         }
04505         add_timeout(&tv, do_decline6, client, NULL, NULL);
04506         dhc6_retrans_advance(client);
04507         return;
04508 
04509 decline_done:
04510         dhc6_lease_destroy(&client->active_lease, MDL);
04511         client->active_lease = NULL;
04512         start_init6(client);
04513         return;
04514 }
04515 
04516 /* While bound, ignore packets.  In the future we'll want to answer
04517  * Reconfigure-Request messages and the like.
04518  */
04519 void
04520 bound_handler(struct packet *packet, struct client_state *client)
04521 {
04522         log_debug("RCV: Input packets are ignored once bound.");
04523 }
04524 
04525 /* start_renew6() gets us all ready to go to start transmitting Renew packets.
04526  * Note that client->next_MRD must be set before entering this function -
04527  * it must be set to the time at which the client should start Rebinding.
04528  */
04529 void
04530 start_renew6(void *input)
04531 {
04532         struct client_state *client;
04533 
04534         client = (struct client_state *)input;
04535 
04536         log_info("PRC: Renewing lease on %s.",
04537                  client->name ? client->name : client->interface->name);
04538         client->state = S_RENEWING;
04539 
04540         client->v6_handler = reply_handler;
04541 
04542         /* Times per RFC3315 section 18.1.3. */
04543         client->IRT = REN_TIMEOUT * 100;
04544         client->MRT = REN_MAX_RT * 100;
04545         client->MRC = 0;
04546         /* MRD is special in renew - we need to set it by checking timer
04547          * state.
04548          */
04549         client->MRD = client->next_MRD - cur_time;
04550 
04551         dhc6_retrans_init(client);
04552 
04553         client->refresh_type = DHCPV6_RENEW;
04554         do_refresh6(client);
04555 }
04556 
04557 /* do_refresh6() transmits one DHCPv6 packet, be it a Renew or Rebind, and
04558  * gives the retransmission state a bump for the next time.  Note that
04559  * client->refresh_type must be set before entering this function.
04560  */
04561 void
04562 do_refresh6(void *input)
04563 {
04564         struct option_cache *oc;
04565         struct sockaddr_in6 unicast, *dest_addr = &DHCPv6DestAddr;
04566         struct data_string ds;
04567         struct client_state *client;
04568         struct dhc6_lease *lease;
04569         struct timeval elapsed, tv;
04570         int send_ret;
04571 
04572         client = (struct client_state *)input;
04573         memset(&ds, 0, sizeof(ds));
04574 
04575         lease = client->active_lease;
04576         if (lease == NULL) {
04577                 log_error("Cannot renew without an active binding.");
04578                 return;
04579         }
04580 
04581         /* Ensure we're emitting a valid message type. */
04582         switch (client->refresh_type) {
04583               case DHCPV6_RENEW:
04584               case DHCPV6_REBIND:
04585                 break;
04586 
04587               default:
04588                 log_fatal("Internal inconsistency (%d) at %s:%d.",
04589                           client->refresh_type, MDL);
04590         }
04591 
04592         /*
04593          * Start_time starts at the first transmission.
04594          */
04595         if (client->txcount == 0) {
04596                 client->start_time.tv_sec = cur_tv.tv_sec;
04597                 client->start_time.tv_usec = cur_tv.tv_usec;
04598         }
04599 
04600         /* elapsed = cur - start */
04601         elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
04602         elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
04603         if (elapsed.tv_usec < 0) {
04604                 elapsed.tv_sec -= 1;
04605                 elapsed.tv_usec += 1000000;
04606         }
04607         if (((client->MRC != 0) && (client->txcount > client->MRC)) ||
04608             ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD))) {
04609                 /* We're done.  Move on to the next phase, if any. */
04610                 dhc6_check_times(client);
04611                 return;
04612         }
04613 
04614         /*
04615          * Check whether the server has sent a unicast option; if so, we can
04616          * use the address it specified for RENEWs.
04617          */
04618         oc = lookup_option(&dhcpv6_universe, lease->options, D6O_UNICAST);
04619         if (oc && evaluate_option_cache(&ds, NULL, NULL, NULL,
04620                                         lease->options, NULL, &global_scope,
04621                                         oc, MDL)) {
04622                 if (ds.len < 16) {
04623                         log_error("Invalid unicast option length %d.", ds.len);
04624                 } else {
04625                         memset(&unicast, 0, sizeof(DHCPv6DestAddr));
04626                         unicast.sin6_family = AF_INET6;
04627                         unicast.sin6_port = remote_port;
04628                         memcpy(&unicast.sin6_addr, ds.data, 16);
04629                         if (client->refresh_type == DHCPV6_RENEW) {
04630                                 dest_addr = &unicast;
04631                         }
04632                 }
04633 
04634                 data_string_forget(&ds, MDL);
04635         }
04636 
04637         /* Commence forming a renew packet. */
04638         memset(&ds, 0, sizeof(ds));
04639         if (!buffer_allocate(&ds.buffer, 4, MDL)) {
04640                 log_error("Unable to allocate memory for packet.");
04641                 return;
04642         }
04643         ds.data = ds.buffer->data;
04644         ds.len = 4;
04645 
04646         ds.buffer->data[0] = client->refresh_type;
04647         memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
04648 
04649         /* Form an elapsed option. */
04650         /* Maximum value is 65535 1/100s coded as 0xffff. */
04651         if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
04652             ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
04653                 client->elapsed = 0xffff;
04654         } else {
04655                 client->elapsed = elapsed.tv_sec * 100;
04656                 client->elapsed += elapsed.tv_usec / 10000;
04657         }
04658 
04659         if (client->elapsed == 0)
04660                 log_debug("XMT: Forming %s, 0 ms elapsed.",
04661                           dhcpv6_type_names[client->refresh_type]);
04662         else
04663                 log_debug("XMT: Forming %s, %u0 ms elapsed.",
04664                           dhcpv6_type_names[client->refresh_type],
04665                           (unsigned)client->elapsed);
04666 
04667         client->elapsed = htons(client->elapsed);
04668 
04669         make_client6_options(client, &client->sent_options, lease,
04670                              client->refresh_type);
04671 
04672         /* Put in any options from the sent cache. */
04673         dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
04674                                     client->sent_options, &global_scope,
04675                                     &dhcpv6_universe);
04676 
04677         /* Append IA's */
04678         if (wanted_ia_na &&
04679             dhc6_add_ia_na(client, &ds, lease,
04680                            client->refresh_type) != ISC_R_SUCCESS) {
04681                 data_string_forget(&ds, MDL);
04682                 return;
04683         }
04684         if (wanted_ia_pd &&
04685             dhc6_add_ia_pd(client, &ds, lease,
04686                            client->refresh_type) != ISC_R_SUCCESS) {
04687                 data_string_forget(&ds, MDL);
04688                 return;
04689         }
04690 
04691         log_info("XMT: %s on %s, interval %ld0ms.",
04692                  dhcpv6_type_names[client->refresh_type],
04693                  client->name ? client->name : client->interface->name,
04694                  (long int)client->RT);
04695 
04696         send_ret = send_packet6(client->interface, ds.data, ds.len, dest_addr);
04697 
04698         if (send_ret != ds.len) {
04699                 log_error("dhc6: send_packet6() sent %d of %d bytes",
04700                           send_ret, ds.len);
04701         }
04702 
04703         data_string_forget(&ds, MDL);
04704 
04705         /* Wait RT */
04706         tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
04707         tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
04708         if (tv.tv_usec >= 1000000) {
04709                 tv.tv_sec += 1;
04710                 tv.tv_usec -= 1000000;
04711         }
04712         add_timeout(&tv, do_refresh6, client, NULL, NULL);
04713 
04714         dhc6_retrans_advance(client);
04715 }
04716 
04717 /* start_rebind6() gets us all set up to go and rebind a lease.  Note that
04718  * client->next_MRD must be set before entering this function.  In this case,
04719  * MRD must be set to the maximum time any address in the packet will
04720  * expire.
04721  */
04722 void
04723 start_rebind6(void *input)
04724 {
04725         struct client_state *client;
04726 
04727         client = (struct client_state *)input;
04728 
04729         log_info("PRC: Rebinding lease on %s.",
04730                  client->name ? client->name : client->interface->name);
04731         client->state = S_REBINDING;
04732 
04733         client->v6_handler = reply_handler;
04734 
04735         /* Times per RFC3315 section 18.1.4. */
04736         client->IRT = REB_TIMEOUT * 100;
04737         client->MRT = REB_MAX_RT * 100;
04738         client->MRC = 0;
04739         /* MRD is special in rebind - it's determined by the timer
04740          * state.
04741          */
04742         client->MRD = client->next_MRD - cur_time;
04743 
04744         dhc6_retrans_init(client);
04745 
04746         client->refresh_type = DHCPV6_REBIND;
04747         do_refresh6(client);
04748 }
04749 
04750 /* do_depref() runs through a given lease's addresses, for each that has
04751  * not yet been depreffed, shells out to the dhclient-script to inform it
04752  * of the status change.  The dhclient-script should then do...something...
04753  * to encourage applications to move off the address and onto one of the
04754  * remaining 'preferred' addresses.
04755  */
04756 void
04757 do_depref(void *input)
04758 {
04759         struct client_state *client;
04760         struct dhc6_lease *lease;
04761         struct dhc6_ia *ia;
04762         struct dhc6_addr *addr;
04763 
04764         client = (struct client_state *)input;
04765 
04766         lease = client->active_lease;
04767         if (lease == NULL)
04768                 return;
04769 
04770         for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
04771                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
04772                         if (addr->flags & DHC6_ADDR_DEPREFFED)
04773                                 continue;
04774 
04775                         if (addr->starts + addr->preferred_life <= cur_time) {
04776                                 script_init(client, "DEPREF6", NULL);
04777                                 dhc6_marshall_values("cur_", client, lease,
04778                                                      ia, addr);
04779                                 script_write_requested6(client);
04780                                 script_go(client);
04781 
04782                                 addr->flags |= DHC6_ADDR_DEPREFFED;
04783 
04784                                 if (ia->ia_type != D6O_IA_PD)
04785                                     log_info("PRC: Address %s depreferred.",
04786                                              piaddr(addr->address));
04787                                 else
04788                                     log_info("PRC: Prefix %s/%u depreferred.",
04789                                              piaddr(addr->address),
04790                                              (unsigned) addr->plen);
04791 
04792 #if defined (NSUPDATE)
04793                                 /* Remove DDNS bindings at depref time. */
04794                                 if ((ia->ia_type == D6O_IA_NA) &&
04795                                     client->config->do_forward_update)
04796                                         client_dns_remove(client, 
04797                                                           &addr->address);
04798 #endif
04799                         }
04800                 }
04801         }
04802 
04803         dhc6_check_times(client);
04804 }
04805 
04806 /* do_expire() searches through all the addresses on a given lease, and
04807  * expires/removes any addresses that are no longer valid.
04808  */
04809 void
04810 do_expire(void *input)
04811 {
04812         struct client_state *client;
04813         struct dhc6_lease *lease;
04814         struct dhc6_ia *ia;
04815         struct dhc6_addr *addr;
04816         int has_addrs = ISC_FALSE;
04817 
04818         client = (struct client_state *)input;
04819 
04820         lease = client->active_lease;
04821         if (lease == NULL)
04822                 return;
04823 
04824         for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
04825                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
04826                         if (addr->flags & DHC6_ADDR_EXPIRED)
04827                                 continue;
04828 
04829                         if (addr->starts + addr->max_life <= cur_time) {
04830                                 script_init(client, "EXPIRE6", NULL);
04831                                 dhc6_marshall_values("old_", client, lease,
04832                                                      ia, addr);
04833                                 script_write_requested6(client);
04834                                 script_go(client);
04835 
04836                                 addr->flags |= DHC6_ADDR_EXPIRED;
04837 
04838                                 if (ia->ia_type != D6O_IA_PD)
04839                                     log_info("PRC: Address %s expired.",
04840                                              piaddr(addr->address));
04841                                 else
04842                                     log_info("PRC: Prefix %s/%u expired.",
04843                                              piaddr(addr->address),
04844                                              (unsigned) addr->plen);
04845 
04846 #if defined (NSUPDATE)
04847                                 /* We remove DNS records at depref time, but
04848                                  * it is possible that we might get here
04849                                  * without depreffing.
04850                                  */
04851                                 if ((ia->ia_type == D6O_IA_NA) &&
04852                                     client->config->do_forward_update &&
04853                                     !(addr->flags & DHC6_ADDR_DEPREFFED))
04854                                         client_dns_remove(client,
04855                                                           &addr->address);
04856 #endif
04857 
04858                                 continue;
04859                         }
04860 
04861                         has_addrs = ISC_TRUE;
04862                 }
04863         }
04864 
04865         /* Clean up empty leases. */
04866         if (has_addrs == ISC_FALSE) {
04867                 log_info("PRC: Bound lease is devoid of active addresses."
04868                          "  Re-initializing.");
04869 
04870                 dhc6_lease_destroy(&lease, MDL);
04871                 client->active_lease = NULL;
04872 
04873                 start_init6(client);
04874                 return;
04875         }
04876 
04877         /* Schedule the next run through. */
04878         dhc6_check_times(client);
04879 }
04880 
04881 /*
04882  * Run client script to unconfigure interface.
04883  * Called with reason STOP6 when dhclient -x is run, or with reason
04884  * RELEASE6 when server has replied to a Release message.
04885  * Stateless is a special case.
04886  */
04887 void
04888 unconfigure6(struct client_state *client, const char *reason)
04889 {
04890         struct dhc6_ia *ia;
04891         struct dhc6_addr *addr;
04892 
04893         if (stateless) {
04894                 script_init(client, reason, NULL);
04895                 if (client->active_lease != NULL)
04896                         script_write_params6(client, "old_",
04897                                              client->active_lease->options);
04898                 script_write_requested6(client);
04899                 script_go(client);
04900                 return;
04901         }
04902 
04903         if (client->active_lease == NULL)
04904                 return;
04905 
04906         for (ia = client->active_lease->bindings ; ia != NULL ; ia = ia->next) {
04907                 if (ia->ia_type == D6O_IA_TA)
04908                         continue;
04909 
04910                 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
04911                         script_init(client, reason, NULL);
04912                         dhc6_marshall_values("old_", client,
04913                                              client->active_lease, ia, addr);
04914                         script_write_requested6(client);
04915                         script_go(client);
04916 
04917 #if defined (NSUPDATE)
04918                         if ((ia->ia_type == D6O_IA_NA) &&
04919                             client->config->do_forward_update)
04920                                 client_dns_remove(client, &addr->address);
04921 #endif
04922                 }
04923         }
04924 }
04925 
04926 void
04927 refresh_info_request6(void *input)
04928 {
04929         struct client_state *client;
04930 
04931         client = (struct client_state *)input;
04932         start_info_request6(client);
04933 }
04934 
04935 /* Timeout for Information-Request (using the IRT option).
04936  */
04937 static void
04938 dhc6_check_irt(struct client_state *client)
04939 {
04940         struct option **req;
04941         struct option_cache *oc;
04942         TIME expire = MAX_TIME;
04943         struct timeval tv;
04944         int i;
04945         isc_boolean_t found = ISC_FALSE;
04946 
04947         cancel_timeout(refresh_info_request6, client);
04948 
04949         req = client->config->requested_options;
04950         for (i = 0; req[i] != NULL; i++) {
04951                 if (req[i] == irt_option) {
04952                         found = ISC_TRUE;
04953                         break;
04954                 }
04955         }
04956         /* Simply return gives a endless loop waiting for nothing. */
04957         if (!found)
04958                 exit(0);
04959 
04960         oc = lookup_option(&dhcpv6_universe, client->active_lease->options,
04961                            D6O_INFORMATION_REFRESH_TIME);
04962         if (oc != NULL) {
04963                 struct data_string irt;
04964 
04965                 memset(&irt, 0, sizeof(irt));
04966                 if (!evaluate_option_cache(&irt, NULL, NULL, client,
04967                                            client->active_lease->options,
04968                                            NULL, &global_scope, oc, MDL) ||
04969                     (irt.len < 4)) {
04970                         log_error("Can't evaluate IRT.");
04971                 } else {
04972                         expire = getULong(irt.data);
04973                         if (expire < IRT_MINIMUM)
04974                                 expire = IRT_MINIMUM;
04975                         if (expire == 0xffffffff)
04976                                 expire = MAX_TIME;
04977                 }
04978                 data_string_forget(&irt, MDL);
04979         } else
04980                 expire = IRT_DEFAULT;
04981 
04982         if (expire != MAX_TIME) {
04983                 log_debug("PRC: Refresh event scheduled in %u seconds.",
04984                           (unsigned) expire);
04985                 tv.tv_sec = cur_time + expire;
04986                 tv.tv_usec = 0;
04987                 add_timeout(&tv, refresh_info_request6, client, NULL, NULL);
04988         }
04989 }
04990 
04991 /* We got a Reply. Give dhclient-script a tickle to inform it about
04992  * the new values, and then lay in wait for the next event.
04993  */
04994 static void
04995 start_informed(struct client_state *client)
04996 {
04997         client->v6_handler = informed_handler;
04998 
04999         log_debug("PRC: Done.");
05000 
05001         client->state = S_BOUND;
05002 
05003         script_init(client, "RENEW6", NULL);
05004         if (client->old_lease != NULL)
05005                 script_write_params6(client, "old_",
05006                                      client->old_lease->options);
05007         script_write_params6(client, "new_", client->active_lease->options);
05008         script_write_requested6(client);
05009         script_go(client);
05010 
05011         go_daemon();
05012 
05013         if (client->old_lease != NULL) {
05014                 dhc6_lease_destroy(&client->old_lease, MDL);
05015                 client->old_lease = NULL;
05016         }
05017 
05018         /* Schedule events. */
05019         dhc6_check_irt(client);
05020 }
05021 
05022 /* While informed, ignore packets.
05023  */
05024 void
05025 informed_handler(struct packet *packet, struct client_state *client)
05026 {
05027         log_debug("RCV: Input packets are ignored once bound.");
05028 }
05029 
05030 /* make_client6_options() fetches option caches relevant to the client's
05031  * scope and places them into the sent_options cache.  This cache is later
05032  * used to populate DHCPv6 output packets with options.
05033  */
05034 static void
05035 make_client6_options(struct client_state *client, struct option_state **op,
05036                      struct dhc6_lease *lease, u_int8_t message)
05037 {
05038         struct option_cache *oc;
05039         struct option **req;
05040         struct buffer *buffer;
05041         int buflen, i, oro_len;
05042 
05043         if ((op == NULL) || (client == NULL))
05044                 return;
05045 
05046         if (*op)
05047                 option_state_dereference(op, MDL);
05048 
05049         /* Create a cache to carry options to transmission. */
05050         option_state_allocate(op, MDL);
05051 
05052         /* Create and store an 'elapsed time' option in the cache. */
05053         oc = NULL;
05054         if (option_cache_allocate(&oc, MDL)) {
05055                 const unsigned char *cdata;
05056 
05057                 cdata = (unsigned char *)&client->elapsed;
05058 
05059                 if (make_const_data(&oc->expression, cdata, 2, 0, 0, MDL)) {
05060                         option_reference(&oc->option, elapsed_option, MDL);
05061                         save_option(&dhcpv6_universe, *op, oc);
05062                 }
05063 
05064                 option_cache_dereference(&oc, MDL);
05065         }
05066 
05067         /* Bring in any configured options to send. */
05068         if (client->config->on_transmission)
05069                 execute_statements_in_scope(NULL, NULL, NULL, client,
05070                                             lease ? lease->options : NULL,
05071                                             *op, &global_scope,
05072                                             client->config->on_transmission,
05073                                             NULL, NULL);
05074 
05075         /* Rapid-commit is only for SOLICITs. */
05076         if (message != DHCPV6_SOLICIT)
05077                 delete_option(&dhcpv6_universe, *op, D6O_RAPID_COMMIT);
05078 
05079         /* See if the user configured a DUID in a relevant scope.  If not,
05080          * introduce our default manufactured id.
05081          */
05082         if ((oc = lookup_option(&dhcpv6_universe, *op,
05083                                 D6O_CLIENTID)) == NULL) {
05084                 if (default_duid.len == 0 ||
05085                     !option_cache(&oc, &default_duid, NULL, clientid_option,
05086                                   MDL))
05087                         log_fatal("Failure assembling a DUID.");
05088 
05089                 save_option(&dhcpv6_universe, *op, oc);
05090                 option_cache_dereference(&oc, MDL);
05091         }
05092 
05093         /* In cases where we're responding to a single server, put the
05094          * server's id in the response.
05095          *
05096          * Note that lease is NULL for SOLICIT or INFO request messages,
05097          * and otherwise MUST be present.
05098          */
05099         if (lease == NULL) {
05100                 if ((message != DHCPV6_SOLICIT) &&
05101                     (message != DHCPV6_INFORMATION_REQUEST))
05102                         log_fatal("Impossible condition at %s:%d.", MDL);
05103         } else if ((message != DHCPV6_REBIND) &&
05104                    (message != DHCPV6_CONFIRM)) {
05105                 oc = lookup_option(&dhcpv6_universe, lease->options,
05106                                    D6O_SERVERID);
05107                 if (oc != NULL)
05108                         save_option(&dhcpv6_universe, *op, oc);
05109         }
05110 
05111         /* 'send dhcp6.oro foo;' syntax we used in 4.0.0a1/a2 has been
05112          * deprecated by adjustments to the 'request' syntax also used for
05113          * DHCPv4.
05114          */
05115         if (lookup_option(&dhcpv6_universe, *op, D6O_ORO) != NULL)
05116                 log_error("'send dhcp6.oro' syntax is deprecated, please "
05117                           "use the 'request' syntax (\"man dhclient.conf\").");
05118 
05119         /* Construct and store an ORO (Option Request Option).  It is a
05120          * fatal error to fail to send an ORO (of at least zero length).
05121          *
05122          * Discussion:  RFC3315 appears to be inconsistent in its statements
05123          * of whether or not the ORO is mandatory.  In section 18.1.1
05124          * ("Creation and Transmission of Request Messages"):
05125          *
05126          *    The client MUST include an Option Request option (see section
05127          *    22.7) to indicate the options the client is interested in
05128          *    receiving.  The client MAY include options with data values as
05129          *    hints to the server about parameter values the client would like
05130          *    to have returned.
05131          *
05132          * This MUST is missing from the creation/transmission of other
05133          * messages (such as Renew and Rebind), and the section 22.7 ("Option
05134          * Request Option" format and definition):
05135          *
05136          *    A client MAY include an Option Request option in a Solicit,
05137          *    Request, Renew, Rebind, Confirm or Information-request message to
05138          *    inform the server about options the client wants the server to
05139          *    send to the client.  A server MAY include an Option Request
05140          *    option in a Reconfigure option to indicate which options the
05141          *    client should request from the server.
05142          *
05143          * seems to relax the requirement from MUST to MAY (and still other
05144          * language in RFC3315 supports this).
05145          *
05146          * In lieu of a clarification of RFC3315, we will conform with the
05147          * MUST.  Instead of an absent ORO, we will if there are no options
05148          * to request supply an empty ORO.  Theoretically, an absent ORO is
05149          * difficult to interpret (does the client want all options or no
05150          * options?).  A zero-length ORO is intuitively clear: requesting
05151          * nothing.
05152          */
05153         buffer = NULL;
05154         oro_len = 0;
05155         buflen = 32;
05156         if (!buffer_allocate(&buffer, buflen, MDL))
05157                 log_fatal("Out of memory constructing DHCPv6 ORO.");
05158         req = client->config->requested_options;
05159         if (req != NULL) {
05160                 for (i = 0 ; req[i] != NULL ; i++) {
05161                         if (buflen == oro_len) {
05162                                 struct buffer *tmpbuf = NULL;
05163 
05164                                 buflen += 32;
05165 
05166                                 /* Shell game. */
05167                                 buffer_reference(&tmpbuf, buffer, MDL);
05168                                 buffer_dereference(&buffer, MDL);
05169 
05170                                 if (!buffer_allocate(&buffer, buflen, MDL))
05171                                         log_fatal("Out of memory resizing "
05172                                                   "DHCPv6 ORO buffer.");
05173 
05174                                 memcpy(buffer->data, tmpbuf->data, oro_len);
05175 
05176                                 buffer_dereference(&tmpbuf, MDL);
05177                         }
05178 
05179                         if (req[i]->universe == &dhcpv6_universe) {
05180                                 /* Append the code to the ORO. */
05181                                 putUShort(buffer->data + oro_len,
05182                                           req[i]->code);
05183                                 oro_len += 2;
05184                         }
05185                 }
05186         }
05187 
05188         oc = NULL;
05189         if (make_const_option_cache(&oc, &buffer, NULL, oro_len,
05190                                     oro_option, MDL)) {
05191                 save_option(&dhcpv6_universe, *op, oc);
05192         } else {
05193                 log_fatal("Unable to create ORO option cache.");
05194         }
05195 
05196         /*
05197          * Note: make_const_option_cache() consumes the buffer, we do not
05198          * need to dereference it (XXX).
05199          */
05200         option_cache_dereference(&oc, MDL);
05201 }
05202 
05203 /* A clone of the DHCPv4 script_write_params() minus the DHCPv4-specific
05204  * filename, server-name, etc specifics.
05205  *
05206  * Simply, store all values present in all universes of the option state
05207  * (probably derived from a DHCPv6 packet) into environment variables
05208  * named after the option names (and universe names) but with the 'prefix'
05209  * prepended.
05210  *
05211  * Later, dhclient-script may compare for example "new_time_servers" and
05212  * "old_time_servers" for differences, and only upon detecting a change
05213  * bother to rewrite ntp.conf and restart it.  Or something along those
05214  * generic lines.
05215  */
05216 static void
05217 script_write_params6(struct client_state *client, const char *prefix,
05218                      struct option_state *options)
05219 {
05220         struct envadd_state es;
05221         int i;
05222 
05223         if (options == NULL)
05224                 return;
05225 
05226         es.client = client;
05227         es.prefix = prefix;
05228 
05229         for (i = 0 ; i < options->universe_count ; i++) {
05230                 option_space_foreach(NULL, NULL, client, NULL, options,
05231                                      &global_scope, universes[i], &es,
05232                                      client_option_envadd);
05233         }
05234 }
05235 
05236 /*
05237  * A clone of the DHCPv4 routine.
05238  * Write out the environment variables for the objects that the
05239  * client requested.  If the object was requested the variable will be:
05240  * requested_<option_name>=1
05241  * If it wasn't requested there won't be a variable.
05242  */
05243 static void script_write_requested6(client)
05244         struct client_state *client;
05245 {
05246         int i;
05247         struct option **req;
05248         char name[256];
05249         req = client->config->requested_options;
05250 
05251         if (req == NULL)
05252                 return;
05253 
05254         for (i = 0 ; req[i] != NULL ; i++) {
05255                 if ((req[i]->universe == &dhcpv6_universe) &&
05256                     dhcp_option_ev_name (name, sizeof(name), req[i])) {
05257                         client_envadd(client, "requested_", name, "%d", 1);
05258                 }
05259         }
05260 }
05261 
05262 /*
05263  * Check if there is something not fully defined in the active lease.
05264  */
05265 static isc_boolean_t
05266 active_prefix(struct client_state *client)
05267 {
05268         struct dhc6_lease *lease;
05269         struct dhc6_ia *ia;
05270         struct dhc6_addr *pref;
05271         char zeros[16];
05272 
05273         lease = client->active_lease;
05274         if (lease == NULL)
05275                 return ISC_FALSE;
05276         memset(zeros, 0, 16);
05277         for (ia = lease->bindings; ia != NULL; ia = ia->next) {
05278                 if (ia->ia_type != D6O_IA_PD)
05279                         continue;
05280                 for (pref = ia->addrs; pref != NULL; pref = pref->next) {
05281                         if (pref->plen == 0)
05282                                 return ISC_FALSE;
05283                         if (pref->address.len != 16)
05284                                 return ISC_FALSE;
05285                         if (memcmp(pref->address.iabuf, zeros, 16) == 0)
05286                                 return ISC_FALSE;
05287                 }
05288         }
05289         return ISC_TRUE;
05290 }
05291 #endif /* DHCPv6 */

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1