Home | History | Annotate | Line # | Download | only in client
      1  1.2  christos /*	$NetBSD: dhc6.c,v 1.4 2022/04/03 01:10:57 christos Exp $	*/
      2  1.1  christos 
      3  1.1  christos /* dhc6.c - DHCPv6 client routines. */
      4  1.1  christos 
      5  1.1  christos /*
      6  1.4  christos  * Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC")
      7  1.1  christos  * Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
      8  1.1  christos  *
      9  1.1  christos  * This Source Code Form is subject to the terms of the Mozilla Public
     10  1.1  christos  * License, v. 2.0. If a copy of the MPL was not distributed with this
     11  1.1  christos  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     12  1.1  christos  *
     13  1.1  christos  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     14  1.1  christos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     15  1.1  christos  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     16  1.1  christos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     17  1.1  christos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     18  1.1  christos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     19  1.1  christos  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     20  1.1  christos  *
     21  1.1  christos  *   Internet Systems Consortium, Inc.
     22  1.4  christos  *   PO Box 360
     23  1.4  christos  *   Newmarket, NH 03857 USA
     24  1.1  christos  *   <info (at) isc.org>
     25  1.1  christos  *   https://www.isc.org/
     26  1.1  christos  */
     27  1.1  christos 
     28  1.1  christos #include <sys/cdefs.h>
     29  1.2  christos __RCSID("$NetBSD: dhc6.c,v 1.4 2022/04/03 01:10:57 christos Exp $");
     30  1.1  christos 
     31  1.1  christos #include "dhcpd.h"
     32  1.1  christos 
     33  1.1  christos #ifdef DHCPv6
     34  1.1  christos 
     35  1.1  christos struct sockaddr_in6 DHCPv6DestAddr;
     36  1.1  christos 
     37  1.1  christos /*
     38  1.1  christos  * Option definition structures that are used by the software - declared
     39  1.1  christos  * here once and assigned at startup to save lookups.
     40  1.1  christos  */
     41  1.1  christos struct option *clientid_option = NULL;
     42  1.1  christos struct option *elapsed_option = NULL;
     43  1.1  christos struct option *ia_na_option = NULL;
     44  1.1  christos struct option *ia_ta_option = NULL;
     45  1.1  christos struct option *ia_pd_option = NULL;
     46  1.1  christos struct option *iaaddr_option = NULL;
     47  1.1  christos struct option *iaprefix_option = NULL;
     48  1.1  christos struct option *oro_option = NULL;
     49  1.1  christos struct option *irt_option = NULL;
     50  1.1  christos 
     51  1.1  christos static struct dhc6_lease *dhc6_dup_lease(struct dhc6_lease *lease,
     52  1.1  christos 					 const char *file, int line);
     53  1.1  christos static struct dhc6_ia *dhc6_dup_ia(struct dhc6_ia *ia,
     54  1.1  christos 				   const char *file, int line);
     55  1.1  christos static struct dhc6_addr *dhc6_dup_addr(struct dhc6_addr *addr,
     56  1.1  christos 				       const char *file, int line);
     57  1.1  christos static void dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line);
     58  1.1  christos static isc_result_t dhc6_parse_ia_na(struct dhc6_ia **pia,
     59  1.1  christos 				     struct packet *packet,
     60  1.1  christos 				     struct option_state *options,
     61  1.1  christos 				     unsigned code);
     62  1.1  christos static isc_result_t dhc6_parse_ia_ta(struct dhc6_ia **pia,
     63  1.1  christos 				     struct packet *packet,
     64  1.1  christos 				     struct option_state *options,
     65  1.1  christos 				     unsigned code);
     66  1.1  christos static isc_result_t dhc6_parse_ia_pd(struct dhc6_ia **pia,
     67  1.1  christos 				     struct packet *packet,
     68  1.1  christos 				     struct option_state *options,
     69  1.1  christos 				     unsigned code);
     70  1.1  christos static isc_result_t dhc6_parse_addrs(struct dhc6_addr **paddr,
     71  1.1  christos 				     struct packet *packet,
     72  1.1  christos 				     struct option_state *options);
     73  1.1  christos static isc_result_t dhc6_parse_prefixes(struct dhc6_addr **ppref,
     74  1.1  christos 					struct packet *packet,
     75  1.1  christos 					struct option_state *options);
     76  1.1  christos static struct dhc6_ia *find_ia(struct dhc6_ia *head,
     77  1.1  christos 			       u_int16_t type, const char *id);
     78  1.1  christos static struct dhc6_addr *find_addr(struct dhc6_addr *head,
     79  1.1  christos 				   struct iaddr *address);
     80  1.1  christos static struct dhc6_addr *find_pref(struct dhc6_addr *head,
     81  1.1  christos 				   struct iaddr *prefix, u_int8_t plen);
     82  1.1  christos void init_handler(struct packet *packet, struct client_state *client);
     83  1.1  christos void info_request_handler(struct packet *packet, struct client_state *client);
     84  1.1  christos void rapid_commit_handler(struct packet *packet, struct client_state *client);
     85  1.1  christos void do_init6(void *input);
     86  1.1  christos void do_info_request6(void *input);
     87  1.1  christos void do_confirm6(void *input);
     88  1.1  christos void reply_handler(struct packet *packet, struct client_state *client);
     89  1.1  christos static isc_result_t dhc6_create_iaid(struct client_state *client,
     90  1.1  christos 				     struct data_string *ia,
     91  1.1  christos 				     int idx,
     92  1.1  christos 				     unsigned len);
     93  1.1  christos static int dhc6_count_ia(struct dhc6_lease *lease,
     94  1.1  christos 			 u_int16_t ia_type);
     95  1.1  christos static isc_result_t dhc6_bare_ia_xx(struct client_state *client,
     96  1.1  christos 				    struct data_string *packet,
     97  1.1  christos 				    int wanted,
     98  1.1  christos 				    u_int16_t ia_type);
     99  1.1  christos static isc_result_t dhc6_add_ia_na(struct client_state *client,
    100  1.1  christos 				   struct data_string *packet,
    101  1.1  christos 				   struct dhc6_lease *lease,
    102  1.1  christos 				   u_int8_t message,
    103  1.1  christos 				   int wanted,
    104  1.1  christos 				   int *added);
    105  1.1  christos static isc_result_t dhc6_add_ia_ta(struct client_state *client,
    106  1.1  christos 				   struct data_string *packet,
    107  1.1  christos 				   struct dhc6_lease *lease,
    108  1.1  christos 				   u_int8_t message,
    109  1.1  christos 				   int wanted,
    110  1.1  christos 				   int *added);
    111  1.1  christos static isc_result_t dhc6_add_ia_pd(struct client_state *client,
    112  1.1  christos 				   struct data_string *packet,
    113  1.1  christos 				   struct dhc6_lease *lease,
    114  1.1  christos 				   u_int8_t message,
    115  1.1  christos 				   int wanted,
    116  1.1  christos 				   int *added);
    117  1.1  christos static isc_boolean_t stopping_finished(void);
    118  1.1  christos static void dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst);
    119  1.1  christos void do_select6(void *input);
    120  1.1  christos void do_refresh6(void *input);
    121  1.1  christos static void do_release6(void *input);
    122  1.1  christos static void start_bound(struct client_state *client);
    123  1.1  christos static void start_decline6(struct client_state *client);
    124  1.1  christos static void do_decline6(void *input);
    125  1.1  christos static void start_informed(struct client_state *client);
    126  1.1  christos void informed_handler(struct packet *packet, struct client_state *client);
    127  1.1  christos void bound_handler(struct packet *packet, struct client_state *client);
    128  1.1  christos void start_renew6(void *input);
    129  1.1  christos void start_rebind6(void *input);
    130  1.1  christos void do_depref(void *input);
    131  1.1  christos void do_expire(void *input);
    132  1.1  christos static void make_client6_options(struct client_state *client,
    133  1.1  christos 				 struct option_state **op,
    134  1.1  christos 				 struct dhc6_lease *lease, u_int8_t message);
    135  1.1  christos static void script_write_params6(struct client_state *client,
    136  1.1  christos 				 const char *prefix,
    137  1.1  christos 				 struct option_state *options);
    138  1.1  christos static void script_write_requested6(struct client_state *client);
    139  1.1  christos static isc_boolean_t active_prefix(struct client_state *client);
    140  1.1  christos 
    141  1.1  christos static int check_timing6(struct client_state *client, u_int8_t msg_type,
    142  1.1  christos 			 char *msg_str, struct dhc6_lease *lease,
    143  1.1  christos 			 struct data_string *ds);
    144  1.1  christos static isc_result_t dhc6_get_status_code(struct option_state *options,
    145  1.1  christos 					 unsigned *code,
    146  1.1  christos 					 struct data_string *msg);
    147  1.1  christos static isc_result_t dhc6_check_status(isc_result_t rval,
    148  1.1  christos 				      struct option_state *options,
    149  1.1  christos 				      const char *scope,
    150  1.1  christos 				      unsigned *code);
    151  1.1  christos static int dhc6_score_lease(struct client_state *client,
    152  1.1  christos 			    struct dhc6_lease *lease);
    153  1.1  christos static isc_result_t dhc6_add_ia_na_decline(struct client_state *client,
    154  1.1  christos 					   struct data_string *packet,
    155  1.1  christos 					   struct dhc6_lease *lease);
    156  1.1  christos static int drop_declined_addrs(struct dhc6_lease *lease);
    157  1.1  christos static isc_boolean_t unexpired_address_in_lease(struct dhc6_lease *lease);
    158  1.1  christos 
    159  1.1  christos extern int onetry;
    160  1.1  christos extern int stateless;
    161  1.1  christos extern int prefix_len_hint;
    162  1.1  christos extern int address_prefix_len;
    163  1.1  christos 
    164  1.1  christos /*
    165  1.1  christos  * Assign DHCPv6 port numbers as a client.
    166  1.1  christos  */
    167  1.1  christos void
    168  1.1  christos dhcpv6_client_assignments(void)
    169  1.1  christos {
    170  1.1  christos 	struct servent *ent;
    171  1.1  christos 	unsigned code;
    172  1.1  christos 
    173  1.1  christos 	if (path_dhclient_pid == NULL)
    174  1.1  christos 		path_dhclient_pid = _PATH_DHCLIENT6_PID;
    175  1.1  christos 	if (path_dhclient_db == NULL)
    176  1.1  christos 		path_dhclient_db = _PATH_DHCLIENT6_DB;
    177  1.1  christos 
    178  1.1  christos 	if (local_port == 0) {
    179  1.1  christos 		ent = getservbyname("dhcpv6-client", "udp");
    180  1.1  christos 		if (ent == NULL)
    181  1.1  christos 			local_port = htons(546);
    182  1.1  christos 		else
    183  1.1  christos 			local_port = ent->s_port;
    184  1.1  christos 	}
    185  1.1  christos 
    186  1.1  christos 	if (remote_port == 0) {
    187  1.1  christos 		ent = getservbyname("dhcpv6-server", "udp");
    188  1.1  christos 		if (ent == NULL)
    189  1.1  christos 			remote_port = htons(547);
    190  1.1  christos 		else
    191  1.1  christos 			remote_port = ent->s_port;
    192  1.1  christos 	}
    193  1.1  christos 
    194  1.1  christos 	memset(&DHCPv6DestAddr, 0, sizeof(DHCPv6DestAddr));
    195  1.1  christos 	DHCPv6DestAddr.sin6_family = AF_INET6;
    196  1.1  christos 	DHCPv6DestAddr.sin6_port = remote_port;
    197  1.1  christos 	if (inet_pton(AF_INET6, All_DHCP_Relay_Agents_and_Servers,
    198  1.1  christos 		      &DHCPv6DestAddr.sin6_addr) <= 0) {
    199  1.1  christos 		log_fatal("Bad address %s", All_DHCP_Relay_Agents_and_Servers);
    200  1.1  christos 	}
    201  1.1  christos 
    202  1.1  christos 	code = D6O_CLIENTID;
    203  1.1  christos 	if (!option_code_hash_lookup(&clientid_option,
    204  1.1  christos 				     dhcpv6_universe.code_hash, &code, 0, MDL))
    205  1.1  christos 		log_fatal("Unable to find the CLIENTID option definition.");
    206  1.1  christos 
    207  1.1  christos 	code = D6O_ELAPSED_TIME;
    208  1.1  christos 	if (!option_code_hash_lookup(&elapsed_option,
    209  1.1  christos 				     dhcpv6_universe.code_hash, &code, 0, MDL))
    210  1.1  christos 		log_fatal("Unable to find the ELAPSED_TIME option definition.");
    211  1.1  christos 
    212  1.1  christos 	code = D6O_IA_NA;
    213  1.1  christos 	if (!option_code_hash_lookup(&ia_na_option, dhcpv6_universe.code_hash,
    214  1.1  christos 				     &code, 0, MDL))
    215  1.1  christos 		log_fatal("Unable to find the IA_NA option definition.");
    216  1.1  christos 
    217  1.1  christos 	code = D6O_IA_TA;
    218  1.1  christos 	if (!option_code_hash_lookup(&ia_ta_option, dhcpv6_universe.code_hash,
    219  1.1  christos 				     &code, 0, MDL))
    220  1.1  christos 		log_fatal("Unable to find the IA_TA option definition.");
    221  1.1  christos 
    222  1.1  christos 	code = D6O_IA_PD;
    223  1.1  christos 	if (!option_code_hash_lookup(&ia_pd_option, dhcpv6_universe.code_hash,
    224  1.1  christos 				     &code, 0, MDL))
    225  1.1  christos 		log_fatal("Unable to find the IA_PD option definition.");
    226  1.1  christos 
    227  1.1  christos 	code = D6O_IAADDR;
    228  1.1  christos 	if (!option_code_hash_lookup(&iaaddr_option, dhcpv6_universe.code_hash,
    229  1.1  christos 				     &code, 0, MDL))
    230  1.1  christos 		log_fatal("Unable to find the IAADDR option definition.");
    231  1.1  christos 
    232  1.1  christos 	code = D6O_IAPREFIX;
    233  1.1  christos 	if (!option_code_hash_lookup(&iaprefix_option,
    234  1.1  christos 				     dhcpv6_universe.code_hash,
    235  1.1  christos 				     &code, 0, MDL))
    236  1.1  christos 		log_fatal("Unable to find the IAPREFIX option definition.");
    237  1.1  christos 
    238  1.1  christos 	code = D6O_ORO;
    239  1.1  christos 	if (!option_code_hash_lookup(&oro_option, dhcpv6_universe.code_hash,
    240  1.1  christos 				     &code, 0, MDL))
    241  1.1  christos 		log_fatal("Unable to find the ORO option definition.");
    242  1.1  christos 
    243  1.1  christos 	code = D6O_INFORMATION_REFRESH_TIME;
    244  1.1  christos 	if (!option_code_hash_lookup(&irt_option, dhcpv6_universe.code_hash,
    245  1.1  christos 				     &code, 0, MDL))
    246  1.1  christos 		log_fatal("Unable to find the IRT option definition.");
    247  1.1  christos 
    248  1.1  christos #ifndef __CYGWIN32__ /* XXX */
    249  1.1  christos 	endservent();
    250  1.1  christos #endif
    251  1.1  christos }
    252  1.1  christos 
    253  1.1  christos /*
    254  1.1  christos  * Instead of implementing RFC3315 RAND (section 14) as a float "between"
    255  1.1  christos  * -0.1 and 0.1 non-inclusive, we implement it as an integer.
    256  1.1  christos  *
    257  1.1  christos  * The result is expected to follow this table:
    258  1.1  christos  *
    259  1.1  christos  *		split range answer
    260  1.1  christos  *		    - ERROR -		      base <= 0
    261  1.1  christos  *		0	1   0..0	 1 <= base <= 10
    262  1.1  christos  *		1	3  -1..1	11 <= base <= 20
    263  1.1  christos  *		2	5  -2..2	21 <= base <= 30
    264  1.1  christos  *		3	7  -3..3	31 <= base <= 40
    265  1.1  christos  *		...
    266  1.1  christos  *
    267  1.1  christos  * XXX: For this to make sense, we really need to do timing on a
    268  1.1  christos  * XXX: usec scale...we currently can assume zero for any value less than
    269  1.1  christos  * XXX: 11, which are very common in early stages of transmission for most
    270  1.1  christos  * XXX: messages.
    271  1.1  christos  */
    272  1.1  christos static TIME
    273  1.1  christos dhc6_rand(TIME base)
    274  1.1  christos {
    275  1.1  christos 	TIME rval;
    276  1.1  christos 	TIME range;
    277  1.1  christos 	TIME split;
    278  1.1  christos 
    279  1.1  christos 	/*
    280  1.1  christos 	 * A zero or less timeout is a bad thing...we don't want to
    281  1.1  christos 	 * DHCP-flood anyone.
    282  1.1  christos 	 */
    283  1.1  christos 	if (base <= 0)
    284  1.1  christos 		log_fatal("Impossible condition at %s:%d.", MDL);
    285  1.1  christos 
    286  1.1  christos 	/*
    287  1.1  christos 	 * The first thing we do is count how many random integers we want
    288  1.1  christos 	 * in either direction (best thought of as the maximum negative
    289  1.1  christos 	 * integer, as we will subtract this potentially from a random 0).
    290  1.1  christos 	 */
    291  1.1  christos 	split = (base - 1) / 10;
    292  1.1  christos 
    293  1.1  christos 	/* Don't bother with the rest of the math if we know we'll get 0. */
    294  1.1  christos 	if (split == 0)
    295  1.1  christos 		return 0;
    296  1.1  christos 
    297  1.1  christos 	/*
    298  1.1  christos 	 * Then we count the total number of integers in this set.  This
    299  1.1  christos 	 * is twice the number of integers in positive and negative
    300  1.1  christos 	 * directions, plus zero (-1, 0, 1 is 3, -2..2 adds 2 to 5, so forth).
    301  1.1  christos 	 */
    302  1.1  christos 	range = (split * 2) + 1;
    303  1.1  christos 
    304  1.1  christos 	/* Take a random number from [0..(range-1)]. */
    305  1.1  christos 	rval = random();
    306  1.1  christos 	rval %= range;
    307  1.1  christos 
    308  1.1  christos 	/* Offset it to uncover potential negative values. */
    309  1.1  christos 	rval -= split;
    310  1.1  christos 
    311  1.1  christos 	return rval;
    312  1.1  christos }
    313  1.1  christos 
    314  1.1  christos /* Initialize message exchange timers (set RT from Initial-RT). */
    315  1.1  christos static void
    316  1.1  christos dhc6_retrans_init(struct client_state *client)
    317  1.1  christos {
    318  1.1  christos 	int xid;
    319  1.1  christos 
    320  1.1  christos 	/* Initialize timers. */
    321  1.1  christos 	client->txcount = 0;
    322  1.1  christos 	client->RT = client->IRT + dhc6_rand(client->IRT);
    323  1.1  christos 
    324  1.1  christos 	/* Generate a new random 24-bit transaction ID for this exchange. */
    325  1.1  christos 
    326  1.1  christos #if (RAND_MAX >= 0x00ffffff)
    327  1.1  christos 	xid = random();
    328  1.1  christos #elif (RAND_MAX >= 0x0000ffff)
    329  1.1  christos 	xid = (random() << 16) ^ random();
    330  1.1  christos #elif (RAND_MAX >= 0x000000ff)
    331  1.1  christos 	xid = (random() << 16) ^ (random() << 8) ^ random();
    332  1.1  christos #else
    333  1.1  christos # error "Random number generator of less than 8 bits not supported."
    334  1.1  christos #endif
    335  1.1  christos 
    336  1.1  christos 	client->dhcpv6_transaction_id[0] = (xid >> 16) & 0xff;
    337  1.1  christos 	client->dhcpv6_transaction_id[1] = (xid >>  8) & 0xff;
    338  1.1  christos 	client->dhcpv6_transaction_id[2] =  xid        & 0xff;
    339  1.1  christos }
    340  1.1  christos 
    341  1.1  christos /* Advance the DHCPv6 retransmission state once. */
    342  1.1  christos static void
    343  1.1  christos dhc6_retrans_advance(struct client_state *client)
    344  1.1  christos {
    345  1.1  christos 	struct timeval elapsed, elapsed_plus_rt;
    346  1.1  christos 
    347  1.1  christos 	/* elapsed = cur - start */
    348  1.1  christos 	elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
    349  1.1  christos 	elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
    350  1.1  christos 	if (elapsed.tv_usec < 0) {
    351  1.1  christos 		elapsed.tv_sec -= 1;
    352  1.1  christos 		elapsed.tv_usec += 1000000;
    353  1.1  christos 	}
    354  1.1  christos 	/* retrans_advance is called after consuming client->RT. */
    355  1.1  christos 	/* elapsed += RT */
    356  1.1  christos 	elapsed.tv_sec += client->RT / 100;
    357  1.1  christos 	elapsed.tv_usec += (client->RT % 100) * 10000;
    358  1.1  christos 	if (elapsed.tv_usec >= 1000000) {
    359  1.1  christos 		elapsed.tv_sec += 1;
    360  1.1  christos 		elapsed.tv_usec -= 1000000;
    361  1.1  christos 	}
    362  1.1  christos 	/*
    363  1.1  christos 	 * Save what the time will be after the current RT to determine
    364  1.1  christos 	 * what the delta to MRD will be.
    365  1.1  christos 	 */
    366  1.1  christos 	elapsed_plus_rt.tv_sec = elapsed.tv_sec;
    367  1.1  christos 	elapsed_plus_rt.tv_usec = elapsed.tv_usec;
    368  1.1  christos 
    369  1.1  christos 	/*
    370  1.1  christos 	 * RT for each subsequent message transmission is based on the previous
    371  1.1  christos 	 * value of RT:
    372  1.1  christos 	 *
    373  1.1  christos 	 *    RT = 2*RTprev + RAND*RTprev
    374  1.1  christos 	 */
    375  1.1  christos 	client->RT += client->RT + dhc6_rand(client->RT);
    376  1.1  christos 
    377  1.1  christos 	/*
    378  1.1  christos 	 * MRT specifies an upper bound on the value of RT (disregarding the
    379  1.1  christos 	 * randomization added by the use of RAND).  If MRT has a value of 0,
    380  1.1  christos 	 * there is no upper limit on the value of RT.  Otherwise:
    381  1.1  christos 	 *
    382  1.1  christos 	 *    if (RT > MRT)
    383  1.1  christos 	 *       RT = MRT + RAND*MRT
    384  1.1  christos 	 */
    385  1.1  christos 	if ((client->MRT != 0) && (client->RT > client->MRT))
    386  1.1  christos 		client->RT = client->MRT + dhc6_rand(client->MRT);
    387  1.1  christos 
    388  1.1  christos 	/*
    389  1.1  christos 	 * Further, if there's an MRD, we should wake up upon reaching
    390  1.1  christos 	 * the MRD rather than at some point after it.
    391  1.1  christos 	 */
    392  1.1  christos 	if (client->MRD == 0) {
    393  1.1  christos 		/* Done. */
    394  1.1  christos 		client->txcount++;
    395  1.1  christos 		return;
    396  1.1  christos 	}
    397  1.1  christos 	/* elapsed += client->RT */
    398  1.1  christos 	elapsed.tv_sec += client->RT / 100;
    399  1.1  christos 	elapsed.tv_usec += (client->RT % 100) * 10000;
    400  1.1  christos 	if (elapsed.tv_usec >= 1000000) {
    401  1.1  christos 		elapsed.tv_sec += 1;
    402  1.1  christos 		elapsed.tv_usec -= 1000000;
    403  1.1  christos 	}
    404  1.1  christos 	if (elapsed.tv_sec >= client->MRD) {
    405  1.1  christos 		/*
    406  1.1  christos 		 * The desired RT is the time that will be remaining in MRD
    407  1.1  christos 		 * when the current timeout finishes.  We then have
    408  1.1  christos 		 * desired RT = MRD - (elapsed time + previous RT); or
    409  1.1  christos 		 * desired RT = MRD - elapsed_plut_rt;
    410  1.1  christos 		 */
    411  1.1  christos 		client->RT = client->MRD - elapsed_plus_rt.tv_sec;
    412  1.1  christos 		client->RT = (client->RT * 100) -
    413  1.1  christos 			(elapsed_plus_rt.tv_usec / 10000);
    414  1.1  christos 		if (client->RT < 0)
    415  1.1  christos 			client->RT = 0;
    416  1.1  christos 	}
    417  1.1  christos 	client->txcount++;
    418  1.1  christos }
    419  1.1  christos 
    420  1.1  christos /* Quick validation of DHCPv6 ADVERTISE packet contents. */
    421  1.1  christos static int
    422  1.1  christos valid_reply(struct packet *packet, struct client_state *client)
    423  1.1  christos {
    424  1.1  christos 	struct data_string sid, cid;
    425  1.1  christos 	struct option_cache *oc;
    426  1.1  christos 	int rval = ISC_TRUE;
    427  1.1  christos 
    428  1.1  christos 	memset(&sid, 0, sizeof(sid));
    429  1.1  christos 	memset(&cid, 0, sizeof(cid));
    430  1.1  christos 
    431  1.1  christos 	if (!lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID)) {
    432  1.1  christos 		log_error("Response without a server identifier received.");
    433  1.1  christos 		rval = ISC_FALSE;
    434  1.1  christos 	}
    435  1.1  christos 
    436  1.1  christos 	oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
    437  1.1  christos 	if (!oc ||
    438  1.1  christos 	    !evaluate_option_cache(&sid, packet, NULL, client, packet->options,
    439  1.1  christos 				   client->sent_options, &global_scope, oc,
    440  1.1  christos 				   MDL)) {
    441  1.1  christos 		log_error("Response without a client identifier.");
    442  1.1  christos 		rval = ISC_FALSE;
    443  1.1  christos 	}
    444  1.1  christos 
    445  1.1  christos 	oc = lookup_option(&dhcpv6_universe, client->sent_options,
    446  1.1  christos 			   D6O_CLIENTID);
    447  1.1  christos 	if (!oc ||
    448  1.1  christos 	    !evaluate_option_cache(&cid, packet, NULL, client,
    449  1.1  christos 				   client->sent_options, NULL, &global_scope,
    450  1.1  christos 				   oc, MDL)) {
    451  1.1  christos 		log_error("Local client identifier is missing!");
    452  1.1  christos 		rval = ISC_FALSE;
    453  1.1  christos 	}
    454  1.1  christos 
    455  1.1  christos 	if (sid.len == 0 ||
    456  1.1  christos 	    sid.len != cid.len ||
    457  1.1  christos 	    memcmp(sid.data, cid.data, sid.len)) {
    458  1.1  christos 		log_error("Advertise with matching transaction ID, but "
    459  1.1  christos 			  "mismatching client id.");
    460  1.1  christos 		rval = ISC_FALSE;
    461  1.1  christos 	}
    462  1.1  christos 
    463  1.1  christos 	/* clean up pointers to the strings */
    464  1.1  christos 	if (sid.data != NULL)
    465  1.1  christos 		data_string_forget(&sid, MDL);
    466  1.1  christos 	if (cid.data != NULL)
    467  1.1  christos 		data_string_forget(&cid, MDL);
    468  1.1  christos 
    469  1.1  christos 	return rval;
    470  1.1  christos }
    471  1.1  christos 
    472  1.1  christos /*
    473  1.1  christos  * Create a complete copy of a DHCPv6 lease structure.
    474  1.1  christos  */
    475  1.1  christos static struct dhc6_lease *
    476  1.1  christos dhc6_dup_lease(struct dhc6_lease *lease, const char *file, int line)
    477  1.1  christos {
    478  1.1  christos 	struct dhc6_lease *copy;
    479  1.1  christos 	struct dhc6_ia **insert_ia, *ia;
    480  1.1  christos 
    481  1.1  christos 	copy = dmalloc(sizeof(*copy), file, line);
    482  1.1  christos 	if (copy == NULL) {
    483  1.1  christos 		log_error("Out of memory for v6 lease structure.");
    484  1.1  christos 		return NULL;
    485  1.1  christos 	}
    486  1.1  christos 
    487  1.1  christos 	data_string_copy(&copy->server_id, &lease->server_id, file, line);
    488  1.1  christos 	copy->pref = lease->pref;
    489  1.1  christos 
    490  1.1  christos 	memcpy(copy->dhcpv6_transaction_id, lease->dhcpv6_transaction_id,
    491  1.1  christos 	       sizeof(copy->dhcpv6_transaction_id));
    492  1.1  christos 
    493  1.1  christos 	option_state_reference(&copy->options, lease->options, file, line);
    494  1.1  christos 
    495  1.1  christos 	insert_ia = &copy->bindings;
    496  1.1  christos 	for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
    497  1.1  christos 		*insert_ia = dhc6_dup_ia(ia, file, line);
    498  1.1  christos 
    499  1.1  christos 		if (*insert_ia == NULL) {
    500  1.1  christos 			dhc6_lease_destroy(&copy, file, line);
    501  1.1  christos 			return NULL;
    502  1.1  christos 		}
    503  1.1  christos 
    504  1.1  christos 		insert_ia = &(*insert_ia)->next;
    505  1.1  christos 	}
    506  1.1  christos 
    507  1.1  christos 	return copy;
    508  1.1  christos }
    509  1.1  christos 
    510  1.1  christos /*
    511  1.1  christos  * Duplicate an IA structure.
    512  1.1  christos  */
    513  1.1  christos static struct dhc6_ia *
    514  1.1  christos dhc6_dup_ia(struct dhc6_ia *ia, const char *file, int line)
    515  1.1  christos {
    516  1.1  christos 	struct dhc6_ia *copy;
    517  1.1  christos 	struct dhc6_addr **insert_addr, *addr;
    518  1.1  christos 
    519  1.1  christos 	copy = dmalloc(sizeof(*ia), file, line);
    520  1.1  christos 	if (copy == NULL) {
    521  1.1  christos 		log_error("Out of memory for v6 duplicate IA structure.");
    522  1.1  christos 		return NULL;
    523  1.1  christos 	}
    524  1.1  christos 
    525  1.1  christos 	memcpy(copy->iaid, ia->iaid, sizeof(copy->iaid));
    526  1.1  christos 
    527  1.1  christos 	copy->ia_type = ia->ia_type;
    528  1.1  christos 	copy->starts = ia->starts;
    529  1.1  christos 	copy->renew = ia->renew;
    530  1.1  christos 	copy->rebind = ia->rebind;
    531  1.1  christos 
    532  1.1  christos 	insert_addr = &copy->addrs;
    533  1.1  christos 	for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
    534  1.1  christos 		*insert_addr = dhc6_dup_addr(addr, file, line);
    535  1.1  christos 
    536  1.1  christos 		if (*insert_addr == NULL) {
    537  1.1  christos 			dhc6_ia_destroy(&copy, file, line);
    538  1.1  christos 			return NULL;
    539  1.1  christos 		}
    540  1.1  christos 
    541  1.1  christos 		insert_addr = &(*insert_addr)->next;
    542  1.1  christos 	}
    543  1.1  christos 
    544  1.1  christos 	if (ia->options != NULL)
    545  1.1  christos 		option_state_reference(&copy->options, ia->options,
    546  1.1  christos 				       file, line);
    547  1.1  christos 
    548  1.1  christos 	return copy;
    549  1.1  christos }
    550  1.1  christos 
    551  1.1  christos /*
    552  1.1  christos  * Duplicate an IAADDR or IAPREFIX structure.
    553  1.1  christos  */
    554  1.1  christos static struct dhc6_addr *
    555  1.1  christos dhc6_dup_addr(struct dhc6_addr *addr, const char *file, int line)
    556  1.1  christos {
    557  1.1  christos 	struct dhc6_addr *copy;
    558  1.1  christos 
    559  1.1  christos 	copy = dmalloc(sizeof(*addr), file, line);
    560  1.1  christos 
    561  1.1  christos 	if (copy == NULL)
    562  1.1  christos 		return NULL;
    563  1.1  christos 
    564  1.1  christos 	memcpy(&copy->address, &addr->address, sizeof(copy->address));
    565  1.1  christos 
    566  1.1  christos 	copy->plen = addr->plen;
    567  1.1  christos 	copy->flags = addr->flags;
    568  1.1  christos 	copy->starts = addr->starts;
    569  1.1  christos 	copy->preferred_life = addr->preferred_life;
    570  1.1  christos 	copy->max_life = addr->max_life;
    571  1.1  christos 
    572  1.1  christos 	if (addr->options != NULL)
    573  1.1  christos 		option_state_reference(&copy->options, addr->options,
    574  1.1  christos 				       file, line);
    575  1.1  christos 
    576  1.1  christos 	return copy;
    577  1.1  christos }
    578  1.1  christos 
    579  1.1  christos /*
    580  1.1  christos  * Form a DHCPv6 lease structure based upon packet contents.  Creates and
    581  1.1  christos  * populates IA's and any IAADDR/IAPREFIX's they contain.
    582  1.1  christos  * Parsed options are deleted in order to not save them in the lease file.
    583  1.1  christos  *
    584  1.1  christos  * If we get a status code of NoAddrs or NoPrefix we toss the affected
    585  1.1  christos  * IAs.  If it as at the top level we toss all IAs of that type.  If it
    586  1.1  christos  * is in an IA we only toss that one.  According to the spec we shouldn't
    587  1.1  christos  * get a NoPrefix status at the top level but we will allow it.
    588  1.1  christos  *
    589  1.1  christos  */
    590  1.1  christos static struct dhc6_lease *
    591  1.1  christos dhc6_leaseify(struct packet *packet, struct client_state* client)
    592  1.1  christos {
    593  1.1  christos 	struct data_string ds;
    594  1.1  christos 	struct dhc6_lease *lease;
    595  1.1  christos 	struct option_cache *oc;
    596  1.1  christos 	unsigned code;
    597  1.1  christos 
    598  1.1  christos 	lease = dmalloc(sizeof(*lease), MDL);
    599  1.1  christos 	if (lease == NULL) {
    600  1.1  christos 		log_error("Out of memory for v6 lease structure.");
    601  1.1  christos 		return NULL;
    602  1.1  christos 	}
    603  1.1  christos 
    604  1.1  christos 	memcpy(lease->dhcpv6_transaction_id, packet->dhcpv6_transaction_id, 3);
    605  1.1  christos 	option_state_reference(&lease->options, packet->options, MDL);
    606  1.1  christos 
    607  1.1  christos 	memset(&ds, 0, sizeof(ds));
    608  1.1  christos 
    609  1.1  christos 	/* Determine preference (default zero). */
    610  1.1  christos 	oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
    611  1.1  christos 	if (oc &&
    612  1.1  christos 	    evaluate_option_cache(&ds, packet, NULL, NULL, lease->options,
    613  1.1  christos 				  NULL, &global_scope, oc, MDL)) {
    614  1.1  christos 		if (ds.len != 1) {
    615  1.1  christos 			log_error("Invalid length of DHCPv6 Preference option "
    616  1.1  christos 				  "(%d != 1)", ds.len);
    617  1.1  christos 			data_string_forget(&ds, MDL);
    618  1.1  christos 			dhc6_lease_destroy(&lease, MDL);
    619  1.1  christos 			return NULL;
    620  1.1  christos 		} else {
    621  1.1  christos 			lease->pref = ds.data[0];
    622  1.1  christos 			log_debug("RCV:  X-- Preference %u.",
    623  1.1  christos 				  (unsigned)lease->pref);
    624  1.1  christos 		}
    625  1.1  christos 
    626  1.1  christos 		data_string_forget(&ds, MDL);
    627  1.1  christos 	}
    628  1.1  christos 	delete_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
    629  1.1  christos 
    630  1.1  christos 	/* Get the top level status code.  If the code is NoAddrsAvail
    631  1.1  christos 	 * or NoPrefixAvail strip it from the options as we don't
    632  1.1  christos 	 * want it to show up in check_[advertise reply].  We
    633  1.1  christos 	 * pass it along to the parse_ia_xx routines and they
    634  1.1  christos 	 * will drop the affected IAs for NoAddrs or NoPrefix,
    635  1.1  christos 	 * other status codes will be ignored and handled by
    636  1.1  christos 	 * the check_[advertise reply] routines.
    637  1.1  christos 	 */
    638  1.1  christos 	code = STATUS_Success;
    639  1.1  christos 	if ((dhc6_get_status_code(lease->options, &code, NULL) == ISC_R_SUCCESS)
    640  1.1  christos 	    &&
    641  1.1  christos 	    ((code == STATUS_NoAddrsAvail) || (code == STATUS_NoPrefixAvail))) {
    642  1.1  christos 		delete_option(&dhcpv6_universe, lease->options,
    643  1.1  christos 			      D6O_STATUS_CODE);
    644  1.1  christos 	}
    645  1.1  christos 
    646  1.1  christos 	/*
    647  1.1  christos 	 * Dig into recursive DHCPv6 pockets for IA_NA and contained IAADDR
    648  1.1  christos 	 * options.
    649  1.1  christos 	 */
    650  1.1  christos 	if (dhc6_parse_ia_na(&lease->bindings, packet,
    651  1.1  christos 			     lease->options, code) != ISC_R_SUCCESS) {
    652  1.1  christos 		/* Error conditions are logged by the caller. */
    653  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
    654  1.1  christos 		return NULL;
    655  1.1  christos 	}
    656  1.1  christos 	/*
    657  1.1  christos 	 * Dig into recursive DHCPv6 pockets for IA_TA and contained IAADDR
    658  1.1  christos 	 * options.
    659  1.1  christos 	 */
    660  1.1  christos 	if (dhc6_parse_ia_ta(&lease->bindings, packet,
    661  1.1  christos 			     lease->options, code) != ISC_R_SUCCESS) {
    662  1.1  christos 		/* Error conditions are logged by the caller. */
    663  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
    664  1.1  christos 		return NULL;
    665  1.1  christos 	}
    666  1.1  christos 	/*
    667  1.1  christos 	 * Dig into recursive DHCPv6 pockets for IA_PD and contained IAPREFIX
    668  1.1  christos 	 * options.
    669  1.1  christos 	 */
    670  1.1  christos 	if (dhc6_parse_ia_pd(&lease->bindings, packet,
    671  1.1  christos 			     lease->options, code) != ISC_R_SUCCESS) {
    672  1.1  christos 		/* Error conditions are logged by the caller. */
    673  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
    674  1.1  christos 		return NULL;
    675  1.1  christos 	}
    676  1.1  christos 
    677  1.1  christos 	/*
    678  1.1  christos 	 * This is last because in the future we may want to make a different
    679  1.1  christos 	 * key based upon additional information from the packet (we may need
    680  1.1  christos 	 * to allow multiple leases in one client state per server, but we're
    681  1.1  christos 	 * not sure based on what additional keys now).
    682  1.1  christos 	 */
    683  1.1  christos 	oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
    684  1.1  christos 	if ((oc == NULL) ||
    685  1.1  christos 	    !evaluate_option_cache(&lease->server_id, packet, NULL, NULL,
    686  1.1  christos 				   lease->options, NULL, &global_scope,
    687  1.1  christos 				   oc, MDL) ||
    688  1.1  christos 	    lease->server_id.len == 0) {
    689  1.1  christos 		/* This should be impossible due to validation checks earlier.
    690  1.1  christos 		 */
    691  1.1  christos 		log_error("Invalid SERVERID option cache.");
    692  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
    693  1.1  christos 		return NULL;
    694  1.1  christos 	} else {
    695  1.1  christos 		log_debug("RCV:  X-- Server ID: %s",
    696  1.1  christos 			  print_hex_1(lease->server_id.len,
    697  1.1  christos 				      lease->server_id.data, 52));
    698  1.1  christos 	}
    699  1.1  christos 
    700  1.1  christos 	execute_statements_in_scope(NULL, (struct packet *)packet, NULL,
    701  1.1  christos 				    client, lease->options, lease->options,
    702  1.1  christos 				    &global_scope, client->config->on_receipt,
    703  1.1  christos 				    NULL, NULL);
    704  1.1  christos 
    705  1.1  christos 	return lease;
    706  1.1  christos }
    707  1.1  christos 
    708  1.1  christos static isc_result_t
    709  1.1  christos dhc6_parse_ia_na(struct dhc6_ia **pia, struct packet *packet,
    710  1.1  christos 		 struct option_state *options, unsigned code)
    711  1.1  christos {
    712  1.1  christos 	struct data_string ds;
    713  1.1  christos 	struct dhc6_ia *ia;
    714  1.1  christos 	struct option_cache *oc;
    715  1.1  christos 	isc_result_t result;
    716  1.1  christos 	unsigned ia_code;
    717  1.1  christos 
    718  1.1  christos 	memset(&ds, 0, sizeof(ds));
    719  1.1  christos 
    720  1.1  christos 	oc = lookup_option(&dhcpv6_universe, options, D6O_IA_NA);
    721  1.1  christos 	for ( ; oc != NULL ; oc = oc->next) {
    722  1.1  christos 		ia = dmalloc(sizeof(*ia), MDL);
    723  1.1  christos 		if (ia == NULL) {
    724  1.1  christos 			log_error("Out of memory allocating IA_NA structure.");
    725  1.1  christos 			return ISC_R_NOMEMORY;
    726  1.1  christos 		} else if (evaluate_option_cache(&ds, packet, NULL, NULL,
    727  1.1  christos 						 options, NULL,
    728  1.1  christos 						 &global_scope, oc, MDL) &&
    729  1.1  christos 			   ds.len >= 12) {
    730  1.1  christos 			memcpy(ia->iaid, ds.data, 4);
    731  1.1  christos 			ia->ia_type = D6O_IA_NA;
    732  1.1  christos 			ia->starts = cur_time;
    733  1.1  christos 			ia->renew = getULong(ds.data + 4);
    734  1.1  christos 			ia->rebind = getULong(ds.data + 8);
    735  1.1  christos 
    736  1.1  christos 			log_debug("RCV:  X-- IA_NA %s",
    737  1.1  christos 				  print_hex_1(4, ia->iaid, 59));
    738  1.1  christos 			/* XXX: This should be the printed time I think. */
    739  1.1  christos 			log_debug("RCV:  | X-- starts %u",
    740  1.1  christos 				  (unsigned)ia->starts);
    741  1.1  christos 			log_debug("RCV:  | X-- t1 - renew  +%u", ia->renew);
    742  1.1  christos 			log_debug("RCV:  | X-- t2 - rebind +%u", ia->rebind);
    743  1.1  christos 
    744  1.1  christos 			/*
    745  1.1  christos 			 * RFC3315 section 22.4, discard IA_NA's that
    746  1.1  christos 			 * have t1 greater than t2, and both not zero.
    747  1.1  christos 			 * Since RFC3315 defines this behaviour, it is not
    748  1.1  christos 			 * an error - just normal operation.
    749  1.1  christos 			 *
    750  1.1  christos 			 * Note that RFC3315 says we MUST honor these values
    751  1.1  christos 			 * if they are not zero.  So insane values are
    752  1.1  christos 			 * totally OK.
    753  1.1  christos 			 */
    754  1.1  christos 			if ((ia->renew > 0) && (ia->rebind > 0) &&
    755  1.1  christos 			    (ia->renew > ia->rebind)) {
    756  1.1  christos 				log_debug("RCV:  | !-- INVALID renew/rebind "
    757  1.1  christos 					  "times, IA_NA discarded.");
    758  1.1  christos 				dfree(ia, MDL);
    759  1.1  christos 				data_string_forget(&ds, MDL);
    760  1.1  christos 				continue;
    761  1.1  christos 			}
    762  1.1  christos 
    763  1.1  christos 			if (ds.len > 12) {
    764  1.1  christos 				log_debug("RCV:  | X-- [Options]");
    765  1.1  christos 
    766  1.1  christos 				if (!option_state_allocate(&ia->options,
    767  1.1  christos 							   MDL)) {
    768  1.1  christos 					log_error("Out of memory allocating "
    769  1.1  christos 						  "IA_NA option state.");
    770  1.1  christos 					dfree(ia, MDL);
    771  1.1  christos 					data_string_forget(&ds, MDL);
    772  1.1  christos 					return ISC_R_NOMEMORY;
    773  1.1  christos 				}
    774  1.1  christos 
    775  1.1  christos 				if (!parse_option_buffer(ia->options,
    776  1.1  christos 							 ds.data + 12,
    777  1.1  christos 							 ds.len - 12,
    778  1.1  christos 							 &dhcpv6_universe)) {
    779  1.1  christos 					log_error("Corrupt IA_NA options.");
    780  1.1  christos 					option_state_dereference(&ia->options,
    781  1.1  christos 								 MDL);
    782  1.1  christos 					dfree(ia, MDL);
    783  1.1  christos 					data_string_forget(&ds, MDL);
    784  1.1  christos 					return DHCP_R_BADPARSE;
    785  1.1  christos 				}
    786  1.1  christos 			}
    787  1.1  christos 			data_string_forget(&ds, MDL);
    788  1.1  christos 
    789  1.1  christos 			if (ia->options != NULL) {
    790  1.1  christos 				result = dhc6_parse_addrs(&ia->addrs, packet,
    791  1.1  christos 							  ia->options);
    792  1.1  christos 				if (result != ISC_R_SUCCESS) {
    793  1.1  christos 					option_state_dereference(&ia->options,
    794  1.1  christos 								 MDL);
    795  1.1  christos 					dfree(ia, MDL);
    796  1.1  christos 					return result;
    797  1.1  christos 				}
    798  1.1  christos 			}
    799  1.1  christos 
    800  1.1  christos 			/* If we have no addresses or the top level status code
    801  1.1  christos 			 * or the status code in this IA indicate no addresses
    802  1.1  christos 			 * toss the IA.
    803  1.1  christos 			 */
    804  1.1  christos 			ia_code = STATUS_Success;
    805  1.1  christos 			if ((ia->addrs == NULL) ||
    806  1.1  christos 			    (code == STATUS_NoAddrsAvail) ||
    807  1.1  christos 			    ((ia->options != NULL) &&
    808  1.1  christos 			     (dhc6_get_status_code(ia->options, &ia_code, NULL)
    809  1.1  christos 			      == ISC_R_SUCCESS) &&
    810  1.1  christos 			     (ia_code == STATUS_NoAddrsAvail))) {
    811  1.1  christos 				log_debug("RCV:  | !-- Status code of "
    812  1.1  christos 					  "no addrs, IA_NA discarded.");
    813  1.1  christos 				dhc6_ia_destroy(&ia, MDL);
    814  1.1  christos 				continue;
    815  1.1  christos 			}
    816  1.1  christos 
    817  1.1  christos 			while (*pia != NULL)
    818  1.1  christos 				pia = &(*pia)->next;
    819  1.1  christos 			*pia = ia;
    820  1.1  christos 			pia = &ia->next;
    821  1.1  christos 		} else {
    822  1.1  christos 			log_error("Invalid IA_NA option cache.");
    823  1.1  christos 			dfree(ia, MDL);
    824  1.3  christos 			data_string_forget(&ds, MDL);
    825  1.1  christos 			return ISC_R_UNEXPECTED;
    826  1.1  christos 		}
    827  1.1  christos 	}
    828  1.1  christos 	delete_option(&dhcpv6_universe, options, D6O_IA_NA);
    829  1.1  christos 
    830  1.1  christos 	return ISC_R_SUCCESS;
    831  1.1  christos }
    832  1.1  christos 
    833  1.1  christos static isc_result_t
    834  1.1  christos dhc6_parse_ia_ta(struct dhc6_ia **pia, struct packet *packet,
    835  1.1  christos 		 struct option_state *options, unsigned code)
    836  1.1  christos {
    837  1.1  christos 	struct data_string ds;
    838  1.1  christos 	struct dhc6_ia *ia;
    839  1.1  christos 	struct option_cache *oc;
    840  1.1  christos 	isc_result_t result;
    841  1.1  christos 	unsigned ia_code;
    842  1.1  christos 
    843  1.1  christos 	memset(&ds, 0, sizeof(ds));
    844  1.1  christos 
    845  1.1  christos 	oc = lookup_option(&dhcpv6_universe, options, D6O_IA_TA);
    846  1.1  christos 	for ( ; oc != NULL ; oc = oc->next) {
    847  1.1  christos 		ia = dmalloc(sizeof(*ia), MDL);
    848  1.1  christos 		if (ia == NULL) {
    849  1.1  christos 			log_error("Out of memory allocating IA_TA structure.");
    850  1.1  christos 			return ISC_R_NOMEMORY;
    851  1.1  christos 		} else if (evaluate_option_cache(&ds, packet, NULL, NULL,
    852  1.1  christos 						 options, NULL,
    853  1.1  christos 						 &global_scope, oc, MDL) &&
    854  1.1  christos 			   ds.len >= 4) {
    855  1.1  christos 			memcpy(ia->iaid, ds.data, 4);
    856  1.1  christos 			ia->ia_type = D6O_IA_TA;
    857  1.1  christos 			ia->starts = cur_time;
    858  1.1  christos 
    859  1.1  christos 			log_debug("RCV:  X-- IA_TA %s",
    860  1.1  christos 				  print_hex_1(4, ia->iaid, 59));
    861  1.1  christos 			/* XXX: This should be the printed time I think. */
    862  1.1  christos 			log_debug("RCV:  | X-- starts %u",
    863  1.1  christos 				  (unsigned)ia->starts);
    864  1.1  christos 
    865  1.1  christos 			if (ds.len > 4) {
    866  1.1  christos 				log_debug("RCV:  | X-- [Options]");
    867  1.1  christos 
    868  1.1  christos 				if (!option_state_allocate(&ia->options,
    869  1.1  christos 							   MDL)) {
    870  1.1  christos 					log_error("Out of memory allocating "
    871  1.1  christos 						  "IA_TA option state.");
    872  1.1  christos 					dfree(ia, MDL);
    873  1.1  christos 					data_string_forget(&ds, MDL);
    874  1.1  christos 					return ISC_R_NOMEMORY;
    875  1.1  christos 				}
    876  1.1  christos 
    877  1.1  christos 				if (!parse_option_buffer(ia->options,
    878  1.1  christos 							 ds.data + 4,
    879  1.1  christos 							 ds.len - 4,
    880  1.1  christos 							 &dhcpv6_universe)) {
    881  1.1  christos 					log_error("Corrupt IA_TA options.");
    882  1.1  christos 					option_state_dereference(&ia->options,
    883  1.1  christos 								 MDL);
    884  1.1  christos 					dfree(ia, MDL);
    885  1.1  christos 					data_string_forget(&ds, MDL);
    886  1.1  christos 					return DHCP_R_BADPARSE;
    887  1.1  christos 				}
    888  1.1  christos 			}
    889  1.1  christos 			data_string_forget(&ds, MDL);
    890  1.1  christos 
    891  1.1  christos 			if (ia->options != NULL) {
    892  1.1  christos 				result = dhc6_parse_addrs(&ia->addrs, packet,
    893  1.1  christos 							  ia->options);
    894  1.1  christos 				if (result != ISC_R_SUCCESS) {
    895  1.1  christos 					option_state_dereference(&ia->options,
    896  1.1  christos 								 MDL);
    897  1.1  christos 					dfree(ia, MDL);
    898  1.1  christos 					return result;
    899  1.1  christos 				}
    900  1.1  christos 			}
    901  1.1  christos 
    902  1.1  christos 			/* If we have no addresses or the top level status code
    903  1.1  christos 			 * or the status code in this IA indicate no addresses
    904  1.1  christos 			 * toss the IA.
    905  1.1  christos 			 */
    906  1.1  christos 			ia_code = STATUS_Success;
    907  1.1  christos 			if ((ia->addrs == NULL) ||
    908  1.1  christos 			    (code == STATUS_NoAddrsAvail) ||
    909  1.1  christos 			    ((ia->options != NULL) &&
    910  1.1  christos 			     (dhc6_get_status_code(ia->options, &ia_code, NULL)
    911  1.1  christos 			      == ISC_R_SUCCESS) &&
    912  1.1  christos 			     (ia_code == STATUS_NoAddrsAvail))) {
    913  1.1  christos 				log_debug("RCV:  | !-- Status code of "
    914  1.1  christos 					  "no addrs, IA_TA discarded.");
    915  1.1  christos 				dhc6_ia_destroy(&ia, MDL);
    916  1.1  christos 				continue;
    917  1.1  christos 			}
    918  1.1  christos 
    919  1.1  christos 			while (*pia != NULL)
    920  1.1  christos 				pia = &(*pia)->next;
    921  1.1  christos 			*pia = ia;
    922  1.1  christos 			pia = &ia->next;
    923  1.1  christos 		} else {
    924  1.1  christos 			log_error("Invalid IA_TA option cache.");
    925  1.1  christos 			dfree(ia, MDL);
    926  1.3  christos 			data_string_forget(&ds, MDL);
    927  1.1  christos 			return ISC_R_UNEXPECTED;
    928  1.1  christos 		}
    929  1.1  christos 	}
    930  1.1  christos 	delete_option(&dhcpv6_universe, options, D6O_IA_TA);
    931  1.1  christos 
    932  1.1  christos 	return ISC_R_SUCCESS;
    933  1.1  christos }
    934  1.1  christos 
    935  1.1  christos static isc_result_t
    936  1.1  christos dhc6_parse_ia_pd(struct dhc6_ia **pia, struct packet *packet,
    937  1.1  christos 		 struct option_state *options, unsigned code)
    938  1.1  christos {
    939  1.1  christos 	struct data_string ds;
    940  1.1  christos 	struct dhc6_ia *ia;
    941  1.1  christos 	struct option_cache *oc;
    942  1.1  christos 	isc_result_t result;
    943  1.1  christos 	unsigned ia_code;
    944  1.1  christos 
    945  1.1  christos 	memset(&ds, 0, sizeof(ds));
    946  1.1  christos 
    947  1.1  christos 	oc = lookup_option(&dhcpv6_universe, options, D6O_IA_PD);
    948  1.1  christos 	for ( ; oc != NULL ; oc = oc->next) {
    949  1.1  christos 		ia = dmalloc(sizeof(*ia), MDL);
    950  1.1  christos 		if (ia == NULL) {
    951  1.1  christos 			log_error("Out of memory allocating IA_PD structure.");
    952  1.1  christos 			return ISC_R_NOMEMORY;
    953  1.1  christos 		} else if (evaluate_option_cache(&ds, packet, NULL, NULL,
    954  1.1  christos 						 options, NULL,
    955  1.1  christos 						 &global_scope, oc, MDL) &&
    956  1.1  christos 			   ds.len >= 12) {
    957  1.1  christos 			memcpy(ia->iaid, ds.data, 4);
    958  1.1  christos 			ia->ia_type = D6O_IA_PD;
    959  1.1  christos 			ia->starts = cur_time;
    960  1.1  christos 			ia->renew = getULong(ds.data + 4);
    961  1.1  christos 			ia->rebind = getULong(ds.data + 8);
    962  1.1  christos 
    963  1.1  christos 			log_debug("RCV:  X-- IA_PD %s",
    964  1.1  christos 				  print_hex_1(4, ia->iaid, 59));
    965  1.1  christos 			/* XXX: This should be the printed time I think. */
    966  1.1  christos 			log_debug("RCV:  | X-- starts %u",
    967  1.1  christos 				  (unsigned)ia->starts);
    968  1.1  christos 			log_debug("RCV:  | X-- t1 - renew  +%u", ia->renew);
    969  1.1  christos 			log_debug("RCV:  | X-- t2 - rebind +%u", ia->rebind);
    970  1.1  christos 
    971  1.1  christos 			/*
    972  1.1  christos 			 * RFC3633 section 9, discard IA_PD's that
    973  1.1  christos 			 * have t1 greater than t2, and both not zero.
    974  1.1  christos 			 * Since RFC3633 defines this behaviour, it is not
    975  1.1  christos 			 * an error - just normal operation.
    976  1.1  christos 			 */
    977  1.1  christos 			if ((ia->renew > 0) && (ia->rebind > 0) &&
    978  1.1  christos 			    (ia->renew > ia->rebind)) {
    979  1.1  christos 				log_debug("RCV:  | !-- INVALID renew/rebind "
    980  1.1  christos 					  "times, IA_PD discarded.");
    981  1.1  christos 				dfree(ia, MDL);
    982  1.1  christos 				data_string_forget(&ds, MDL);
    983  1.1  christos 				continue;
    984  1.1  christos 			}
    985  1.1  christos 
    986  1.1  christos 			if (ds.len > 12) {
    987  1.1  christos 				log_debug("RCV:  | X-- [Options]");
    988  1.1  christos 
    989  1.1  christos 				if (!option_state_allocate(&ia->options,
    990  1.1  christos 							   MDL)) {
    991  1.1  christos 					log_error("Out of memory allocating "
    992  1.1  christos 						  "IA_PD option state.");
    993  1.1  christos 					dfree(ia, MDL);
    994  1.1  christos 					data_string_forget(&ds, MDL);
    995  1.1  christos 					return ISC_R_NOMEMORY;
    996  1.1  christos 				}
    997  1.1  christos 
    998  1.1  christos 				if (!parse_option_buffer(ia->options,
    999  1.1  christos 							 ds.data + 12,
   1000  1.1  christos 							 ds.len - 12,
   1001  1.1  christos 							 &dhcpv6_universe)) {
   1002  1.1  christos 					log_error("Corrupt IA_PD options.");
   1003  1.1  christos 					option_state_dereference(&ia->options,
   1004  1.1  christos 								 MDL);
   1005  1.1  christos 					dfree(ia, MDL);
   1006  1.1  christos 					data_string_forget(&ds, MDL);
   1007  1.1  christos 					return DHCP_R_BADPARSE;
   1008  1.1  christos 				}
   1009  1.1  christos 			}
   1010  1.1  christos 			data_string_forget(&ds, MDL);
   1011  1.1  christos 
   1012  1.1  christos 			if (ia->options != NULL) {
   1013  1.1  christos 				result = dhc6_parse_prefixes(&ia->addrs,
   1014  1.1  christos 							     packet,
   1015  1.1  christos 							     ia->options);
   1016  1.1  christos 				if (result != ISC_R_SUCCESS) {
   1017  1.1  christos 					option_state_dereference(&ia->options,
   1018  1.1  christos 								 MDL);
   1019  1.1  christos 					dfree(ia, MDL);
   1020  1.1  christos 					return result;
   1021  1.1  christos 				}
   1022  1.1  christos 			}
   1023  1.1  christos 
   1024  1.1  christos 			/* If we have no prefixes or the top level status code
   1025  1.1  christos 			 * or the status code in this IA indicate no prefixes
   1026  1.1  christos 			 * toss the IA.
   1027  1.1  christos 			 */
   1028  1.1  christos 			ia_code = STATUS_Success;
   1029  1.1  christos 			if ((ia->addrs == NULL) ||
   1030  1.1  christos 			    (code == STATUS_NoPrefixAvail) ||
   1031  1.1  christos 			    ((ia->options != NULL) &&
   1032  1.1  christos 			     (dhc6_get_status_code(ia->options, &ia_code, NULL)
   1033  1.1  christos 			      == ISC_R_SUCCESS) &&
   1034  1.1  christos 			     (ia_code == STATUS_NoPrefixAvail))) {
   1035  1.1  christos 				log_debug("RCV:  | !-- Status code of "
   1036  1.1  christos 					  "no prefix, IA_PD discarded.");
   1037  1.1  christos 				dhc6_ia_destroy(&ia, MDL);
   1038  1.1  christos 				continue;
   1039  1.1  christos 			}
   1040  1.1  christos 
   1041  1.1  christos 			while (*pia != NULL)
   1042  1.1  christos 				pia = &(*pia)->next;
   1043  1.1  christos 			*pia = ia;
   1044  1.1  christos 			pia = &ia->next;
   1045  1.1  christos 		} else {
   1046  1.1  christos 			log_error("Invalid IA_PD option cache.");
   1047  1.1  christos 			dfree(ia, MDL);
   1048  1.3  christos 			data_string_forget(&ds, MDL);
   1049  1.1  christos 			return ISC_R_UNEXPECTED;
   1050  1.1  christos 		}
   1051  1.1  christos 	}
   1052  1.1  christos 	delete_option(&dhcpv6_universe, options, D6O_IA_PD);
   1053  1.1  christos 
   1054  1.1  christos 	return ISC_R_SUCCESS;
   1055  1.1  christos }
   1056  1.1  christos 
   1057  1.1  christos 
   1058  1.1  christos static isc_result_t
   1059  1.1  christos dhc6_parse_addrs(struct dhc6_addr **paddr, struct packet *packet,
   1060  1.1  christos 		 struct option_state *options)
   1061  1.1  christos {
   1062  1.1  christos 	struct data_string ds;
   1063  1.1  christos 	struct option_cache *oc;
   1064  1.1  christos 	struct dhc6_addr *addr;
   1065  1.1  christos 	isc_result_t rval = ISC_R_SUCCESS;
   1066  1.1  christos 	unsigned code;
   1067  1.1  christos 
   1068  1.1  christos 	memset(&ds, 0, sizeof(ds));
   1069  1.1  christos 
   1070  1.1  christos 	oc = lookup_option(&dhcpv6_universe, options, D6O_IAADDR);
   1071  1.1  christos 	for ( ; oc != NULL ; oc = oc->next) {
   1072  1.1  christos 		addr = dmalloc(sizeof(*addr), MDL);
   1073  1.1  christos 		if (addr == NULL) {
   1074  1.1  christos 			log_error("Out of memory allocating "
   1075  1.1  christos 				  "address structure.");
   1076  1.1  christos 			return ISC_R_NOMEMORY;
   1077  1.1  christos 		} else if (evaluate_option_cache(&ds, packet, NULL, NULL,
   1078  1.1  christos 						 options, NULL, &global_scope,
   1079  1.1  christos 						 oc, MDL) &&
   1080  1.1  christos 			   (ds.len >= 24)) {
   1081  1.1  christos 
   1082  1.1  christos 			addr->address.len = 16;
   1083  1.1  christos 			memcpy(addr->address.iabuf, ds.data, 16);
   1084  1.1  christos 			addr->starts = cur_time;
   1085  1.1  christos 			addr->preferred_life = getULong(ds.data + 16);
   1086  1.1  christos 			addr->max_life = getULong(ds.data + 20);
   1087  1.1  christos 
   1088  1.1  christos 			log_debug("RCV:  | | X-- IAADDR %s",
   1089  1.1  christos 				  piaddr(addr->address));
   1090  1.1  christos 			log_debug("RCV:  | | | X-- Preferred lifetime %u.",
   1091  1.1  christos 				  addr->preferred_life);
   1092  1.1  christos 			log_debug("RCV:  | | | X-- Max lifetime %u.",
   1093  1.1  christos 				  addr->max_life);
   1094  1.1  christos 
   1095  1.1  christos 			/*
   1096  1.1  christos 			 * RFC 3315 section 22.6 says we must discard
   1097  1.1  christos 			 * addresses whose pref is later than valid.
   1098  1.1  christos 			 */
   1099  1.1  christos 			if ((addr->preferred_life > addr->max_life)) {
   1100  1.1  christos 				log_debug("RCV:  | | | !-- INVALID lifetimes, "
   1101  1.1  christos 					  "IAADDR discarded.  Check your "
   1102  1.1  christos 					  "server configuration.");
   1103  1.1  christos 				dfree(addr, MDL);
   1104  1.1  christos 				data_string_forget(&ds, MDL);
   1105  1.1  christos 				continue;
   1106  1.1  christos 			}
   1107  1.1  christos 
   1108  1.1  christos 			/*
   1109  1.1  christos 			 * Fortunately this is the last recursion in the
   1110  1.1  christos 			 * protocol.
   1111  1.1  christos 			 */
   1112  1.1  christos 			if (ds.len > 24) {
   1113  1.1  christos 				if (!option_state_allocate(&addr->options,
   1114  1.1  christos 							   MDL)) {
   1115  1.1  christos 					log_error("Out of memory allocating "
   1116  1.1  christos 						  "IAADDR option state.");
   1117  1.1  christos 					dfree(addr, MDL);
   1118  1.1  christos 					data_string_forget(&ds, MDL);
   1119  1.1  christos 					return ISC_R_NOMEMORY;
   1120  1.1  christos 				}
   1121  1.1  christos 
   1122  1.1  christos 				if (!parse_option_buffer(addr->options,
   1123  1.1  christos 							 ds.data + 24,
   1124  1.1  christos 							 ds.len - 24,
   1125  1.1  christos 							 &dhcpv6_universe)) {
   1126  1.1  christos 					log_error("Corrupt IAADDR options.");
   1127  1.1  christos 					option_state_dereference(&addr->options,
   1128  1.1  christos 								 MDL);
   1129  1.1  christos 					dfree(addr, MDL);
   1130  1.1  christos 					data_string_forget(&ds, MDL);
   1131  1.1  christos 					return DHCP_R_BADPARSE;
   1132  1.1  christos 				}
   1133  1.1  christos 			}
   1134  1.1  christos 
   1135  1.1  christos 			data_string_forget(&ds, MDL);
   1136  1.1  christos 
   1137  1.1  christos 			if (addr->options != NULL) {
   1138  1.1  christos 				log_debug("RCV:  | | | X-- [Options]");
   1139  1.1  christos 
   1140  1.1  christos 				/* Get the status code if the return value
   1141  1.1  christos 				 * indicates an error or the status code
   1142  1.1  christos 				 * indicates no address toss the address
   1143  1.1  christos 				 */
   1144  1.1  christos 				code = STATUS_Success;
   1145  1.1  christos 				rval = dhc6_check_status(ISC_R_SUCCESS,
   1146  1.1  christos 							 addr->options,
   1147  1.1  christos 							 "IAADDR", &code);
   1148  1.1  christos 				if (rval != ISC_R_SUCCESS) {
   1149  1.1  christos 					log_debug("RCV:  | | | X-- Status code"
   1150  1.1  christos 						  " issue, IAADDR discarded.");
   1151  1.1  christos 					option_state_dereference(&addr->options,
   1152  1.1  christos 								 MDL);
   1153  1.1  christos 					dfree(addr, MDL);
   1154  1.1  christos 					continue;
   1155  1.1  christos 				}
   1156  1.1  christos 			}
   1157  1.1  christos 
   1158  1.1  christos 			*paddr = addr;
   1159  1.1  christos 			paddr = &addr->next;
   1160  1.1  christos 		} else {
   1161  1.1  christos 			log_error("Invalid IAADDR option cache.");
   1162  1.1  christos 			dfree(addr, MDL);
   1163  1.3  christos 			data_string_forget(&ds, MDL);
   1164  1.1  christos 			return ISC_R_UNEXPECTED;
   1165  1.1  christos 		}
   1166  1.1  christos 	}
   1167  1.1  christos 	delete_option(&dhcpv6_universe, options, D6O_IAADDR);
   1168  1.1  christos 
   1169  1.1  christos 	return ISC_R_SUCCESS;
   1170  1.1  christos }
   1171  1.1  christos 
   1172  1.1  christos static isc_result_t
   1173  1.1  christos dhc6_parse_prefixes(struct dhc6_addr **ppfx, struct packet *packet,
   1174  1.1  christos 		    struct option_state *options)
   1175  1.1  christos {
   1176  1.1  christos 	struct data_string ds;
   1177  1.1  christos 	struct option_cache *oc;
   1178  1.1  christos 	struct dhc6_addr *pfx;
   1179  1.1  christos 	isc_result_t rval = ISC_R_SUCCESS;
   1180  1.1  christos 	unsigned code;
   1181  1.1  christos 
   1182  1.1  christos 	memset(&ds, 0, sizeof(ds));
   1183  1.1  christos 
   1184  1.1  christos 	oc = lookup_option(&dhcpv6_universe, options, D6O_IAPREFIX);
   1185  1.1  christos 	for ( ; oc != NULL ; oc = oc->next) {
   1186  1.1  christos 		pfx = dmalloc(sizeof(*pfx), MDL);
   1187  1.1  christos 		if (pfx == NULL) {
   1188  1.1  christos 			log_error("Out of memory allocating "
   1189  1.1  christos 				  "prefix structure.");
   1190  1.1  christos 			return ISC_R_NOMEMORY;
   1191  1.1  christos 		} else if (evaluate_option_cache(&ds, packet, NULL, NULL,
   1192  1.1  christos 						 options, NULL, &global_scope,
   1193  1.1  christos 						 oc, MDL) &&
   1194  1.1  christos 			   (ds.len >= 25)) {
   1195  1.1  christos 
   1196  1.1  christos 			pfx->preferred_life = getULong(ds.data);
   1197  1.1  christos 			pfx->max_life = getULong(ds.data + 4);
   1198  1.1  christos 			pfx->plen = getUChar(ds.data + 8);
   1199  1.1  christos 			pfx->address.len = 16;
   1200  1.1  christos 			memcpy(pfx->address.iabuf, ds.data + 9, 16);
   1201  1.1  christos 			pfx->starts = cur_time;
   1202  1.1  christos 
   1203  1.1  christos 			log_debug("RCV:  | | X-- IAPREFIX %s/%d",
   1204  1.1  christos 				  piaddr(pfx->address), (int)pfx->plen);
   1205  1.1  christos 			log_debug("RCV:  | | | X-- Preferred lifetime %u.",
   1206  1.1  christos 				  pfx->preferred_life);
   1207  1.1  christos 			log_debug("RCV:  | | | X-- Max lifetime %u.",
   1208  1.1  christos 				  pfx->max_life);
   1209  1.1  christos 
   1210  1.1  christos 			/* Sanity check over the prefix length */
   1211  1.1  christos 			if ((pfx->plen < 4) || (pfx->plen > 128)) {
   1212  1.1  christos 				log_debug("RCV:  | | | !-- INVALID prefix "
   1213  1.1  christos 					  "length, IAPREFIX discarded.  "
   1214  1.1  christos 					  "Check your server configuration.");
   1215  1.1  christos 				dfree(pfx, MDL);
   1216  1.1  christos 				data_string_forget(&ds, MDL);
   1217  1.1  christos 				continue;
   1218  1.1  christos 			}
   1219  1.1  christos 			/*
   1220  1.1  christos 			 * RFC 3633 section 10 says we must discard
   1221  1.1  christos 			 * prefixes whose pref is later than valid.
   1222  1.1  christos 			 */
   1223  1.1  christos 			if ((pfx->preferred_life > pfx->max_life)) {
   1224  1.1  christos 				log_debug("RCV:  | | | !-- INVALID lifetimes, "
   1225  1.1  christos 					  "IAPREFIX discarded.  Check your "
   1226  1.1  christos 					  "server configuration.");
   1227  1.1  christos 				dfree(pfx, MDL);
   1228  1.1  christos 				data_string_forget(&ds, MDL);
   1229  1.1  christos 				continue;
   1230  1.1  christos 			}
   1231  1.1  christos 
   1232  1.1  christos 			/*
   1233  1.1  christos 			 * Fortunately this is the last recursion in the
   1234  1.1  christos 			 * protocol.
   1235  1.1  christos 			 */
   1236  1.1  christos 			if (ds.len > 25) {
   1237  1.1  christos 				if (!option_state_allocate(&pfx->options,
   1238  1.1  christos 							   MDL)) {
   1239  1.1  christos 					log_error("Out of memory allocating "
   1240  1.1  christos 						  "IAPREFIX option state.");
   1241  1.1  christos 					dfree(pfx, MDL);
   1242  1.1  christos 					data_string_forget(&ds, MDL);
   1243  1.1  christos 					return ISC_R_NOMEMORY;
   1244  1.1  christos 				}
   1245  1.1  christos 
   1246  1.1  christos 				if (!parse_option_buffer(pfx->options,
   1247  1.1  christos 							 ds.data + 25,
   1248  1.1  christos 							 ds.len - 25,
   1249  1.1  christos 							 &dhcpv6_universe)) {
   1250  1.1  christos 					log_error("Corrupt IAPREFIX options.");
   1251  1.1  christos 					option_state_dereference(&pfx->options,
   1252  1.1  christos 								 MDL);
   1253  1.1  christos 					dfree(pfx, MDL);
   1254  1.1  christos 					data_string_forget(&ds, MDL);
   1255  1.1  christos 					return DHCP_R_BADPARSE;
   1256  1.1  christos 				}
   1257  1.1  christos 			}
   1258  1.1  christos 
   1259  1.1  christos 			data_string_forget(&ds, MDL);
   1260  1.1  christos 
   1261  1.1  christos 			if (pfx->options != NULL) {
   1262  1.1  christos 				log_debug("RCV:  | | | X-- [Options]");
   1263  1.1  christos 
   1264  1.1  christos 				/* Get the status code if the return value
   1265  1.1  christos 				 * indicates an error or the status code
   1266  1.1  christos 				 * indicates no prefix toss the prefix
   1267  1.1  christos 				 */
   1268  1.1  christos 				code = STATUS_Success;
   1269  1.1  christos 				rval = dhc6_check_status(ISC_R_SUCCESS,
   1270  1.1  christos 							 pfx->options,
   1271  1.1  christos 							 "IAPREFIX", &code);
   1272  1.1  christos 				if (rval != ISC_R_SUCCESS) {
   1273  1.1  christos 					log_debug("RCV:  | | | X-- Status code"
   1274  1.1  christos 						  " issue IAPREFIX discarded.");
   1275  1.1  christos 					option_state_dereference(&pfx->options,
   1276  1.1  christos 								 MDL);
   1277  1.1  christos 					dfree(pfx, MDL);
   1278  1.1  christos 					continue;
   1279  1.1  christos 				}
   1280  1.1  christos 			}
   1281  1.1  christos 
   1282  1.1  christos 			*ppfx = pfx;
   1283  1.1  christos 			ppfx = &pfx->next;
   1284  1.1  christos 		} else {
   1285  1.1  christos 			log_error("Invalid IAPREFIX option cache.");
   1286  1.1  christos 			dfree(pfx, MDL);
   1287  1.3  christos 			data_string_forget(&ds, MDL);
   1288  1.1  christos 			return ISC_R_UNEXPECTED;
   1289  1.1  christos 		}
   1290  1.1  christos 	}
   1291  1.1  christos 	delete_option(&dhcpv6_universe, options, D6O_IAPREFIX);
   1292  1.1  christos 
   1293  1.1  christos 	return ISC_R_SUCCESS;
   1294  1.1  christos }
   1295  1.1  christos 
   1296  1.1  christos /* Clean up a lease object, deallocate all its parts, and set it to NULL. */
   1297  1.1  christos void
   1298  1.1  christos dhc6_lease_destroy(struct dhc6_lease **src, const char *file, int line)
   1299  1.1  christos {
   1300  1.1  christos 	struct dhc6_ia *ia, *nia;
   1301  1.1  christos 	struct dhc6_lease *lease;
   1302  1.1  christos 
   1303  1.1  christos 	if (src == NULL || *src == NULL) {
   1304  1.1  christos 		log_error("Attempt to destroy null lease.");
   1305  1.1  christos 		return;
   1306  1.1  christos 	}
   1307  1.1  christos 	lease = *src;
   1308  1.1  christos 
   1309  1.3  christos 	data_string_forget(&lease->server_id, file, line);
   1310  1.1  christos 	for (ia = lease->bindings ; ia != NULL ; ia = nia) {
   1311  1.1  christos 		nia = ia->next;
   1312  1.1  christos 
   1313  1.1  christos 		dhc6_ia_destroy(&ia, file, line);
   1314  1.1  christos 	}
   1315  1.1  christos 
   1316  1.1  christos 	if (lease->options != NULL)
   1317  1.1  christos 		option_state_dereference(&lease->options, file, line);
   1318  1.1  christos 
   1319  1.1  christos 	dfree(lease, file, line);
   1320  1.1  christos 	*src = NULL;
   1321  1.1  christos }
   1322  1.1  christos 
   1323  1.1  christos /*
   1324  1.1  christos  * Traverse the addresses list, and destroy their contents, and NULL the
   1325  1.1  christos  * list pointer.
   1326  1.1  christos  */
   1327  1.1  christos static void
   1328  1.1  christos dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line)
   1329  1.1  christos {
   1330  1.1  christos 	struct dhc6_addr *addr, *naddr;
   1331  1.1  christos 	struct dhc6_ia *ia;
   1332  1.1  christos 
   1333  1.1  christos 	if (src == NULL || *src == NULL) {
   1334  1.1  christos 		log_error("Attempt to destroy null IA.");
   1335  1.1  christos 		return;
   1336  1.1  christos 	}
   1337  1.1  christos 	ia = *src;
   1338  1.1  christos 
   1339  1.1  christos 	for (addr = ia->addrs ; addr != NULL ; addr = naddr) {
   1340  1.1  christos 		naddr = addr->next;
   1341  1.1  christos 
   1342  1.1  christos 		if (addr->options != NULL)
   1343  1.1  christos 			option_state_dereference(&addr->options, file, line);
   1344  1.1  christos 
   1345  1.1  christos 		dfree(addr, file, line);
   1346  1.1  christos 	}
   1347  1.1  christos 
   1348  1.1  christos 	if (ia->options != NULL)
   1349  1.1  christos 		option_state_dereference(&ia->options, file, line);
   1350  1.1  christos 
   1351  1.1  christos 	dfree(ia, file, line);
   1352  1.1  christos 	*src = NULL;
   1353  1.1  christos }
   1354  1.1  christos 
   1355  1.1  christos /*
   1356  1.1  christos  * For a given lease, insert it into the tail of the lease list.  Upon
   1357  1.1  christos  * finding a duplicate by server id, remove it and take over its position.
   1358  1.1  christos  */
   1359  1.1  christos static void
   1360  1.1  christos insert_lease(struct dhc6_lease **head, struct dhc6_lease *new)
   1361  1.1  christos {
   1362  1.1  christos 	while (*head != NULL) {
   1363  1.1  christos 		if ((*head)->server_id.len == new->server_id.len &&
   1364  1.1  christos 		    memcmp((*head)->server_id.data, new->server_id.data,
   1365  1.1  christos 			   new->server_id.len) == 0) {
   1366  1.1  christos 			new->next = (*head)->next;
   1367  1.1  christos 			dhc6_lease_destroy(head, MDL);
   1368  1.1  christos 			break;
   1369  1.1  christos 		}
   1370  1.1  christos 
   1371  1.1  christos 		head= &(*head)->next;
   1372  1.1  christos 	}
   1373  1.1  christos 
   1374  1.1  christos 	*head = new;
   1375  1.1  christos 	return;
   1376  1.1  christos }
   1377  1.1  christos 
   1378  1.1  christos /*!
   1379  1.1  christos  *
   1380  1.1  christos  * \brief Determine a score for a lease.  We use this to
   1381  1.1  christos  * compare and choose leases if we receive multiple candidates.
   1382  1.1  christos  *
   1383  1.1  christos  * We originally started with scores of 50 for a binding and 100 for
   1384  1.1  christos  * an address.  This would select multiple adresses over multiple
   1385  1.1  christos  * bindings.  As part of the 7550 work I've changed this to be
   1386  1.1  christos  * 10000 for a binding, 100 for an address and 1 for an option.
   1387  1.1  christos  * This will cause us to choose a lease with more bindings over
   1388  1.1  christos  * a lease with less bindings but more addresses which seems
   1389  1.1  christos  * to be the best selection criteria to me.
   1390  1.1  christos  * In theory we could end up with a lease with enough addresses
   1391  1.1  christos  * or options being better but at 100 to 1 I don't think it's likely.
   1392  1.1  christos  *
   1393  1.1  christos  * \param client = the state of the entire client
   1394  1.1  christos  * \param lease  = the lease to score.
   1395  1.1  christos  *
   1396  1.1  christos  * \retrun the score of the lease
   1397  1.1  christos  */
   1398  1.1  christos 
   1399  1.1  christos /* The scores for individual items. */
   1400  1.1  christos #ifdef USE_ORIGINAL_CLIENT_LEASE_WEIGHTS
   1401  1.1  christos #define SCORE_BINDING  50
   1402  1.1  christos #define SCORE_ADDRESS 100
   1403  1.1  christos #else
   1404  1.1  christos #define SCORE_BINDING 10000
   1405  1.1  christos #define SCORE_ADDRESS   100
   1406  1.1  christos #endif
   1407  1.1  christos 
   1408  1.1  christos #define SCORE_OPTION      1
   1409  1.1  christos /* We need a lease with at least 1 binding and 1 address */
   1410  1.1  christos #define SCORE_MIN (SCORE_BINDING + SCORE_ADDRESS)
   1411  1.1  christos 
   1412  1.1  christos static int
   1413  1.1  christos dhc6_score_lease(struct client_state *client, struct dhc6_lease *lease)
   1414  1.1  christos {
   1415  1.1  christos 	struct dhc6_ia *ia;
   1416  1.1  christos 	struct dhc6_addr *addr;
   1417  1.1  christos 	struct option **req;
   1418  1.1  christos 	int i;
   1419  1.1  christos 
   1420  1.1  christos 	if (lease->score)
   1421  1.1  christos 		return lease->score;
   1422  1.1  christos 
   1423  1.1  christos 	lease->score = SCORE_OPTION;
   1424  1.1  christos 
   1425  1.1  christos 	/* If this lease lacks a required option, dump it. */
   1426  1.1  christos 	/* XXX: we should be able to cache the failure... */
   1427  1.1  christos 	req = client->config->required_options;
   1428  1.1  christos 	if (req != NULL) {
   1429  1.1  christos 		for (i = 0 ; req[i] != NULL ; i++) {
   1430  1.1  christos 			if (lookup_option(&dhcpv6_universe, lease->options,
   1431  1.1  christos 					  req[i]->code) == NULL) {
   1432  1.1  christos 				lease->score = 0;
   1433  1.1  christos 				return lease->score;
   1434  1.1  christos 			}
   1435  1.1  christos 		}
   1436  1.1  christos 	}
   1437  1.1  christos 
   1438  1.1  christos 	/* If this lease contains a requested option, improve its score. */
   1439  1.1  christos 	req = client->config->requested_options;
   1440  1.1  christos 	if (req != NULL) {
   1441  1.1  christos 		for (i = 0 ; req[i] != NULL ; i++) {
   1442  1.1  christos 			if (lookup_option(&dhcpv6_universe, lease->options,
   1443  1.1  christos 					  req[i]->code) != NULL)
   1444  1.1  christos 				lease->score += SCORE_OPTION;
   1445  1.1  christos 		}
   1446  1.1  christos 	}
   1447  1.1  christos 
   1448  1.1  christos 	for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
   1449  1.1  christos 		lease->score += SCORE_BINDING;
   1450  1.1  christos 
   1451  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   1452  1.1  christos 			lease->score += SCORE_ADDRESS;
   1453  1.1  christos 		}
   1454  1.1  christos 	}
   1455  1.1  christos 
   1456  1.1  christos 	return lease->score;
   1457  1.1  christos }
   1458  1.1  christos 
   1459  1.1  christos /*
   1460  1.1  christos  * start_init6() kicks off the process, transmitting a packet and
   1461  1.1  christos  * scheduling a retransmission event.
   1462  1.1  christos  */
   1463  1.1  christos void
   1464  1.1  christos start_init6(struct client_state *client)
   1465  1.1  christos {
   1466  1.1  christos 	struct timeval tv;
   1467  1.1  christos 
   1468  1.1  christos 	log_debug("PRC: Soliciting for leases (INIT).");
   1469  1.1  christos 	client->state = S_INIT;
   1470  1.1  christos 
   1471  1.1  christos 	/* Initialize timers, RFC3315 section 17.1.2. */
   1472  1.1  christos 	client->IRT = SOL_TIMEOUT * 100;
   1473  1.1  christos 	client->MRT = SOL_MAX_RT * 100;
   1474  1.1  christos 	client->MRC = 0;
   1475  1.1  christos 	/* Default is 0 (no max) but -1 changes this. */
   1476  1.1  christos 	if (!onetry)
   1477  1.1  christos 		client->MRD = 0;
   1478  1.1  christos 	else
   1479  1.1  christos 		client->MRD = client->config->timeout;
   1480  1.1  christos 
   1481  1.1  christos 	dhc6_retrans_init(client);
   1482  1.1  christos 
   1483  1.1  christos 	/*
   1484  1.1  christos 	 * RFC3315 section 17.1.2 goes out of its way:
   1485  1.1  christos 	 * Also, the first RT MUST be selected to be strictly greater than IRT
   1486  1.1  christos 	 * by choosing RAND to be strictly greater than 0.
   1487  1.1  christos 	 */
   1488  1.1  christos 	/* if RAND < 0 then RAND = -RAND */
   1489  1.1  christos 	if (client->RT <= client->IRT)
   1490  1.1  christos 		client->RT = client->IRT + (client->IRT - client->RT);
   1491  1.1  christos 	/* if RAND == 0 then RAND = 1 */
   1492  1.1  christos 	if (client->RT <= client->IRT)
   1493  1.1  christos 		client->RT = client->IRT + 1;
   1494  1.1  christos 
   1495  1.1  christos 	client->v6_handler = init_handler;
   1496  1.1  christos 
   1497  1.1  christos 	/*
   1498  1.1  christos 	 * RFC3315 section 17.1.2 says we MUST start the first packet
   1499  1.1  christos 	 * between 0 and SOL_MAX_DELAY seconds.  The good news is
   1500  1.1  christos 	 * SOL_MAX_DELAY is 1.
   1501  1.1  christos 	 */
   1502  1.1  christos 	tv.tv_sec = cur_tv.tv_sec;
   1503  1.1  christos 	tv.tv_usec = cur_tv.tv_usec;
   1504  1.1  christos 	tv.tv_usec += (random() % (SOL_MAX_DELAY * 100)) * 10000;
   1505  1.1  christos 	if (tv.tv_usec >= 1000000) {
   1506  1.1  christos 		tv.tv_sec += 1;
   1507  1.1  christos 		tv.tv_usec -= 1000000;
   1508  1.1  christos 	}
   1509  1.1  christos 	add_timeout(&tv, do_init6, client, NULL, NULL);
   1510  1.1  christos 
   1511  1.1  christos 	if (nowait)
   1512  1.1  christos 		detach();
   1513  1.1  christos }
   1514  1.1  christos 
   1515  1.1  christos /*
   1516  1.1  christos  * start_info_request6() kicks off the process, transmitting an info
   1517  1.1  christos  * request packet and scheduling a retransmission event.
   1518  1.1  christos  */
   1519  1.1  christos void
   1520  1.1  christos start_info_request6(struct client_state *client)
   1521  1.1  christos {
   1522  1.1  christos 	struct timeval tv;
   1523  1.1  christos 
   1524  1.1  christos 	log_debug("PRC: Requesting information (INIT).");
   1525  1.1  christos 	client->state = S_INIT;
   1526  1.1  christos 
   1527  1.1  christos 	/* Initialize timers, RFC3315 section 18.1.5. */
   1528  1.1  christos 	client->IRT = INF_TIMEOUT * 100;
   1529  1.1  christos 	client->MRT = INF_MAX_RT * 100;
   1530  1.1  christos 	client->MRC = 0;
   1531  1.1  christos 	/* Default is 0 (no max) but -1 changes this. */
   1532  1.1  christos 	if (!onetry)
   1533  1.1  christos 		client->MRD = 0;
   1534  1.1  christos 	else
   1535  1.1  christos 		client->MRD = client->config->timeout;
   1536  1.1  christos 
   1537  1.1  christos 	dhc6_retrans_init(client);
   1538  1.1  christos 
   1539  1.1  christos 	client->v6_handler = info_request_handler;
   1540  1.1  christos 
   1541  1.1  christos 	/*
   1542  1.1  christos 	 * RFC3315 section 18.1.5 says we MUST start the first packet
   1543  1.1  christos 	 * between 0 and INF_MAX_DELAY seconds.  The good news is
   1544  1.1  christos 	 * INF_MAX_DELAY is 1.
   1545  1.1  christos 	 */
   1546  1.1  christos 	tv.tv_sec = cur_tv.tv_sec;
   1547  1.1  christos 	tv.tv_usec = cur_tv.tv_usec;
   1548  1.1  christos 	tv.tv_usec += (random() % (INF_MAX_DELAY * 100)) * 10000;
   1549  1.1  christos 	if (tv.tv_usec >= 1000000) {
   1550  1.1  christos 		tv.tv_sec += 1;
   1551  1.1  christos 		tv.tv_usec -= 1000000;
   1552  1.1  christos 	}
   1553  1.1  christos 	add_timeout(&tv, do_info_request6, client, NULL, NULL);
   1554  1.1  christos 
   1555  1.1  christos 	if (nowait)
   1556  1.1  christos 		detach();
   1557  1.1  christos }
   1558  1.1  christos 
   1559  1.1  christos /*
   1560  1.1  christos  * start_confirm6() kicks off an "init-reboot" version of the process, at
   1561  1.1  christos  * startup to find out if old bindings are 'fair' and at runtime whenever
   1562  1.1  christos  * a link cycles state we'll eventually want to do this.
   1563  1.1  christos  */
   1564  1.1  christos void
   1565  1.1  christos start_confirm6(struct client_state *client)
   1566  1.1  christos {
   1567  1.1  christos 	struct timeval tv;
   1568  1.1  christos 
   1569  1.1  christos 	/* If there is no active lease, there is nothing to check. */
   1570  1.1  christos 	if ((client->active_lease == NULL) ||
   1571  1.1  christos 	    !active_prefix(client) ||
   1572  1.1  christos 	    client->active_lease->released ||
   1573  1.1  christos 	    !unexpired_address_in_lease(client->active_lease)) {
   1574  1.1  christos 		dhc6_lease_destroy(&client->active_lease, MDL);
   1575  1.1  christos 		start_init6(client);
   1576  1.1  christos 		return;
   1577  1.1  christos 	}
   1578  1.1  christos 
   1579  1.1  christos 	log_debug("PRC: Confirming active lease (INIT-REBOOT).");
   1580  1.1  christos 	client->state = S_REBOOTING;
   1581  1.1  christos 
   1582  1.1  christos 	/* Initialize timers, RFC3315 section 17.1.3. */
   1583  1.1  christos 	client->IRT = CNF_TIMEOUT * 100;
   1584  1.1  christos 	client->MRT = CNF_MAX_RT * 100;
   1585  1.1  christos 	client->MRC = 0;
   1586  1.1  christos 	client->MRD = CNF_MAX_RD;
   1587  1.1  christos 
   1588  1.1  christos 	dhc6_retrans_init(client);
   1589  1.1  christos 
   1590  1.1  christos 	client->v6_handler = reply_handler;
   1591  1.1  christos 
   1592  1.1  christos 	/*
   1593  1.1  christos 	 * RFC3315 section 18.1.2 says we MUST start the first packet
   1594  1.1  christos 	 * between 0 and CNF_MAX_DELAY seconds.  The good news is
   1595  1.1  christos 	 * CNF_MAX_DELAY is 1.
   1596  1.1  christos 	 */
   1597  1.1  christos 	tv.tv_sec = cur_tv.tv_sec;
   1598  1.1  christos 	tv.tv_usec = cur_tv.tv_usec;
   1599  1.1  christos 	tv.tv_usec += (random() % (CNF_MAX_DELAY * 100)) * 10000;
   1600  1.1  christos 	if (tv.tv_usec >= 1000000) {
   1601  1.1  christos 		tv.tv_sec += 1;
   1602  1.1  christos 		tv.tv_usec -= 1000000;
   1603  1.1  christos 	}
   1604  1.1  christos 
   1605  1.1  christos 	/* We do a rebind instead of a confirm if the user
   1606  1.1  christos 	 * is requesting PDs or previously requesed PDs or
   1607  1.1  christos 	 * increased the number of NAs or TAs they want
   1608  1.1  christos 	 * Confirms don't tell us if PDs are still on-link and
   1609  1.1  christos 	 * we won't add new IAs on a confirm.
   1610  1.1  christos 	 */
   1611  1.1  christos 
   1612  1.1  christos 	if ((wanted_ia_pd != 0) ||
   1613  1.1  christos 	    (dhc6_count_ia(client->active_lease, D6O_IA_PD) != 0) ||
   1614  1.1  christos 	    (dhc6_count_ia(client->active_lease, D6O_IA_NA) < wanted_ia_na) ||
   1615  1.1  christos 	    (dhc6_count_ia(client->active_lease, D6O_IA_TA) < wanted_ia_ta)) {
   1616  1.1  christos 		client->state = S_REBINDING;
   1617  1.1  christos 		client->refresh_type = DHCPV6_REBIND;
   1618  1.1  christos 		add_timeout(&tv, do_refresh6, client, NULL, NULL);
   1619  1.1  christos 	} else
   1620  1.1  christos 		add_timeout(&tv, do_confirm6, client, NULL, NULL);
   1621  1.1  christos }
   1622  1.1  christos 
   1623  1.1  christos /*
   1624  1.1  christos  * check_timing6() check on the timing for sending a v6 message
   1625  1.1  christos  * and then do the basic initialization for a v6 message.
   1626  1.1  christos  */
   1627  1.1  christos #define CHK_TIM_SUCCESS		0
   1628  1.1  christos #define CHK_TIM_MRC_EXCEEDED	1
   1629  1.1  christos #define CHK_TIM_MRD_EXCEEDED	2
   1630  1.1  christos #define CHK_TIM_ALLOC_FAILURE	3
   1631  1.1  christos 
   1632  1.1  christos int
   1633  1.1  christos check_timing6 (struct client_state *client, u_int8_t msg_type,
   1634  1.1  christos 	       char *msg_str, struct dhc6_lease *lease,
   1635  1.1  christos 	       struct data_string *ds)
   1636  1.1  christos {
   1637  1.1  christos 	struct timeval elapsed;
   1638  1.1  christos 
   1639  1.1  christos 	/*
   1640  1.1  christos 	 * Start_time starts at the first transmission.
   1641  1.1  christos 	 */
   1642  1.1  christos 	if (client->txcount == 0) {
   1643  1.1  christos 		client->start_time.tv_sec = cur_tv.tv_sec;
   1644  1.1  christos 		client->start_time.tv_usec = cur_tv.tv_usec;
   1645  1.1  christos 	} else if ((client->MRC != 0) && (client->txcount > client->MRC)) {
   1646  1.1  christos 		log_info("Max retransmission count exceeded.");
   1647  1.1  christos 		return(CHK_TIM_MRC_EXCEEDED);
   1648  1.1  christos 	}
   1649  1.1  christos 
   1650  1.1  christos 	/* elapsed = cur - start */
   1651  1.1  christos 	elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
   1652  1.1  christos 	elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
   1653  1.1  christos 	if (elapsed.tv_usec < 0) {
   1654  1.1  christos 		elapsed.tv_sec -= 1;
   1655  1.1  christos 		elapsed.tv_usec += 1000000;
   1656  1.1  christos 	}
   1657  1.1  christos 
   1658  1.1  christos 	/* Check if finished (-1 argument). */
   1659  1.1  christos 	if ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD)) {
   1660  1.1  christos 		log_info("Max retransmission duration exceeded.");
   1661  1.1  christos 		return(CHK_TIM_MRD_EXCEEDED);
   1662  1.1  christos 	}
   1663  1.1  christos 
   1664  1.1  christos 	memset(ds, 0, sizeof(*ds));
   1665  1.1  christos 	if (!buffer_allocate(&(ds->buffer), 4, MDL)) {
   1666  1.1  christos 		log_error("Unable to allocate memory for %s.", msg_str);
   1667  1.1  christos 		return(CHK_TIM_ALLOC_FAILURE);
   1668  1.1  christos 	}
   1669  1.1  christos 	ds->data = ds->buffer->data;
   1670  1.1  christos 	ds->len = 4;
   1671  1.1  christos 
   1672  1.1  christos 	ds->buffer->data[0] = msg_type;
   1673  1.1  christos 	memcpy(ds->buffer->data + 1, client->dhcpv6_transaction_id, 3);
   1674  1.1  christos 
   1675  1.1  christos 	/* Form an elapsed option. */
   1676  1.1  christos 	/* Maximum value is 65535 1/100s coded as 0xffff. */
   1677  1.1  christos 	if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
   1678  1.1  christos 	    ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
   1679  1.1  christos 		client->elapsed = 0xffff;
   1680  1.1  christos 	} else {
   1681  1.1  christos 		client->elapsed = elapsed.tv_sec * 100;
   1682  1.1  christos 		client->elapsed += elapsed.tv_usec / 10000;
   1683  1.1  christos 	}
   1684  1.1  christos 
   1685  1.1  christos 	if (client->elapsed == 0)
   1686  1.1  christos 		log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str);
   1687  1.1  christos 	else
   1688  1.1  christos 		log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str,
   1689  1.1  christos 			  (unsigned)client->elapsed);
   1690  1.1  christos 
   1691  1.1  christos 	client->elapsed = htons(client->elapsed);
   1692  1.1  christos 
   1693  1.1  christos 	make_client6_options(client, &client->sent_options, lease, msg_type);
   1694  1.1  christos 
   1695  1.1  christos 	return(CHK_TIM_SUCCESS);
   1696  1.1  christos }
   1697  1.1  christos 
   1698  1.1  christos /*!
   1699  1.1  christos  *
   1700  1.1  christos  * \brief Create an iaid from information from the client.
   1701  1.1  christos  *
   1702  1.1  christos  * \param client = the state of the entire client
   1703  1.1  christos  * \param ia     = the ia to fill in
   1704  1.1  christos  * \param idx    = index of the ia in case we are doing multiples
   1705  1.1  christos  * \param len    = length of the base IA (4 for TA, 12 for NA & PD)
   1706  1.1  christos  *
   1707  1.1  christos  * \return ISC_R_SUCCESS - all is well continue, any other return indicates
   1708  1.1  christos  *                         an error and the packet should be tossed
   1709  1.1  christos  */
   1710  1.1  christos 
   1711  1.1  christos static isc_result_t
   1712  1.1  christos dhc6_create_iaid(struct client_state *client,
   1713  1.1  christos 		 struct data_string *ia,
   1714  1.1  christos 		 int idx,
   1715  1.1  christos 		 unsigned len)
   1716  1.1  christos {
   1717  1.1  christos 	int start_idx, copy_len;
   1718  1.1  christos 
   1719  1.1  christos 	memset(ia, 0, sizeof(*ia));
   1720  1.1  christos 	if (!buffer_allocate(&ia->buffer, len, MDL)) {
   1721  1.1  christos 		return (ISC_R_NOMEMORY);
   1722  1.1  christos 	}
   1723  1.1  christos 	ia->data = ia->buffer->data;
   1724  1.1  christos 	ia->len = len;
   1725  1.1  christos 
   1726  1.1  christos 	/*
   1727  1.1  christos 	 * A simple IAID is the last 4 bytes
   1728  1.1  christos 	 * of the hardware address.
   1729  1.1  christos 	 */
   1730  1.1  christos 	if (client->interface->hw_address.hlen > 4) {
   1731  1.1  christos 		start_idx = client->interface->hw_address.hlen - 4;
   1732  1.1  christos 		copy_len = 4;
   1733  1.1  christos 	} else {
   1734  1.1  christos 		start_idx = 0;
   1735  1.1  christos 		copy_len = client->interface->hw_address.hlen;
   1736  1.1  christos 	}
   1737  1.1  christos 	memcpy(ia->buffer->data,
   1738  1.1  christos 	       client->interface->hw_address.hbuf + start_idx,
   1739  1.1  christos 	       copy_len);
   1740  1.1  christos 	if (idx)
   1741  1.1  christos 		ia->buffer->data[3] += idx;
   1742  1.1  christos 
   1743  1.1  christos 	return (ISC_R_SUCCESS);
   1744  1.1  christos }
   1745  1.1  christos 
   1746  1.1  christos /*!
   1747  1.1  christos  *
   1748  1.1  christos  * \brief Add bare IA_NAs, IA_TAs or IA_PDs to the packet we are building.
   1749  1.1  christos  *
   1750  1.1  christos  * Attempt to add the number of bare IAs indicated by wanted to
   1751  1.1  christos  * the packet.  As we have already added a number of IAs based
   1752  1.1  christos  * on what is in the current lease after we create an IAID we check
   1753  1.1  christos  * it against the current lease and skip any that are already in use.
   1754  1.1  christos  *
   1755  1.1  christos  * \param client = the state of the entire client
   1756  1.1  christos  * \param packet = the packet we are building and where we
   1757  1.1  christos  *                 shall append the IA_NA, IA_TA  or IA_PDs we create
   1758  1.1  christos  * \param wanted = the number of IA_NA, IA_TA or IA_PDs we want to create
   1759  1.1  christos  * \param ia_type = the type of the IAs we want to create: NA, TA or PD.
   1760  1.1  christos  *
   1761  1.1  christos  * \return ISC_R_SUCCESS - all is well continue, any other return indicates
   1762  1.1  christos  *                         an error and the packet should be tossed
   1763  1.1  christos  */
   1764  1.1  christos static isc_result_t
   1765  1.1  christos dhc6_bare_ia_xx(struct client_state *client,
   1766  1.1  christos 		struct data_string *packet,
   1767  1.1  christos 		int wanted,
   1768  1.1  christos 		u_int16_t ia_type)
   1769  1.1  christos {
   1770  1.1  christos 	struct dhc6_ia *old_ia;
   1771  1.1  christos 	struct data_string ia;
   1772  1.1  christos 	u_int32_t t1, t2;
   1773  1.1  christos 	int i, len;
   1774  1.1  christos 	isc_result_t rval;
   1775  1.1  christos 	char *type_string;
   1776  1.1  christos 	struct option *type_option;
   1777  1.1  christos 
   1778  1.1  christos 	/* figure out what type of option we are working with */
   1779  1.1  christos 	switch (ia_type) {
   1780  1.1  christos 	      case D6O_IA_NA:
   1781  1.1  christos 		type_string = "IA_NA";
   1782  1.1  christos 		type_option = ia_na_option;
   1783  1.1  christos 		len = IA_NA_OFFSET;
   1784  1.1  christos 		break;
   1785  1.1  christos 	      case D6O_IA_TA:
   1786  1.1  christos 		type_string = "IA_TA";
   1787  1.1  christos 		type_option = ia_ta_option;
   1788  1.1  christos 		len = IA_TA_OFFSET;
   1789  1.1  christos 		break;
   1790  1.1  christos 	      case D6O_IA_PD:
   1791  1.1  christos 		type_string = "IA_PD";
   1792  1.1  christos 		type_option = ia_pd_option;
   1793  1.1  christos 		len = IA_PD_OFFSET;
   1794  1.1  christos 		if (prefix_len_hint > 0) {
   1795  1.1  christos 			len += IASUBOPT_PD_LEN;
   1796  1.1  christos 		}
   1797  1.1  christos 		break;
   1798  1.1  christos 
   1799  1.1  christos 	      default:
   1800  1.1  christos 		return (ISC_R_FAILURE);
   1801  1.1  christos 	}
   1802  1.1  christos 
   1803  1.1  christos 	for (i = 0; wanted != 0; i++) {
   1804  1.1  christos 		rval = dhc6_create_iaid(client, &ia, i, len);
   1805  1.1  christos 		if (rval != ISC_R_SUCCESS) {
   1806  1.1  christos 			log_error("Unable to allocate memory for %s.",
   1807  1.1  christos 				  type_string);
   1808  1.1  christos 			return (rval);
   1809  1.1  christos 		}
   1810  1.1  christos 
   1811  1.1  christos 		/* If we are already using this IAID, skip it and try again */
   1812  1.1  christos 		if ((client->active_lease != NULL) &&
   1813  1.1  christos 		    ((old_ia = find_ia(client->active_lease->bindings,
   1814  1.1  christos 				       ia_type,
   1815  1.1  christos 				       (char *)ia.buffer->data)) != NULL)) {
   1816  1.1  christos 			data_string_forget(&ia, MDL);
   1817  1.1  christos 			continue;
   1818  1.1  christos 		}
   1819  1.1  christos 
   1820  1.1  christos 		/* We have a good IAID, log it */
   1821  1.1  christos 		log_debug("XMT:  X-- %s %s",
   1822  1.1  christos 			  type_string, print_hex_1(4, ia.buffer->data, 55));
   1823  1.1  christos 
   1824  1.1  christos 		/* If we are requesting an NA or a PD we also want to add
   1825  1.1  christos 		 * the renew and rebind times we are requesting.
   1826  1.1  christos 		 */
   1827  1.1  christos 		if (ia_type != D6O_IA_TA) {
   1828  1.1  christos 			t1 = client->config->requested_lease / 2;
   1829  1.1  christos 			t2 = t1 + (t1 / 2);
   1830  1.1  christos 			putULong(ia.buffer->data + 4, t1);
   1831  1.1  christos 			putULong(ia.buffer->data + 8, t2);
   1832  1.1  christos 
   1833  1.1  christos 			log_debug("XMT:  | X-- Request renew in  +%u",
   1834  1.1  christos 				  (unsigned)t1);
   1835  1.1  christos 			log_debug("XMT:  | X-- Request rebind in +%u",
   1836  1.1  christos 				  (unsigned)t2);
   1837  1.1  christos 		}
   1838  1.1  christos 
   1839  1.1  christos 		if (ia_type == D6O_IA_PD && prefix_len_hint > 0) {
   1840  1.1  christos 			unsigned char *ptr = ia.buffer->data + IA_NA_OFFSET;
   1841  1.1  christos 			putUShort(ptr, D6O_IAPREFIX);
   1842  1.1  christos 			ptr += 2;
   1843  1.1  christos 			putUShort(ptr, IASUBOPT_PD_LEN);
   1844  1.1  christos 			ptr += 2;
   1845  1.1  christos 			putUChar(ptr + IASUBOPT_PD_PREFLEN_OFFSET,
   1846  1.1  christos 				 prefix_len_hint);
   1847  1.1  christos 			log_debug("XMT:  | | X-- Request prefix ::/%u.",
   1848  1.1  christos 				  prefix_len_hint);
   1849  1.1  christos 		}
   1850  1.1  christos 
   1851  1.1  christos 		/* and append it to the packet */
   1852  1.1  christos 		append_option(packet, &dhcpv6_universe, type_option, &ia);
   1853  1.1  christos 		data_string_forget(&ia, MDL);
   1854  1.1  christos 
   1855  1.1  christos 		/* decrement the number of IAs we want */
   1856  1.1  christos 		wanted--;
   1857  1.1  christos 	}
   1858  1.1  christos 
   1859  1.1  christos 	return (ISC_R_SUCCESS);
   1860  1.1  christos }
   1861  1.1  christos 
   1862  1.1  christos /*
   1863  1.1  christos  * do_init6() marshals and transmits a solicit.
   1864  1.1  christos  */
   1865  1.1  christos void
   1866  1.1  christos do_init6(void *input)
   1867  1.1  christos {
   1868  1.1  christos 	struct client_state *client;
   1869  1.1  christos 	struct dhc6_ia *old_ia;
   1870  1.1  christos 	struct dhc6_addr *old_addr;
   1871  1.1  christos 	struct data_string ds;
   1872  1.1  christos 	struct data_string ia;
   1873  1.1  christos 	struct data_string addr;
   1874  1.1  christos 	struct timeval tv;
   1875  1.1  christos 	u_int32_t t1, t2;
   1876  1.1  christos 	int i, send_ret;
   1877  1.1  christos 
   1878  1.1  christos 	client = input;
   1879  1.1  christos 
   1880  1.1  christos 	/*
   1881  1.1  christos 	 * In RFC3315 section 17.1.2, the retransmission timer is
   1882  1.1  christos 	 * used as the selecting timer.
   1883  1.1  christos 	 */
   1884  1.1  christos 	if (client->advertised_leases != NULL) {
   1885  1.1  christos 		start_selecting6(client);
   1886  1.1  christos 		return;
   1887  1.1  christos 	}
   1888  1.1  christos 
   1889  1.1  christos 	switch(check_timing6(client, DHCPV6_SOLICIT, "Solicit", NULL, &ds)) {
   1890  1.1  christos 	      case CHK_TIM_MRC_EXCEEDED:
   1891  1.1  christos 	      case CHK_TIM_ALLOC_FAILURE:
   1892  1.1  christos 		return;
   1893  1.1  christos 	      case CHK_TIM_MRD_EXCEEDED:
   1894  1.1  christos 		client->state = S_STOPPED;
   1895  1.1  christos 		if (client->active_lease != NULL) {
   1896  1.1  christos 			dhc6_lease_destroy(&client->active_lease, MDL);
   1897  1.1  christos 			client->active_lease = NULL;
   1898  1.1  christos 		}
   1899  1.1  christos 		/* Stop if and only if this is the last client. */
   1900  1.1  christos 		if (stopping_finished())
   1901  1.1  christos 			finish(2);
   1902  1.1  christos 		return;
   1903  1.1  christos 	}
   1904  1.1  christos 
   1905  1.1  christos 	/*
   1906  1.1  christos 	 * Fetch any configured 'sent' options (includes DUID) in wire format.
   1907  1.1  christos 	 */
   1908  1.1  christos 	dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
   1909  1.1  christos 				    NULL, client->sent_options, &global_scope,
   1910  1.1  christos 				    &dhcpv6_universe);
   1911  1.1  christos 
   1912  1.1  christos 	/* Use a specific handler with rapid-commit. */
   1913  1.1  christos 	if (lookup_option(&dhcpv6_universe, client->sent_options,
   1914  1.1  christos 			  D6O_RAPID_COMMIT) != NULL) {
   1915  1.1  christos 		client->v6_handler = rapid_commit_handler;
   1916  1.1  christos 	}
   1917  1.1  christos 
   1918  1.1  christos 	/* Append IA_NA. */
   1919  1.1  christos 	for (i = 0; i < wanted_ia_na; i++) {
   1920  1.1  christos 		/*
   1921  1.1  christos 		 * XXX: maybe the IA_NA('s) should be put into the sent_options
   1922  1.1  christos 		 * cache.  They'd have to be pulled down as they also contain
   1923  1.1  christos 		 * different option caches in the same universe...
   1924  1.1  christos 		 */
   1925  1.1  christos 		if (dhc6_create_iaid(client, &ia, i, 12) != ISC_R_SUCCESS) {
   1926  1.1  christos 			log_error("Unable to allocate memory for IA_NA.");
   1927  1.1  christos 			data_string_forget(&ds, MDL);
   1928  1.1  christos 			return;
   1929  1.1  christos 		}
   1930  1.1  christos 
   1931  1.1  christos 		t1 = client->config->requested_lease / 2;
   1932  1.1  christos 		t2 = t1 + (t1 / 2);
   1933  1.1  christos 		putULong(ia.buffer->data + 4, t1);
   1934  1.1  christos 		putULong(ia.buffer->data + 8, t2);
   1935  1.1  christos 
   1936  1.1  christos 		log_debug("XMT:  X-- IA_NA %s",
   1937  1.1  christos 			  print_hex_1(4, ia.buffer->data, 55));
   1938  1.1  christos 		log_debug("XMT:  | X-- Request renew in  +%u", (unsigned)t1);
   1939  1.1  christos 		log_debug("XMT:  | X-- Request rebind in +%u", (unsigned)t2);
   1940  1.1  christos 
   1941  1.1  christos 		if ((client->active_lease != NULL) &&
   1942  1.1  christos 		    ((old_ia = find_ia(client->active_lease->bindings,
   1943  1.1  christos 				       D6O_IA_NA,
   1944  1.1  christos 				       (char *)ia.buffer->data)) != NULL)) {
   1945  1.1  christos 			/*
   1946  1.1  christos 			 * For each address in the old IA_NA,
   1947  1.1  christos 			 * request a binding.
   1948  1.1  christos 			 */
   1949  1.1  christos 			memset(&addr, 0, sizeof(addr));
   1950  1.1  christos 			for (old_addr = old_ia->addrs ; old_addr != NULL ;
   1951  1.1  christos 			     old_addr = old_addr->next) {
   1952  1.1  christos 				if (old_addr->address.len != 16) {
   1953  1.1  christos 					log_error("Invalid IPv6 address "
   1954  1.1  christos 						  "length %d.  "
   1955  1.1  christos 						  "Ignoring.  (%s:%d)",
   1956  1.1  christos 						  old_addr->address.len,
   1957  1.1  christos 						  MDL);
   1958  1.1  christos 					continue;
   1959  1.1  christos 				}
   1960  1.1  christos 
   1961  1.1  christos 				if (!buffer_allocate(&addr.buffer, 24, MDL)) {
   1962  1.1  christos 					log_error("Unable to allocate memory "
   1963  1.1  christos 						  "for IAADDR.");
   1964  1.1  christos 					data_string_forget(&ia, MDL);
   1965  1.1  christos 					data_string_forget(&ds, MDL);
   1966  1.1  christos 					return;
   1967  1.1  christos 				}
   1968  1.1  christos 				addr.data = addr.buffer->data;
   1969  1.1  christos 				addr.len = 24;
   1970  1.1  christos 
   1971  1.1  christos 				memcpy(addr.buffer->data,
   1972  1.1  christos 				       old_addr->address.iabuf,
   1973  1.1  christos 				       16);
   1974  1.1  christos 
   1975  1.1  christos 				t1 = client->config->requested_lease;
   1976  1.1  christos 				t2 = t1 + (t1 / 2);
   1977  1.1  christos 				putULong(addr.buffer->data + 16, t1);
   1978  1.1  christos 				putULong(addr.buffer->data + 20, t2);
   1979  1.1  christos 
   1980  1.1  christos 				log_debug("XMT:  | X-- Request address %s.",
   1981  1.1  christos 					  piaddr(old_addr->address));
   1982  1.1  christos 				log_debug("XMT:  | | X-- Request "
   1983  1.1  christos 					  "preferred in +%u",
   1984  1.1  christos 					  (unsigned)t1);
   1985  1.1  christos 				log_debug("XMT:  | | X-- Request valid "
   1986  1.1  christos 					  "in     +%u",
   1987  1.1  christos 					  (unsigned)t2);
   1988  1.1  christos 
   1989  1.1  christos 				append_option(&ia, &dhcpv6_universe,
   1990  1.1  christos 					      iaaddr_option,
   1991  1.1  christos 					      &addr);
   1992  1.1  christos 
   1993  1.1  christos 				data_string_forget(&addr, MDL);
   1994  1.1  christos 			}
   1995  1.1  christos 		}
   1996  1.1  christos 
   1997  1.1  christos 		append_option(&ds, &dhcpv6_universe, ia_na_option, &ia);
   1998  1.1  christos 		data_string_forget(&ia, MDL);
   1999  1.1  christos 	}
   2000  1.1  christos 
   2001  1.1  christos 	/* Append IA_TA. */
   2002  1.1  christos 	for (i = 0; i < wanted_ia_ta; i++) {
   2003  1.1  christos 		/*
   2004  1.1  christos 		 * XXX: maybe the IA_TA('s) should be put into the sent_options
   2005  1.1  christos 		 * cache.  They'd have to be pulled down as they also contain
   2006  1.1  christos 		 * different option caches in the same universe...
   2007  1.1  christos 		 */
   2008  1.1  christos 		if (dhc6_create_iaid(client, &ia, i, 4) != ISC_R_SUCCESS) {
   2009  1.1  christos 			log_error("Unable to allocate memory for IA_TA.");
   2010  1.1  christos 			data_string_forget(&ds, MDL);
   2011  1.1  christos 			return;
   2012  1.1  christos 		}
   2013  1.1  christos 
   2014  1.1  christos 		log_debug("XMT:  X-- IA_TA %s",
   2015  1.1  christos 			  print_hex_1(4, ia.buffer->data, 55));
   2016  1.1  christos 
   2017  1.1  christos 		if ((client->active_lease != NULL) &&
   2018  1.1  christos 		    ((old_ia = find_ia(client->active_lease->bindings,
   2019  1.1  christos 				       D6O_IA_TA,
   2020  1.1  christos 				       (char *)ia.buffer->data)) != NULL)) {
   2021  1.1  christos 			/*
   2022  1.1  christos 			 * For each address in the old IA_TA,
   2023  1.1  christos 			 * request a binding.
   2024  1.1  christos 			 */
   2025  1.1  christos 			memset(&addr, 0, sizeof(addr));
   2026  1.1  christos 			for (old_addr = old_ia->addrs ; old_addr != NULL ;
   2027  1.1  christos 			     old_addr = old_addr->next) {
   2028  1.1  christos 				if (old_addr->address.len != 16) {
   2029  1.1  christos 					log_error("Invalid IPv6 address "
   2030  1.1  christos 						  "length %d.  "
   2031  1.1  christos 						  "Ignoring.  (%s:%d)",
   2032  1.1  christos 						  old_addr->address.len,
   2033  1.1  christos 						  MDL);
   2034  1.1  christos 					continue;
   2035  1.1  christos 				}
   2036  1.1  christos 
   2037  1.1  christos 				if (!buffer_allocate(&addr.buffer, 24, MDL)) {
   2038  1.1  christos 					log_error("Unable to allocate memory "
   2039  1.1  christos 						  "for IAADDR.");
   2040  1.1  christos 					data_string_forget(&ia, MDL);
   2041  1.1  christos 					data_string_forget(&ds, MDL);
   2042  1.1  christos 					return;
   2043  1.1  christos 				}
   2044  1.1  christos 				addr.data = addr.buffer->data;
   2045  1.1  christos 				addr.len = 24;
   2046  1.1  christos 
   2047  1.1  christos 				memcpy(addr.buffer->data,
   2048  1.1  christos 				       old_addr->address.iabuf,
   2049  1.1  christos 				       16);
   2050  1.1  christos 
   2051  1.1  christos 				t1 = client->config->requested_lease;
   2052  1.1  christos 				t2 = t1 + (t1 / 2);
   2053  1.1  christos 				putULong(addr.buffer->data + 16, t1);
   2054  1.1  christos 				putULong(addr.buffer->data + 20, t2);
   2055  1.1  christos 
   2056  1.1  christos 				log_debug("XMT:  | X-- Request address %s.",
   2057  1.1  christos 					  piaddr(old_addr->address));
   2058  1.1  christos 				log_debug("XMT:  | | X-- Request "
   2059  1.1  christos 					  "preferred in +%u",
   2060  1.1  christos 					  (unsigned)t1);
   2061  1.1  christos 				log_debug("XMT:  | | X-- Request valid "
   2062  1.1  christos 					  "in     +%u",
   2063  1.1  christos 					  (unsigned)t2);
   2064  1.1  christos 
   2065  1.1  christos 				append_option(&ia, &dhcpv6_universe,
   2066  1.1  christos 					      iaaddr_option,
   2067  1.1  christos 					      &addr);
   2068  1.1  christos 
   2069  1.1  christos 				data_string_forget(&addr, MDL);
   2070  1.1  christos 			}
   2071  1.1  christos 		}
   2072  1.1  christos 
   2073  1.1  christos 		append_option(&ds, &dhcpv6_universe, ia_ta_option, &ia);
   2074  1.1  christos 		data_string_forget(&ia, MDL);
   2075  1.1  christos 	}
   2076  1.1  christos 
   2077  1.1  christos 	/* Append IA_PD. */
   2078  1.1  christos 	for (i = 0; i < wanted_ia_pd; i++) {
   2079  1.1  christos 		/*
   2080  1.1  christos 		 * XXX: maybe the IA_PD('s) should be put into the sent_options
   2081  1.1  christos 		 * cache.  They'd have to be pulled down as they also contain
   2082  1.1  christos 		 * different option caches in the same universe...
   2083  1.1  christos 		 */
   2084  1.1  christos 		memset(&ia, 0, sizeof(ia));
   2085  1.1  christos 		if (dhc6_create_iaid(client, &ia, i, 12) != ISC_R_SUCCESS) {
   2086  1.1  christos 			log_error("Unable to allocate memory for IA_PD.");
   2087  1.1  christos 			data_string_forget(&ds, MDL);
   2088  1.1  christos 			return;
   2089  1.1  christos 		}
   2090  1.1  christos 
   2091  1.1  christos 		t1 = client->config->requested_lease / 2;
   2092  1.1  christos 		t2 = t1 + (t1 / 2);
   2093  1.1  christos 		putULong(ia.buffer->data + 4, t1);
   2094  1.1  christos 		putULong(ia.buffer->data + 8, t2);
   2095  1.1  christos 
   2096  1.1  christos 		log_debug("XMT:  X-- IA_PD %s",
   2097  1.1  christos 			  print_hex_1(4, ia.buffer->data, 55));
   2098  1.1  christos 		log_debug("XMT:  | X-- Request renew in  +%u", (unsigned)t1);
   2099  1.1  christos 		log_debug("XMT:  | X-- Request rebind in +%u", (unsigned)t2);
   2100  1.1  christos 
   2101  1.1  christos 		if ((client->active_lease != NULL) &&
   2102  1.1  christos 		    ((old_ia = find_ia(client->active_lease->bindings,
   2103  1.1  christos 				       D6O_IA_PD,
   2104  1.1  christos 				       (char *)ia.buffer->data)) != NULL)) {
   2105  1.1  christos 			/*
   2106  1.1  christos 			 * For each prefix in the old IA_PD,
   2107  1.1  christos 			 * request a binding.
   2108  1.1  christos 			 */
   2109  1.1  christos 			memset(&addr, 0, sizeof(addr));
   2110  1.1  christos 			for (old_addr = old_ia->addrs ; old_addr != NULL ;
   2111  1.1  christos 			     old_addr = old_addr->next) {
   2112  1.1  christos 				if (old_addr->address.len != 16) {
   2113  1.1  christos 					log_error("Invalid IPv6 prefix, "
   2114  1.1  christos 						  "Ignoring.  (%s:%d)",
   2115  1.1  christos 						  MDL);
   2116  1.1  christos 					continue;
   2117  1.1  christos 				}
   2118  1.1  christos 
   2119  1.1  christos 				if (!buffer_allocate(&addr.buffer, 25, MDL)) {
   2120  1.1  christos 					log_error("Unable to allocate memory "
   2121  1.1  christos 						  "for IAPREFIX.");
   2122  1.1  christos 					data_string_forget(&ia, MDL);
   2123  1.1  christos 					data_string_forget(&ds, MDL);
   2124  1.1  christos 					return;
   2125  1.1  christos 				}
   2126  1.1  christos 				addr.data = addr.buffer->data;
   2127  1.1  christos 				addr.len = 25;
   2128  1.1  christos 
   2129  1.1  christos 				t1 = client->config->requested_lease;
   2130  1.1  christos 				t2 = t1 + (t1 / 2);
   2131  1.1  christos 				putULong(addr.buffer->data, t1);
   2132  1.1  christos 				putULong(addr.buffer->data + 4, t2);
   2133  1.1  christos 
   2134  1.1  christos 				putUChar(addr.buffer->data + 8,
   2135  1.1  christos 					 old_addr->plen);
   2136  1.1  christos 				memcpy(addr.buffer->data + 9,
   2137  1.1  christos 				       old_addr->address.iabuf,
   2138  1.1  christos 				       16);
   2139  1.1  christos 
   2140  1.1  christos 				log_debug("XMT:  | X-- Request prefix %s/%u.",
   2141  1.1  christos 					  piaddr(old_addr->address),
   2142  1.1  christos 					  (unsigned) old_addr->plen);
   2143  1.1  christos 				log_debug("XMT:  | | X-- Request "
   2144  1.1  christos 					  "preferred in +%u",
   2145  1.1  christos 					  (unsigned)t1);
   2146  1.1  christos 				log_debug("XMT:  | | X-- Request valid "
   2147  1.1  christos 					  "in     +%u",
   2148  1.1  christos 					  (unsigned)t2);
   2149  1.1  christos 
   2150  1.1  christos 				append_option(&ia, &dhcpv6_universe,
   2151  1.1  christos 					      iaprefix_option,
   2152  1.1  christos 					      &addr);
   2153  1.1  christos 
   2154  1.1  christos 				data_string_forget(&addr, MDL);
   2155  1.1  christos 			}
   2156  1.1  christos 		} else if (prefix_len_hint > 0) {
   2157  1.1  christos 			memset(&addr, 0, sizeof(addr));
   2158  1.1  christos 			if (!buffer_allocate(&addr.buffer, 25, MDL)) {
   2159  1.1  christos 				log_error("Unable to allocate memory "
   2160  1.1  christos 					  "for IAPREFIX.");
   2161  1.1  christos 				data_string_forget(&ia, MDL);
   2162  1.1  christos 				data_string_forget(&ds, MDL);
   2163  1.1  christos 				return;
   2164  1.1  christos 			}
   2165  1.1  christos 
   2166  1.1  christos 			addr.data = addr.buffer->data;
   2167  1.1  christos 			addr.len = 25;
   2168  1.1  christos 
   2169  1.1  christos 			putUChar(addr.buffer->data + 8, prefix_len_hint);
   2170  1.1  christos 			log_debug("XMT:  | | X-- Request prefix ::/%u.",
   2171  1.1  christos 				  prefix_len_hint);
   2172  1.1  christos 			append_option(&ia, &dhcpv6_universe, iaprefix_option,
   2173  1.1  christos 				      &addr);
   2174  1.1  christos 			data_string_forget(&addr, MDL);
   2175  1.1  christos 		}
   2176  1.1  christos 
   2177  1.1  christos 		append_option(&ds, &dhcpv6_universe, ia_pd_option, &ia);
   2178  1.1  christos 		data_string_forget(&ia, MDL);
   2179  1.1  christos 	}
   2180  1.1  christos 
   2181  1.1  christos 	/* Transmit and wait. */
   2182  1.1  christos 
   2183  1.1  christos 	log_info("XMT: Solicit on %s, interval %ld0ms.",
   2184  1.1  christos 		 client->name ? client->name : client->interface->name,
   2185  1.1  christos 		 (long int)client->RT);
   2186  1.1  christos 
   2187  1.1  christos 	send_ret = send_packet6(client->interface,
   2188  1.1  christos 				ds.data, ds.len, &DHCPv6DestAddr);
   2189  1.1  christos 	if (send_ret != ds.len) {
   2190  1.1  christos 		log_error("dhc6: send_packet6() sent %d of %d bytes",
   2191  1.1  christos 			  send_ret, ds.len);
   2192  1.1  christos 	}
   2193  1.1  christos 
   2194  1.1  christos 	data_string_forget(&ds, MDL);
   2195  1.1  christos 
   2196  1.1  christos 	/* Wait RT */
   2197  1.1  christos 	tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
   2198  1.1  christos 	tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
   2199  1.1  christos 	if (tv.tv_usec >= 1000000) {
   2200  1.1  christos 		tv.tv_sec += 1;
   2201  1.1  christos 		tv.tv_usec -= 1000000;
   2202  1.1  christos 	}
   2203  1.1  christos 	add_timeout(&tv, do_init6, client, NULL, NULL);
   2204  1.1  christos 
   2205  1.1  christos 	dhc6_retrans_advance(client);
   2206  1.1  christos }
   2207  1.1  christos 
   2208  1.1  christos /* do_info_request6() marshals and transmits an information-request. */
   2209  1.1  christos void
   2210  1.1  christos do_info_request6(void *input)
   2211  1.1  christos {
   2212  1.1  christos 	struct client_state *client;
   2213  1.1  christos 	struct data_string ds;
   2214  1.1  christos 	struct timeval tv;
   2215  1.1  christos 	int send_ret;
   2216  1.1  christos 
   2217  1.1  christos 	client = input;
   2218  1.1  christos 
   2219  1.1  christos 	switch(check_timing6(client, DHCPV6_INFORMATION_REQUEST,
   2220  1.1  christos 			     "Info-Request", NULL, &ds)) {
   2221  1.1  christos 	      case CHK_TIM_MRC_EXCEEDED:
   2222  1.1  christos 	      case CHK_TIM_ALLOC_FAILURE:
   2223  1.1  christos 		return;
   2224  1.1  christos 	      case CHK_TIM_MRD_EXCEEDED:
   2225  1.1  christos 		finish(2);
   2226  1.1  christos 	      case CHK_TIM_SUCCESS:
   2227  1.1  christos 		break;
   2228  1.1  christos 	}
   2229  1.1  christos 
   2230  1.1  christos 	/* Fetch any configured 'sent' options (includes DUID) in wire format.
   2231  1.1  christos 	 */
   2232  1.1  christos 	dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
   2233  1.1  christos 				    NULL, client->sent_options, &global_scope,
   2234  1.1  christos 				    &dhcpv6_universe);
   2235  1.1  christos 
   2236  1.1  christos 	/* Transmit and wait. */
   2237  1.1  christos 
   2238  1.1  christos 	log_info("XMT: Info-Request on %s, interval %ld0ms.",
   2239  1.1  christos 		 client->name ? client->name : client->interface->name,
   2240  1.1  christos 		 (long int)client->RT);
   2241  1.1  christos 
   2242  1.1  christos 	send_ret = send_packet6(client->interface,
   2243  1.1  christos 				ds.data, ds.len, &DHCPv6DestAddr);
   2244  1.1  christos 	if (send_ret != ds.len) {
   2245  1.1  christos 		log_error("dhc6: send_packet6() sent %d of %d bytes",
   2246  1.1  christos 			  send_ret, ds.len);
   2247  1.1  christos 	}
   2248  1.1  christos 
   2249  1.1  christos 	data_string_forget(&ds, MDL);
   2250  1.1  christos 
   2251  1.1  christos 	/* Wait RT */
   2252  1.1  christos 	tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
   2253  1.1  christos 	tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
   2254  1.1  christos 	if (tv.tv_usec >= 1000000) {
   2255  1.1  christos 		tv.tv_sec += 1;
   2256  1.1  christos 		tv.tv_usec -= 1000000;
   2257  1.1  christos 	}
   2258  1.1  christos 	add_timeout(&tv, do_info_request6, client, NULL, NULL);
   2259  1.1  christos 
   2260  1.1  christos 	dhc6_retrans_advance(client);
   2261  1.1  christos }
   2262  1.1  christos 
   2263  1.1  christos /* do_confirm6() creates a Confirm packet and transmits it.  This function
   2264  1.1  christos  * is called on every timeout to (re)transmit.
   2265  1.1  christos  */
   2266  1.1  christos void
   2267  1.1  christos do_confirm6(void *input)
   2268  1.1  christos {
   2269  1.1  christos 	struct client_state *client;
   2270  1.1  christos 	struct data_string ds;
   2271  1.1  christos 	int send_ret, added;
   2272  1.1  christos 	struct timeval tv;
   2273  1.1  christos 
   2274  1.1  christos 	client = input;
   2275  1.1  christos 
   2276  1.1  christos 	if (client->active_lease == NULL)
   2277  1.1  christos 		log_fatal("Impossible condition at %s:%d.", MDL);
   2278  1.1  christos 
   2279  1.1  christos 	/* In section 17.1.3, it is said:
   2280  1.1  christos 	 *
   2281  1.1  christos 	 *   If the client receives no responses before the message
   2282  1.1  christos 	 *   transmission process terminates, as described in section 14,
   2283  1.1  christos 	 *   the client SHOULD continue to use any IP addresses, using the
   2284  1.1  christos 	 *   last known lifetimes for those addresses, and SHOULD continue
   2285  1.1  christos 	 *   to use any other previously obtained configuration parameters.
   2286  1.1  christos 	 *
   2287  1.1  christos 	 * So if confirm times out, we go active.
   2288  1.1  christos 	 *
   2289  1.1  christos 	 * XXX: Should we reduce all IA's t1 to 0, so that we renew and
   2290  1.1  christos 	 * stick there until we get a reply?
   2291  1.1  christos 	 */
   2292  1.1  christos 
   2293  1.1  christos 	switch(check_timing6(client, DHCPV6_CONFIRM, "Confirm",
   2294  1.1  christos 			     client->active_lease, &ds)) {
   2295  1.1  christos 	      case CHK_TIM_MRC_EXCEEDED:
   2296  1.1  christos 	      case CHK_TIM_MRD_EXCEEDED:
   2297  1.1  christos 		start_bound(client);
   2298  1.1  christos 		return;
   2299  1.1  christos 	      case CHK_TIM_ALLOC_FAILURE:
   2300  1.1  christos 		return;
   2301  1.1  christos 	      case CHK_TIM_SUCCESS:
   2302  1.1  christos 		break;
   2303  1.1  christos 	}
   2304  1.1  christos 
   2305  1.1  christos 	/* Fetch any configured 'sent' options (includes DUID') in wire format.
   2306  1.1  christos 	 */
   2307  1.1  christos 	dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
   2308  1.1  christos 				    client->sent_options, &global_scope,
   2309  1.1  christos 				    &dhcpv6_universe);
   2310  1.1  christos 
   2311  1.1  christos 	/* Append IA's. */
   2312  1.1  christos 	if (wanted_ia_na &&
   2313  1.1  christos 	    dhc6_add_ia_na(client, &ds, client->active_lease,
   2314  1.1  christos 			   DHCPV6_CONFIRM, 0, &added) != ISC_R_SUCCESS) {
   2315  1.1  christos 		data_string_forget(&ds, MDL);
   2316  1.1  christos 		return;
   2317  1.1  christos 	}
   2318  1.1  christos 	if (wanted_ia_ta &&
   2319  1.1  christos 	    dhc6_add_ia_ta(client, &ds, client->active_lease,
   2320  1.1  christos 			   DHCPV6_CONFIRM, 0, &added) != ISC_R_SUCCESS) {
   2321  1.1  christos 		data_string_forget(&ds, MDL);
   2322  1.1  christos 		return;
   2323  1.1  christos 	}
   2324  1.1  christos 
   2325  1.1  christos 	/* Transmit and wait. */
   2326  1.1  christos 
   2327  1.1  christos 	log_info("XMT: Confirm on %s, interval %ld0ms.",
   2328  1.1  christos 		 client->name ? client->name : client->interface->name,
   2329  1.1  christos 		 (long int)client->RT);
   2330  1.1  christos 
   2331  1.1  christos 	send_ret = send_packet6(client->interface, ds.data, ds.len,
   2332  1.1  christos 				&DHCPv6DestAddr);
   2333  1.1  christos 	if (send_ret != ds.len) {
   2334  1.1  christos 		log_error("dhc6: sendpacket6() sent %d of %d bytes",
   2335  1.1  christos 			  send_ret, ds.len);
   2336  1.1  christos 	}
   2337  1.1  christos 
   2338  1.1  christos 	data_string_forget(&ds, MDL);
   2339  1.1  christos 
   2340  1.1  christos 	/* Wait RT */
   2341  1.1  christos 	tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
   2342  1.1  christos 	tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
   2343  1.1  christos 	if (tv.tv_usec >= 1000000) {
   2344  1.1  christos 		tv.tv_sec += 1;
   2345  1.1  christos 		tv.tv_usec -= 1000000;
   2346  1.1  christos 	}
   2347  1.1  christos 	add_timeout(&tv, do_confirm6, client, NULL, NULL);
   2348  1.1  christos 
   2349  1.1  christos 	dhc6_retrans_advance(client);
   2350  1.1  christos }
   2351  1.1  christos 
   2352  1.1  christos /*
   2353  1.1  christos  * Release addresses.
   2354  1.1  christos  */
   2355  1.1  christos void
   2356  1.1  christos start_release6(struct client_state *client)
   2357  1.1  christos {
   2358  1.1  christos 	/* Cancel any pending transmissions */
   2359  1.1  christos 	cancel_timeout(do_confirm6, client);
   2360  1.1  christos 	cancel_timeout(do_select6, client);
   2361  1.1  christos 	cancel_timeout(do_refresh6, client);
   2362  1.1  christos 	cancel_timeout(do_release6, client);
   2363  1.1  christos 	cancel_timeout(do_decline6, client);
   2364  1.1  christos 	client->state = S_STOPPED;
   2365  1.1  christos 
   2366  1.1  christos 	/*
   2367  1.1  christos 	 * It is written:  "The client MUST NOT use any of the addresses it
   2368  1.1  christos 	 * is releasing as the source address in the Release message or in
   2369  1.1  christos 	 * any subsequently transmitted message."  So unconfigure now.
   2370  1.1  christos 	 */
   2371  1.1  christos 	unconfigure6(client, "RELEASE6");
   2372  1.1  christos 
   2373  1.1  christos 	/* Note this in the lease file. */
   2374  1.1  christos 	if (client->active_lease == NULL)
   2375  1.1  christos 		return;
   2376  1.1  christos 	client->active_lease->released = ISC_TRUE;
   2377  1.1  christos 	write_client6_lease(client, client->active_lease, 0, 1);
   2378  1.1  christos 
   2379  1.1  christos 	/* Set timers per RFC3315 section 18.1.6. */
   2380  1.1  christos 	client->IRT = REL_TIMEOUT * 100;
   2381  1.1  christos 	client->MRT = 0;
   2382  1.1  christos 	client->MRC = REL_MAX_RC;
   2383  1.1  christos 	client->MRD = 0;
   2384  1.1  christos 
   2385  1.1  christos 	dhc6_retrans_init(client);
   2386  1.1  christos 	client->v6_handler = reply_handler;
   2387  1.1  christos 
   2388  1.1  christos 	do_release6(client);
   2389  1.1  christos }
   2390  1.1  christos /*
   2391  1.1  christos  * do_release6() creates a Release packet and transmits it.
   2392  1.1  christos  */
   2393  1.1  christos static void
   2394  1.1  christos do_release6(void *input)
   2395  1.1  christos {
   2396  1.1  christos 	struct client_state *client;
   2397  1.1  christos 	struct data_string ds;
   2398  1.1  christos 	int send_ret, added;
   2399  1.1  christos 	struct timeval tv;
   2400  1.1  christos 
   2401  1.1  christos 	client = input;
   2402  1.1  christos 
   2403  1.1  christos 	if ((client->active_lease == NULL) || !active_prefix(client))
   2404  1.1  christos 		return;
   2405  1.1  christos 
   2406  1.1  christos 	switch(check_timing6(client, DHCPV6_RELEASE, "Release",
   2407  1.1  christos 			     client->active_lease, &ds)) {
   2408  1.1  christos 	      case CHK_TIM_MRC_EXCEEDED:
   2409  1.1  christos 	      case CHK_TIM_ALLOC_FAILURE:
   2410  1.1  christos 	      case CHK_TIM_MRD_EXCEEDED:
   2411  1.1  christos 		goto release_done;
   2412  1.1  christos 	      case CHK_TIM_SUCCESS:
   2413  1.1  christos 		break;
   2414  1.1  christos 	}
   2415  1.1  christos 
   2416  1.1  christos 	/*
   2417  1.1  christos 	 * Don't use unicast as we don't know if we still have an
   2418  1.1  christos 	 * available address with enough scope.
   2419  1.1  christos 	 */
   2420  1.1  christos 
   2421  1.1  christos 	dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
   2422  1.1  christos 				    client->sent_options, &global_scope,
   2423  1.1  christos 				    &dhcpv6_universe);
   2424  1.1  christos 
   2425  1.1  christos 	/* Append IA's (but don't release temporary addresses). */
   2426  1.1  christos 	if (wanted_ia_na &&
   2427  1.1  christos 	    dhc6_add_ia_na(client, &ds, client->active_lease,
   2428  1.1  christos 			   DHCPV6_RELEASE, 0, &added) != ISC_R_SUCCESS) {
   2429  1.1  christos 		data_string_forget(&ds, MDL);
   2430  1.1  christos 		goto release_done;
   2431  1.1  christos 	}
   2432  1.1  christos 	if (wanted_ia_pd &&
   2433  1.1  christos 	    dhc6_add_ia_pd(client, &ds, client->active_lease,
   2434  1.1  christos 			   DHCPV6_RELEASE, 0, &added) != ISC_R_SUCCESS) {
   2435  1.1  christos 		data_string_forget(&ds, MDL);
   2436  1.1  christos 		goto release_done;
   2437  1.1  christos 	}
   2438  1.1  christos 
   2439  1.1  christos 	/* Transmit and wait. */
   2440  1.1  christos 	log_info("XMT: Release on %s, interval %ld0ms.",
   2441  1.1  christos 		 client->name ? client->name : client->interface->name,
   2442  1.1  christos 		 (long int)client->RT);
   2443  1.1  christos 
   2444  1.1  christos 	send_ret = send_packet6(client->interface, ds.data, ds.len,
   2445  1.1  christos 				&DHCPv6DestAddr);
   2446  1.1  christos 	if (send_ret != ds.len) {
   2447  1.1  christos 		log_error("dhc6: sendpacket6() sent %d of %d bytes",
   2448  1.1  christos 			  send_ret, ds.len);
   2449  1.1  christos 	}
   2450  1.1  christos 
   2451  1.1  christos 	data_string_forget(&ds, MDL);
   2452  1.1  christos 
   2453  1.1  christos 	/* Wait RT */
   2454  1.1  christos 	tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
   2455  1.1  christos 	tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
   2456  1.1  christos 	if (tv.tv_usec >= 1000000) {
   2457  1.1  christos 		tv.tv_sec += 1;
   2458  1.1  christos 		tv.tv_usec -= 1000000;
   2459  1.1  christos 	}
   2460  1.1  christos 	add_timeout(&tv, do_release6, client, NULL, NULL);
   2461  1.1  christos 	dhc6_retrans_advance(client);
   2462  1.1  christos 	return;
   2463  1.1  christos 
   2464  1.1  christos       release_done:
   2465  1.1  christos 	dhc6_lease_destroy(&client->active_lease, MDL);
   2466  1.1  christos 	client->active_lease = NULL;
   2467  1.1  christos 	if (stopping_finished())
   2468  1.1  christos 		finish(0);
   2469  1.1  christos }
   2470  1.1  christos 
   2471  1.1  christos /* status_log() just puts a status code into displayable form and logs it
   2472  1.1  christos  * to info level.
   2473  1.1  christos  */
   2474  1.1  christos static void
   2475  1.1  christos status_log(int code, const char *scope, const char *additional, int len)
   2476  1.1  christos {
   2477  1.1  christos 	const char *msg = NULL;
   2478  1.1  christos 
   2479  1.1  christos 	switch(code) {
   2480  1.1  christos 	      case STATUS_Success:
   2481  1.1  christos 		msg = "Success";
   2482  1.1  christos 		break;
   2483  1.1  christos 
   2484  1.1  christos 	      case STATUS_UnspecFail:
   2485  1.1  christos 		msg = "UnspecFail";
   2486  1.1  christos 		break;
   2487  1.1  christos 
   2488  1.1  christos 	      case STATUS_NoAddrsAvail:
   2489  1.1  christos 		msg = "NoAddrsAvail";
   2490  1.1  christos 		break;
   2491  1.1  christos 
   2492  1.1  christos 	      case STATUS_NoBinding:
   2493  1.1  christos 		msg = "NoBinding";
   2494  1.1  christos 		break;
   2495  1.1  christos 
   2496  1.1  christos 	      case STATUS_NotOnLink:
   2497  1.1  christos 		msg = "NotOnLink";
   2498  1.1  christos 		break;
   2499  1.1  christos 
   2500  1.1  christos 	      case STATUS_UseMulticast:
   2501  1.1  christos 		msg = "UseMulticast";
   2502  1.1  christos 		break;
   2503  1.1  christos 
   2504  1.1  christos 	      case STATUS_NoPrefixAvail:
   2505  1.1  christos 		msg = "NoPrefixAvail";
   2506  1.1  christos 		break;
   2507  1.1  christos 
   2508  1.1  christos 	      default:
   2509  1.1  christos 		msg = "UNKNOWN";
   2510  1.1  christos 		break;
   2511  1.1  christos 	}
   2512  1.1  christos 
   2513  1.1  christos 	if (len > 0)
   2514  1.1  christos 		log_info("%s status code %s: %s", scope, msg,
   2515  1.1  christos 			 print_hex_1(len,
   2516  1.1  christos 				     (const unsigned char *)additional, 50));
   2517  1.1  christos 	else
   2518  1.1  christos 		log_info("%s status code %s.", scope, msg);
   2519  1.1  christos }
   2520  1.1  christos 
   2521  1.1  christos /* Acquire a status code.
   2522  1.1  christos  */
   2523  1.1  christos static isc_result_t
   2524  1.1  christos dhc6_get_status_code(struct option_state *options, unsigned *code,
   2525  1.1  christos 		     struct data_string *msg)
   2526  1.1  christos {
   2527  1.1  christos 	struct option_cache *oc;
   2528  1.1  christos 	struct data_string ds;
   2529  1.1  christos 	isc_result_t rval = ISC_R_SUCCESS;
   2530  1.1  christos 
   2531  1.1  christos 	if ((options == NULL) || (code == NULL))
   2532  1.1  christos 		return DHCP_R_INVALIDARG;
   2533  1.1  christos 
   2534  1.1  christos 	if ((msg != NULL) && (msg->len != 0))
   2535  1.1  christos 		return DHCP_R_INVALIDARG;
   2536  1.1  christos 
   2537  1.1  christos 	memset(&ds, 0, sizeof(ds));
   2538  1.1  christos 
   2539  1.1  christos 	/* Assume success if there is no option. */
   2540  1.1  christos 	*code = STATUS_Success;
   2541  1.1  christos 
   2542  1.1  christos 	oc = lookup_option(&dhcpv6_universe, options, D6O_STATUS_CODE);
   2543  1.1  christos 	if ((oc != NULL) &&
   2544  1.1  christos 	    evaluate_option_cache(&ds, NULL, NULL, NULL, options,
   2545  1.1  christos 				  NULL, &global_scope, oc, MDL)) {
   2546  1.1  christos 		if (ds.len < 2) {
   2547  1.1  christos 			log_error("Invalid status code length %d.", ds.len);
   2548  1.1  christos 			rval = DHCP_R_FORMERR;
   2549  1.1  christos 		} else
   2550  1.1  christos 			*code = getUShort(ds.data);
   2551  1.1  christos 
   2552  1.1  christos 		if ((msg != NULL) && (ds.len > 2)) {
   2553  1.1  christos 			data_string_copy(msg, &ds, MDL);
   2554  1.1  christos 			msg->data += 2;
   2555  1.1  christos 			msg->len -= 2;
   2556  1.1  christos 		}
   2557  1.1  christos 
   2558  1.1  christos 		data_string_forget(&ds, MDL);
   2559  1.1  christos 		return rval;
   2560  1.1  christos 	}
   2561  1.1  christos 
   2562  1.1  christos 	return ISC_R_NOTFOUND;
   2563  1.1  christos }
   2564  1.1  christos 
   2565  1.1  christos /* Look at status codes in an advertise, and reform the return value.
   2566  1.1  christos  */
   2567  1.1  christos static isc_result_t
   2568  1.1  christos dhc6_check_status(isc_result_t rval, struct option_state *options,
   2569  1.1  christos 		  const char *scope, unsigned *code)
   2570  1.1  christos {
   2571  1.1  christos 	struct data_string msg;
   2572  1.1  christos 	isc_result_t status;
   2573  1.1  christos 
   2574  1.1  christos 	if ((scope == NULL) || (code == NULL))
   2575  1.1  christos 		return DHCP_R_INVALIDARG;
   2576  1.1  christos 
   2577  1.1  christos 	/* If we don't find a code, we assume success. */
   2578  1.1  christos 	*code = STATUS_Success;
   2579  1.1  christos 
   2580  1.1  christos 	/* If there is no options cache, then there is no code. */
   2581  1.1  christos 	if (options != NULL) {
   2582  1.1  christos 		memset(&msg, 0, sizeof(msg));
   2583  1.1  christos 		status = dhc6_get_status_code(options, code, &msg);
   2584  1.1  christos 
   2585  1.1  christos 		if (status == ISC_R_SUCCESS) {
   2586  1.1  christos 			status_log(*code, scope, (char *)msg.data, msg.len);
   2587  1.1  christos 			data_string_forget(&msg, MDL);
   2588  1.1  christos 
   2589  1.1  christos 			if (*code != STATUS_Success)
   2590  1.1  christos 				rval = ISC_R_FAILURE;
   2591  1.1  christos 
   2592  1.1  christos 		} else if (status != ISC_R_NOTFOUND)
   2593  1.1  christos 			rval = status;
   2594  1.1  christos 	}
   2595  1.1  christos 
   2596  1.1  christos 	return rval;
   2597  1.1  christos }
   2598  1.1  christos 
   2599  1.1  christos /* Determine if this packet could provide usable information.
   2600  1.1  christos  * We check the status codes at the top level and at the IA level,
   2601  1.1  christos  * IAADDRS have already been checked in the leaseify step and any with
   2602  1.1  christos  * a bad format or status code that wasn't success have been dropped.
   2603  1.1  christos  *
   2604  1.1  christos  * leaseify has also already removed any IAs for which the top level status
   2605  1.1  christos  * code or the IA status code indicated no addresses or prefixes were
   2606  1.1  christos  * available.
   2607  1.1  christos  */
   2608  1.1  christos static isc_result_t
   2609  1.1  christos dhc6_check_advertise(struct dhc6_lease *lease)
   2610  1.1  christos {
   2611  1.1  christos 	struct dhc6_ia *ia;
   2612  1.1  christos 	isc_result_t rval = ISC_R_SUCCESS;
   2613  1.1  christos 	int have_addrs = ISC_FALSE;
   2614  1.1  christos 	unsigned code;
   2615  1.1  christos 	const char *scope;
   2616  1.1  christos 	int got_na = 0, got_ta = 0, got_pd = 0;
   2617  1.1  christos 
   2618  1.1  christos 	rval = dhc6_check_status(rval, lease->options, "message", &code);
   2619  1.1  christos 
   2620  1.1  christos 	for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
   2621  1.1  christos 		switch (ia->ia_type) {
   2622  1.1  christos 			case D6O_IA_NA:
   2623  1.1  christos 				scope = "IA_NA";
   2624  1.1  christos 				got_na++;
   2625  1.1  christos 				break;
   2626  1.1  christos 			case D6O_IA_TA:
   2627  1.1  christos 				scope = "IA_TA";
   2628  1.1  christos 				got_ta++;
   2629  1.1  christos 				break;
   2630  1.1  christos 			case D6O_IA_PD:
   2631  1.1  christos 				scope = "IA_PD";
   2632  1.1  christos 				got_pd++;
   2633  1.1  christos 				break;
   2634  1.1  christos 			default:
   2635  1.1  christos 				log_error("dhc6_check_advertise: no type.");
   2636  1.1  christos 				return ISC_R_FAILURE;
   2637  1.1  christos 		}
   2638  1.1  christos 		/* Currently we toss packets if we have an error getting a
   2639  1.1  christos 		 * status code or if the status code isn't success, so
   2640  1.1  christos 		 * no need to loop through the addresses */
   2641  1.1  christos 		rval = dhc6_check_status(rval, ia->options, scope, &code);
   2642  1.1  christos 		if (rval != ISC_R_SUCCESS)
   2643  1.1  christos 			continue;
   2644  1.1  christos 
   2645  1.1  christos 		/* We don't need to check status on IAADDRS here as we already
   2646  1.1  christos 		 * did it as part of the leaseify step and tossed bad IAADDRS.
   2647  1.1  christos 		 * We are just checking to see if we have any addrs.
   2648  1.1  christos 		 * Should we check the addr itself for usability?
   2649  1.1  christos 		 */
   2650  1.1  christos 		if (ia->addrs != NULL) {
   2651  1.1  christos 			have_addrs = ISC_TRUE;
   2652  1.1  christos 		}
   2653  1.1  christos 	}
   2654  1.1  christos 
   2655  1.1  christos 	/* If we didn't get some addrs or the user required us to
   2656  1.1  christos 	 * get all of the requested IAs and we didn't return an error
   2657  1.1  christos 	 */
   2658  1.1  christos 	if ((have_addrs != ISC_TRUE) ||
   2659  1.1  christos 	    ((require_all_ias != 0) &&
   2660  1.1  christos 	     ((got_na < wanted_ia_na) ||
   2661  1.1  christos 	      (got_ta < wanted_ia_ta) ||
   2662  1.1  christos 	      (got_pd < wanted_ia_pd))))
   2663  1.1  christos 		rval = ISC_R_ADDRNOTAVAIL;
   2664  1.1  christos 
   2665  1.1  christos 	return rval;
   2666  1.1  christos }
   2667  1.1  christos 
   2668  1.1  christos /* status code <-> action matrix for the client in INIT state
   2669  1.1  christos  * (rapid/commit).  Returns always false as no action is defined.
   2670  1.1  christos  */
   2671  1.1  christos static isc_boolean_t
   2672  1.1  christos dhc6_init_action(struct client_state *client, isc_result_t *rvalp,
   2673  1.1  christos 		 unsigned code)
   2674  1.1  christos {
   2675  1.1  christos 	if (rvalp == NULL)
   2676  1.1  christos 		log_fatal("Impossible condition at %s:%d.", MDL);
   2677  1.1  christos 
   2678  1.1  christos 	if (client == NULL) {
   2679  1.1  christos 		*rvalp = DHCP_R_INVALIDARG;
   2680  1.1  christos 		return ISC_FALSE;
   2681  1.1  christos 	}
   2682  1.1  christos 
   2683  1.1  christos 	if (*rvalp == ISC_R_SUCCESS)
   2684  1.1  christos 		return ISC_FALSE;
   2685  1.1  christos 
   2686  1.1  christos 	/* No possible action in any case... */
   2687  1.1  christos 	return ISC_FALSE;
   2688  1.1  christos }
   2689  1.1  christos 
   2690  1.1  christos /* status code <-> action matrix for the client in SELECT state
   2691  1.1  christos  * (request/reply).  Returns true if action was taken (and the
   2692  1.1  christos  * packet should be ignored), or false if no action was taken.
   2693  1.1  christos  */
   2694  1.1  christos static isc_boolean_t
   2695  1.1  christos dhc6_select_action(struct client_state *client, isc_result_t *rvalp,
   2696  1.1  christos 		   unsigned code)
   2697  1.1  christos {
   2698  1.1  christos 	struct dhc6_lease *lease;
   2699  1.1  christos 	isc_result_t rval;
   2700  1.1  christos 
   2701  1.1  christos 	if (rvalp == NULL)
   2702  1.1  christos 		log_fatal("Impossible condition at %s:%d.", MDL);
   2703  1.1  christos 
   2704  1.1  christos 	if (client == NULL) {
   2705  1.1  christos 		*rvalp = DHCP_R_INVALIDARG;
   2706  1.1  christos 		return ISC_FALSE;
   2707  1.1  christos 	}
   2708  1.1  christos 	rval = *rvalp;
   2709  1.1  christos 
   2710  1.1  christos 	if (rval == ISC_R_SUCCESS)
   2711  1.1  christos 		return ISC_FALSE;
   2712  1.1  christos 
   2713  1.1  christos 	switch (code) {
   2714  1.1  christos 		/* We may have an earlier failure status code (so no
   2715  1.1  christos 		 * success rval), and a success code now.  This
   2716  1.1  christos 		 * doesn't upgrade the rval to success, but it does
   2717  1.1  christos 		 * mean we take no action here.
   2718  1.1  christos 		 */
   2719  1.1  christos 	      case STATUS_Success:
   2720  1.1  christos 		/* Gimpy server, or possibly an attacker. */
   2721  1.1  christos 	      case STATUS_NoBinding:
   2722  1.1  christos 	      case STATUS_UseMulticast:
   2723  1.1  christos 		/* Take no action. */
   2724  1.1  christos 		return ISC_FALSE;
   2725  1.1  christos 
   2726  1.1  christos 		/* If the server can't deal with us, either try the
   2727  1.1  christos 		 * next advertised server, or continue retrying if there
   2728  1.1  christos 		 * weren't any.
   2729  1.1  christos 		 */
   2730  1.1  christos 	      default:
   2731  1.1  christos 	      case STATUS_UnspecFail:
   2732  1.1  christos 		if (client->advertised_leases != NULL) {
   2733  1.1  christos 			dhc6_lease_destroy(&client->selected_lease, MDL);
   2734  1.1  christos 			client->selected_lease = NULL;
   2735  1.1  christos 
   2736  1.1  christos 			start_selecting6(client);
   2737  1.1  christos 
   2738  1.1  christos 			break;
   2739  1.1  christos 		} else /* Take no action - continue to retry. */
   2740  1.1  christos 			return ISC_FALSE;
   2741  1.1  christos 
   2742  1.1  christos 		/* If the server has no addresses, try other servers if
   2743  1.1  christos 		 * we got some, otherwise go to INIT to hope for more
   2744  1.1  christos 		 * servers.
   2745  1.1  christos 		 */
   2746  1.1  christos 	      case STATUS_NoAddrsAvail:
   2747  1.1  christos 	      case STATUS_NoPrefixAvail:
   2748  1.1  christos 		if (client->state == S_REBOOTING)
   2749  1.1  christos 			return ISC_FALSE;
   2750  1.1  christos 
   2751  1.1  christos 		if (client->selected_lease == NULL)
   2752  1.1  christos 			log_fatal("Impossible case at %s:%d.", MDL);
   2753  1.1  christos 
   2754  1.1  christos 		dhc6_lease_destroy(&client->selected_lease, MDL);
   2755  1.1  christos 		client->selected_lease = NULL;
   2756  1.1  christos 
   2757  1.1  christos 		if (client->advertised_leases != NULL)
   2758  1.1  christos 			start_selecting6(client);
   2759  1.1  christos 		else
   2760  1.1  christos 			start_init6(client);
   2761  1.1  christos 
   2762  1.1  christos 		break;
   2763  1.1  christos 
   2764  1.1  christos 		/* If we got a NotOnLink from a Confirm, then we're not
   2765  1.1  christos 		 * on link.  Kill the old-active binding and start over.
   2766  1.1  christos 		 *
   2767  1.1  christos 		 * If we got a NotOnLink from our Request, something weird
   2768  1.1  christos 		 * happened.  Start over from scratch anyway.
   2769  1.1  christos 		 */
   2770  1.1  christos 	      case STATUS_NotOnLink:
   2771  1.1  christos 		if (client->state == S_REBOOTING) {
   2772  1.1  christos 			if (client->active_lease == NULL)
   2773  1.1  christos 				log_fatal("Impossible case at %s:%d.", MDL);
   2774  1.1  christos 
   2775  1.1  christos 			dhc6_lease_destroy(&client->active_lease, MDL);
   2776  1.1  christos 		} else {
   2777  1.1  christos 			if (client->selected_lease == NULL)
   2778  1.1  christos 				log_fatal("Impossible case at %s:%d.", MDL);
   2779  1.1  christos 
   2780  1.1  christos 			dhc6_lease_destroy(&client->selected_lease, MDL);
   2781  1.1  christos 			client->selected_lease = NULL;
   2782  1.1  christos 
   2783  1.1  christos 			while (client->advertised_leases != NULL) {
   2784  1.1  christos 				lease = client->advertised_leases;
   2785  1.1  christos 				client->advertised_leases = lease->next;
   2786  1.1  christos 
   2787  1.1  christos 				dhc6_lease_destroy(&lease, MDL);
   2788  1.1  christos 			}
   2789  1.1  christos 		}
   2790  1.1  christos 
   2791  1.1  christos 		start_init6(client);
   2792  1.1  christos 		break;
   2793  1.1  christos 	}
   2794  1.1  christos 
   2795  1.1  christos 	return ISC_TRUE;
   2796  1.1  christos }
   2797  1.1  christos 
   2798  1.1  christos static void
   2799  1.1  christos dhc6_withdraw_lease(struct client_state *client)
   2800  1.1  christos {
   2801  1.1  christos 	struct dhc6_ia *ia;
   2802  1.1  christos 	struct dhc6_addr *addr;
   2803  1.1  christos 
   2804  1.1  christos 	if ((client == NULL) || (client->active_lease == NULL))
   2805  1.1  christos 		return;
   2806  1.1  christos 
   2807  1.1  christos 	for (ia = client->active_lease->bindings ; ia != NULL ;
   2808  1.1  christos 	     ia = ia->next) {
   2809  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   2810  1.1  christos 			addr->max_life = addr->preferred_life = 0;
   2811  1.1  christos 		}
   2812  1.1  christos 	}
   2813  1.1  christos 
   2814  1.1  christos 	/* Perform expiry. */
   2815  1.1  christos 	do_expire(client);
   2816  1.1  christos }
   2817  1.1  christos 
   2818  1.1  christos /* status code <-> action matrix for the client in BOUND state
   2819  1.1  christos  * (request/reply).  Returns true if action was taken (and the
   2820  1.1  christos  * packet should be ignored), or false if no action was taken.
   2821  1.1  christos  */
   2822  1.1  christos static isc_boolean_t
   2823  1.1  christos dhc6_reply_action(struct client_state *client, isc_result_t *rvalp,
   2824  1.1  christos 		  unsigned code)
   2825  1.1  christos {
   2826  1.1  christos 	isc_result_t rval;
   2827  1.1  christos 
   2828  1.1  christos 	if (rvalp == NULL)
   2829  1.1  christos 		log_fatal("Impossible condition at %s:%d.", MDL);
   2830  1.1  christos 
   2831  1.1  christos 	if (client == NULL) {
   2832  1.1  christos 		*rvalp = DHCP_R_INVALIDARG;
   2833  1.1  christos 		return ISC_FALSE;
   2834  1.1  christos 	}
   2835  1.1  christos 	rval = *rvalp;
   2836  1.1  christos 
   2837  1.1  christos 	if (rval == ISC_R_SUCCESS)
   2838  1.1  christos 		return ISC_FALSE;
   2839  1.1  christos 
   2840  1.1  christos 	switch (code) {
   2841  1.1  christos 		/* It's possible an earlier status code set rval to a failure
   2842  1.1  christos 		 * code, and we've encountered a later success.
   2843  1.1  christos 		 */
   2844  1.1  christos 	      case STATUS_Success:
   2845  1.1  christos 		/* In "refreshes" (where we get replies), we probably
   2846  1.1  christos 		 * still have a valid lease.  So "take no action" and
   2847  1.1  christos 		 * the upper levels will keep retrying until the lease
   2848  1.1  christos 		 * expires (or we rebind).
   2849  1.1  christos 		 */
   2850  1.1  christos 	      case STATUS_UnspecFail:
   2851  1.1  christos 		/* For unknown codes...it's a soft (retryable) error. */
   2852  1.1  christos 	      default:
   2853  1.1  christos 		return ISC_FALSE;
   2854  1.1  christos 
   2855  1.1  christos 		/* The server is telling us to use a multicast address, so
   2856  1.1  christos 		 * we have to delete the unicast option from the active
   2857  1.1  christos 		 * lease, then allow retransmission to occur normally.
   2858  1.1  christos 		 * (XXX: It might be preferable in this case to retransmit
   2859  1.1  christos 		 * sooner than the current interval, but for now we don't.)
   2860  1.1  christos 		 */
   2861  1.1  christos 	      case STATUS_UseMulticast:
   2862  1.1  christos 		if (client->active_lease != NULL)
   2863  1.1  christos 			delete_option(&dhcp_universe,
   2864  1.1  christos 				      client->active_lease->options,
   2865  1.1  christos 				      D6O_UNICAST);
   2866  1.1  christos 		return ISC_FALSE;
   2867  1.1  christos 
   2868  1.1  christos 		/* "When the client receives a NotOnLink status from the
   2869  1.1  christos 		 *  server in response to a Request, the client can either
   2870  1.1  christos 		 *  re-issue the Request without specifying any addresses
   2871  1.1  christos 		 *  or restart the DHCP server discovery process."
   2872  1.1  christos 		 *
   2873  1.1  christos 		 * This is strange.  If competing server evaluation is
   2874  1.1  christos 		 * useful (and therefore in the protocol), then why would
   2875  1.1  christos 		 * a client's first reaction be to request from the same
   2876  1.1  christos 		 * server on a different link?  Surely you'd want to
   2877  1.1  christos 		 * re-evaluate your server selection.
   2878  1.1  christos 		 *
   2879  1.1  christos 		 * Well, I guess that's the answer.
   2880  1.1  christos 		 */
   2881  1.1  christos 	      case STATUS_NotOnLink:
   2882  1.1  christos 		/* In this case, we need to rescind all current active
   2883  1.1  christos 		 * bindings (just 'expire' them all normally, if early).
   2884  1.1  christos 		 * They're no use to us on the wrong link.  Then head back
   2885  1.1  christos 		 * to init, redo server selection and get new addresses.
   2886  1.1  christos 		 */
   2887  1.1  christos 		dhc6_withdraw_lease(client);
   2888  1.1  christos 		break;
   2889  1.1  christos 
   2890  1.1  christos 		/* "If the status code is NoAddrsAvail, the client has
   2891  1.1  christos 		 *  received no usable addresses in the IA and may choose
   2892  1.1  christos 		 *  to try obtaining addresses for the IA from another
   2893  1.1  christos 		 *  server."
   2894  1.1  christos 		 */
   2895  1.1  christos 	      case STATUS_NoAddrsAvail:
   2896  1.1  christos 	      case STATUS_NoPrefixAvail:
   2897  1.1  christos 		/* Head back to init, keeping any active bindings (!). */
   2898  1.1  christos 		start_init6(client);
   2899  1.1  christos 		break;
   2900  1.1  christos 
   2901  1.1  christos 		/* -  sends a Request message if the IA contained a Status
   2902  1.1  christos 		 *    Code option with the NoBinding status (and does not
   2903  1.1  christos 		 *    send any additional Renew/Rebind messages)
   2904  1.1  christos 		 */
   2905  1.1  christos 	      case STATUS_NoBinding:
   2906  1.1  christos 		if (client->advertised_leases != NULL)
   2907  1.1  christos 			log_fatal("Impossible condition at %s:%d.", MDL);
   2908  1.1  christos 
   2909  1.1  christos 		client->advertised_leases =
   2910  1.1  christos 				dhc6_dup_lease(client->active_lease, MDL);
   2911  1.1  christos 		start_selecting6(client);
   2912  1.1  christos 		break;
   2913  1.1  christos 	}
   2914  1.1  christos 
   2915  1.1  christos 	return ISC_TRUE;
   2916  1.1  christos }
   2917  1.1  christos 
   2918  1.1  christos /* status code <-> action matrix for the client in STOPPED state
   2919  1.1  christos  * (release/decline).  Returns true if action was taken (and the
   2920  1.1  christos  * packet should be ignored), or false if no action was taken.
   2921  1.1  christos  * NoBinding is translated into Success.
   2922  1.1  christos  */
   2923  1.1  christos static isc_boolean_t
   2924  1.1  christos dhc6_stop_action(struct client_state *client, isc_result_t *rvalp,
   2925  1.1  christos 		  unsigned code)
   2926  1.1  christos {
   2927  1.1  christos 	isc_result_t rval;
   2928  1.1  christos 
   2929  1.1  christos 	if (rvalp == NULL)
   2930  1.1  christos 		log_fatal("Impossible condition at %s:%d.", MDL);
   2931  1.1  christos 
   2932  1.1  christos 	if (client == NULL) {
   2933  1.1  christos 		*rvalp = DHCP_R_INVALIDARG;
   2934  1.1  christos 		return ISC_FALSE;
   2935  1.1  christos 	}
   2936  1.1  christos 	rval = *rvalp;
   2937  1.1  christos 
   2938  1.1  christos 	if (rval == ISC_R_SUCCESS)
   2939  1.1  christos 		return ISC_FALSE;
   2940  1.1  christos 
   2941  1.1  christos 	switch (code) {
   2942  1.1  christos 		/* It's possible an earlier status code set rval to a failure
   2943  1.1  christos 		 * code, and we've encountered a later success.
   2944  1.1  christos 		 */
   2945  1.1  christos 	      case STATUS_Success:
   2946  1.1  christos 		/* For unknown codes...it's a soft (retryable) error. */
   2947  1.1  christos 	      case STATUS_UnspecFail:
   2948  1.1  christos 	      default:
   2949  1.1  christos 		return ISC_FALSE;
   2950  1.1  christos 
   2951  1.1  christos 		/* NoBinding is not an error */
   2952  1.1  christos 	      case STATUS_NoBinding:
   2953  1.1  christos 		if (rval == ISC_R_FAILURE)
   2954  1.1  christos 			*rvalp = ISC_R_SUCCESS;
   2955  1.1  christos 		return ISC_FALSE;
   2956  1.1  christos 
   2957  1.1  christos 		/* Should not happen */
   2958  1.1  christos 	      case STATUS_NoAddrsAvail:
   2959  1.1  christos 	      case STATUS_NoPrefixAvail:
   2960  1.1  christos 		break;
   2961  1.1  christos 
   2962  1.1  christos 		/* Give up on it */
   2963  1.1  christos 	      case STATUS_NotOnLink:
   2964  1.1  christos 		break;
   2965  1.1  christos 
   2966  1.1  christos 		/* The server is telling us to use a multicast address, so
   2967  1.1  christos 		 * we have to delete the unicast option from the active
   2968  1.1  christos 		 * lease, then allow retransmission to occur normally.
   2969  1.1  christos 		 * (XXX: It might be preferable in this case to retransmit
   2970  1.1  christos 		 * sooner than the current interval, but for now we don't.)
   2971  1.1  christos 		 */
   2972  1.1  christos 	      case STATUS_UseMulticast:
   2973  1.1  christos 		if (client->active_lease != NULL)
   2974  1.1  christos 			delete_option(&dhcp_universe,
   2975  1.1  christos 				      client->active_lease->options,
   2976  1.1  christos 				      D6O_UNICAST);
   2977  1.1  christos 		return ISC_FALSE;
   2978  1.1  christos 	}
   2979  1.1  christos 
   2980  1.1  christos 	return ISC_TRUE;
   2981  1.1  christos }
   2982  1.1  christos 
   2983  1.1  christos static isc_boolean_t
   2984  1.1  christos dhc6_decline_action(struct client_state *client, isc_result_t *rvalp,
   2985  1.1  christos 		  unsigned code)
   2986  1.1  christos {
   2987  1.1  christos 	isc_result_t rval;
   2988  1.1  christos 
   2989  1.1  christos 	if (rvalp == NULL)
   2990  1.1  christos 		log_fatal("Impossible condition at %s:%d.", MDL);
   2991  1.1  christos 
   2992  1.1  christos 	if (client == NULL) {
   2993  1.1  christos 		*rvalp = DHCP_R_INVALIDARG;
   2994  1.1  christos 		return ISC_FALSE;
   2995  1.1  christos 	}
   2996  1.1  christos 	rval = *rvalp;
   2997  1.1  christos 
   2998  1.1  christos 	if (rval == ISC_R_SUCCESS) {
   2999  1.1  christos 		return ISC_FALSE;
   3000  1.1  christos 	}
   3001  1.1  christos 
   3002  1.1  christos 	switch (code) {
   3003  1.1  christos 	case STATUS_UseMulticast:
   3004  1.1  christos 		/* The server is telling us to use a multicast address, so
   3005  1.1  christos 		* we have to delete the unicast option from the active
   3006  1.1  christos 		* lease, then allow retransmission to occur normally.
   3007  1.1  christos 		* (XXX: It might be preferable in this case to retransmit
   3008  1.1  christos 		* sooner than the current interval, but for now we don't.)
   3009  1.1  christos 		*/
   3010  1.1  christos 		if (client->active_lease != NULL)
   3011  1.1  christos 			delete_option(&dhcp_universe,
   3012  1.1  christos 				      client->active_lease->options,
   3013  1.1  christos 				      D6O_UNICAST);
   3014  1.1  christos 		return ISC_FALSE;
   3015  1.1  christos 	default:
   3016  1.1  christos 		/* Anything else is basically meaningless */
   3017  1.1  christos 		break;
   3018  1.1  christos 	}
   3019  1.1  christos 
   3020  1.1  christos 	return ISC_TRUE;
   3021  1.1  christos }
   3022  1.1  christos 
   3023  1.1  christos 
   3024  1.1  christos /* Look at a new and old lease, and make sure the new information is not
   3025  1.1  christos  * losing us any state.
   3026  1.1  christos  */
   3027  1.1  christos static isc_result_t
   3028  1.1  christos dhc6_check_reply(struct client_state *client, struct dhc6_lease *new)
   3029  1.1  christos {
   3030  1.1  christos 	isc_boolean_t (*action)(struct client_state *,
   3031  1.1  christos 				isc_result_t *, unsigned);
   3032  1.1  christos 	struct dhc6_ia *ia;
   3033  1.1  christos 	isc_result_t rval = ISC_R_SUCCESS;
   3034  1.1  christos 	unsigned code;
   3035  1.1  christos 	const char *scope;
   3036  1.1  christos 	int nscore, sscore;
   3037  1.1  christos 	int have_addrs = ISC_FALSE;
   3038  1.1  christos 	int got_na = 0, got_ta = 0, got_pd = 0;
   3039  1.1  christos 
   3040  1.1  christos 	if ((client == NULL) || (new == NULL))
   3041  1.1  christos 		return DHCP_R_INVALIDARG;
   3042  1.1  christos 
   3043  1.1  christos 	switch (client->state) {
   3044  1.1  christos 	      case S_INIT:
   3045  1.1  christos 		action = dhc6_init_action;
   3046  1.1  christos 		break;
   3047  1.1  christos 
   3048  1.1  christos 	      case S_SELECTING:
   3049  1.1  christos 	      case S_REBOOTING:
   3050  1.1  christos 		action = dhc6_select_action;
   3051  1.1  christos 		break;
   3052  1.1  christos 
   3053  1.1  christos 	      case S_RENEWING:
   3054  1.1  christos 	      case S_REBINDING:
   3055  1.1  christos 		action = dhc6_reply_action;
   3056  1.1  christos 		break;
   3057  1.1  christos 
   3058  1.1  christos 	      case S_STOPPED:
   3059  1.1  christos 		action = dhc6_stop_action;
   3060  1.1  christos 		break;
   3061  1.1  christos 
   3062  1.1  christos 	      case S_DECLINING:
   3063  1.1  christos 		action = dhc6_decline_action;
   3064  1.1  christos 		break;
   3065  1.1  christos 
   3066  1.1  christos 	      default:
   3067  1.1  christos 		log_fatal("Impossible condition at %s:%d.", MDL);
   3068  1.1  christos 		return ISC_R_CANCELED;
   3069  1.1  christos 	}
   3070  1.1  christos 
   3071  1.1  christos 	/* If there is a code to extract, and if there is some
   3072  1.1  christos 	 * action to take based on that code, then take the action
   3073  1.1  christos 	 * and do not continue.
   3074  1.1  christos 	 */
   3075  1.1  christos 	rval = dhc6_check_status(rval, new->options, "message", &code);
   3076  1.1  christos 	if (action(client, &rval, code))
   3077  1.1  christos 		return ISC_R_CANCELED;
   3078  1.1  christos 
   3079  1.1  christos 	for (ia = new->bindings ; ia != NULL ; ia = ia->next) {
   3080  1.1  christos 		switch (ia->ia_type) {
   3081  1.1  christos 			case D6O_IA_NA:
   3082  1.1  christos 				scope = "IA_NA";
   3083  1.1  christos 				got_na++;
   3084  1.1  christos 				break;
   3085  1.1  christos 			case D6O_IA_TA:
   3086  1.1  christos 				scope = "IA_TA";
   3087  1.1  christos 				got_ta++;
   3088  1.1  christos 				break;
   3089  1.1  christos 			case D6O_IA_PD:
   3090  1.1  christos 				scope = "IA_PD";
   3091  1.1  christos 				got_pd++;
   3092  1.1  christos 				break;
   3093  1.1  christos 			default:
   3094  1.1  christos 				log_error("dhc6_check_reply: no type.");
   3095  1.1  christos 				return DHCP_R_INVALIDARG;
   3096  1.1  christos 		}
   3097  1.1  christos 		rval = dhc6_check_status(rval, ia->options, scope, &code);
   3098  1.1  christos 
   3099  1.1  christos 		if (action(client, &rval, code))
   3100  1.1  christos 			return ISC_R_CANCELED;
   3101  1.1  christos 
   3102  1.1  christos 		if (ia->addrs != NULL) {
   3103  1.1  christos 			have_addrs = ISC_TRUE;
   3104  1.1  christos 		}
   3105  1.1  christos 	}
   3106  1.1  christos 
   3107  1.1  christos 	/* A Confirm->Reply is unsuitable for comparison to the old lease. */
   3108  1.1  christos 	if (client->state == S_REBOOTING)
   3109  1.1  christos 		return rval;
   3110  1.1  christos 
   3111  1.1  christos 	/* We expect the lease to have at least one address and if
   3112  1.1  christos 	 * required all of the requested IAs if not flag it as
   3113  1.1  christos 	 * NoAddrs and call the action routine to try again.
   3114  1.1  christos 	 *
   3115  1.1  christos 	 * Currently we don't completely handle TAs in all cases
   3116  1.1  christos 	 * so we don't check them for requires.  I've left the
   3117  1.1  christos 	 * check in and commented it as I eventually do want
   3118  1.1  christos 	 * us to check for TAs as well.  SAR
   3119  1.1  christos 	 */
   3120  1.1  christos 	if ((have_addrs != ISC_TRUE) ||
   3121  1.1  christos 	    ((require_all_ias != 0) &&
   3122  1.1  christos 	     ((got_na < wanted_ia_na) ||
   3123  1.1  christos 	      /*(got_ta < wanted_ia_ta) ||*/
   3124  1.1  christos 	      (got_pd < wanted_ia_pd)))) {
   3125  1.1  christos 		rval = ISC_R_FAILURE;
   3126  1.1  christos 		if (action(client, &rval, STATUS_NoAddrsAvail) == ISC_TRUE) {
   3127  1.1  christos 			return ISC_R_CANCELED;
   3128  1.1  christos 		}
   3129  1.1  christos 	}
   3130  1.1  christos 
   3131  1.1  christos 	/* No old lease in rapid-commit. */
   3132  1.1  christos 	if (client->state == S_INIT)
   3133  1.1  christos 		return rval;
   3134  1.1  christos 
   3135  1.1  christos 	switch (client->state) {
   3136  1.1  christos 	      case S_SELECTING:
   3137  1.1  christos 		/* Compare the new lease with the selected lease to make
   3138  1.1  christos 		 * sure there is no risky business.
   3139  1.1  christos 		 */
   3140  1.1  christos 		nscore = dhc6_score_lease(client, new);
   3141  1.1  christos 		sscore = dhc6_score_lease(client, client->selected_lease);
   3142  1.1  christos 		if ((client->advertised_leases != NULL) &&
   3143  1.1  christos 		    (nscore < (sscore / 2))) {
   3144  1.1  christos 			/* XXX: An attacker might reply this way to make
   3145  1.1  christos 			 * XXX: sure we latch onto their configuration.
   3146  1.1  christos 			 * XXX: We might want to ignore the packet and
   3147  1.1  christos 			 * XXX: schedule re-selection at the next timeout?
   3148  1.1  christos 			 */
   3149  1.1  christos 			log_error("PRC: BAIT AND SWITCH detected.  Score of "
   3150  1.1  christos 				  "supplied lease (%d) is substantially "
   3151  1.1  christos 				  "smaller than the advertised score (%d).  "
   3152  1.1  christos 				  "Trying other servers.",
   3153  1.1  christos 				  nscore, sscore);
   3154  1.1  christos 
   3155  1.1  christos 			dhc6_lease_destroy(&client->selected_lease, MDL);
   3156  1.1  christos 			client->selected_lease = NULL;
   3157  1.1  christos 
   3158  1.1  christos 			start_selecting6(client);
   3159  1.1  christos 
   3160  1.1  christos 			return ISC_R_CANCELED;
   3161  1.1  christos 		}
   3162  1.1  christos 		break;
   3163  1.1  christos 
   3164  1.1  christos 	      case S_RENEWING:
   3165  1.1  christos 	      case S_REBINDING:
   3166  1.1  christos 		/* This leaves one RFC3315 status check unimplemented:
   3167  1.1  christos 		 *
   3168  1.1  christos 		 * -  sends a Renew/Rebind if the IA is not in the Reply
   3169  1.1  christos 		 *    message
   3170  1.1  christos 		 *
   3171  1.1  christos 		 * We rely on the scheduling system to note that the IA has
   3172  1.1  christos 		 * not left Renewal/Rebinding/whatever since it still carries
   3173  1.1  christos 		 * old times from the last successful binding.  So this is
   3174  1.1  christos 		 * implemented actually, just not explicitly.
   3175  1.1  christos 		 */
   3176  1.1  christos 		break;
   3177  1.1  christos 
   3178  1.1  christos 	      case S_STOPPED:
   3179  1.1  christos 	      case S_DECLINING:
   3180  1.1  christos 		/* Nothing critical to do at this stage. */
   3181  1.1  christos 		break;
   3182  1.1  christos 
   3183  1.1  christos 	      default:
   3184  1.1  christos 		log_fatal("REALLY impossible condition at %s:%d.", MDL);
   3185  1.1  christos 		return ISC_R_CANCELED;
   3186  1.1  christos 	}
   3187  1.1  christos 
   3188  1.1  christos 	return rval;
   3189  1.1  christos }
   3190  1.1  christos 
   3191  1.1  christos /* While in init state, we only collect advertisements.  If there happens
   3192  1.1  christos  * to be an advertisement with a preference option of 255, that's an
   3193  1.1  christos  * automatic exit.  Otherwise, we collect advertisements until our timeout
   3194  1.1  christos  * expires (client->RT).
   3195  1.1  christos  */
   3196  1.1  christos void
   3197  1.1  christos init_handler(struct packet *packet, struct client_state *client)
   3198  1.1  christos {
   3199  1.1  christos 	struct dhc6_lease *lease;
   3200  1.1  christos 
   3201  1.1  christos 	/* In INIT state, we send solicits, we only expect to get
   3202  1.1  christos 	 * advertises (rapid commit has its own handler).
   3203  1.1  christos 	 */
   3204  1.1  christos 	if (packet->dhcpv6_msg_type != DHCPV6_ADVERTISE)
   3205  1.1  christos 		return;
   3206  1.1  christos 
   3207  1.1  christos 	/* RFC3315 section 15.3 validation (same as 15.10 since we
   3208  1.1  christos 	 * always include a client id).
   3209  1.1  christos 	 */
   3210  1.1  christos 	if (!valid_reply(packet, client)) {
   3211  1.1  christos 		log_error("Invalid Advertise - rejecting.");
   3212  1.1  christos 		return;
   3213  1.1  christos 	}
   3214  1.1  christos 
   3215  1.1  christos 	lease = dhc6_leaseify(packet, client);
   3216  1.1  christos 
   3217  1.1  christos 	/* Out of memory or corrupt packet condition...hopefully a temporary
   3218  1.1  christos 	 * problem.  Returning now makes us try to retransmit later.
   3219  1.1  christos 	 */
   3220  1.1  christos 	if (lease == NULL)
   3221  1.1  christos 		return;
   3222  1.1  christos 
   3223  1.1  christos 	if (dhc6_check_advertise(lease) != ISC_R_SUCCESS) {
   3224  1.1  christos 		log_debug("PRC: Lease failed to satisfy.");
   3225  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
   3226  1.1  christos 		return;
   3227  1.1  christos 	}
   3228  1.1  christos 
   3229  1.1  christos 	int lease_score =  dhc6_score_lease(client, lease);
   3230  1.1  christos #ifdef ENFORCE_DHCPV6_CLIENT_REQUIRE
   3231  1.1  christos 	if (lease_score == 0) {
   3232  1.1  christos 		log_debug("RCV:Advertised lease scored 0, toss it.");
   3233  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
   3234  1.1  christos 		return;
   3235  1.1  christos 	}
   3236  1.1  christos #endif
   3237  1.1  christos 
   3238  1.1  christos 	insert_lease(&client->advertised_leases, lease);
   3239  1.1  christos 
   3240  1.1  christos 	/* According to RFC3315 section 17.1.2, the client MUST wait for
   3241  1.1  christos 	 * the first RT before selecting a lease.  But on the 400th RT,
   3242  1.1  christos 	 * we dont' want to wait the full timeout if we finally get an
   3243  1.1  christos 	 * advertise.  We could probably wait a second, but ohwell,
   3244  1.1  christos 	 * RFC3315 doesn't say so.
   3245  1.1  christos 	 *
   3246  1.1  christos 	 * If the lease is highest possible preference, 255, RFC3315 claims
   3247  1.1  christos 	 * we should continue immediately even on the first RT.  We probably
   3248  1.1  christos 	 * should not if the advertise contains less than one IA and address.
   3249  1.1  christos 	 */
   3250  1.1  christos 	if ((client->txcount > 1) ||
   3251  1.1  christos 	    ((lease->pref == 255) && (lease_score > SCORE_MIN))) {
   3252  1.1  christos 		log_debug("RCV:  Advertisement immediately selected.");
   3253  1.1  christos 		cancel_timeout(do_init6, client);
   3254  1.1  christos 		start_selecting6(client);
   3255  1.1  christos 	} else
   3256  1.1  christos 		log_debug("RCV:  Advertisement recorded.");
   3257  1.1  christos }
   3258  1.1  christos 
   3259  1.1  christos /* info_request_handler() accepts a Reply to an Info-request.
   3260  1.1  christos  */
   3261  1.1  christos void
   3262  1.1  christos info_request_handler(struct packet *packet, struct client_state *client)
   3263  1.1  christos {
   3264  1.1  christos 	isc_result_t check_status;
   3265  1.1  christos 	unsigned code;
   3266  1.1  christos 
   3267  1.1  christos 	if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
   3268  1.1  christos 		return;
   3269  1.1  christos 
   3270  1.1  christos 	/* RFC3315 section 15.10 validation (same as 15.3 since we
   3271  1.1  christos 	 * always include a client id).
   3272  1.1  christos 	 */
   3273  1.1  christos 	if (!valid_reply(packet, client)) {
   3274  1.1  christos 		log_error("Invalid Reply - rejecting.");
   3275  1.1  christos 		return;
   3276  1.1  christos 	}
   3277  1.1  christos 
   3278  1.1  christos 	check_status = dhc6_check_status(ISC_R_SUCCESS, packet->options,
   3279  1.1  christos 					 "message", &code);
   3280  1.1  christos 
   3281  1.1  christos 	if (check_status != ISC_R_SUCCESS) {
   3282  1.1  christos 		/* If no action was taken, but there is an error, then
   3283  1.1  christos 		 * we wait for a retransmission.
   3284  1.1  christos 		 */
   3285  1.1  christos 		if (check_status != ISC_R_CANCELED)
   3286  1.1  christos 			return;
   3287  1.1  christos 	}
   3288  1.1  christos 
   3289  1.1  christos 	/* We're done retransmitting at this point. */
   3290  1.1  christos 	cancel_timeout(do_info_request6, client);
   3291  1.1  christos 
   3292  1.1  christos 	/* Action was taken, so now that we've torn down our scheduled
   3293  1.1  christos 	 * retransmissions, return.
   3294  1.1  christos 	 */
   3295  1.1  christos 	if (check_status == ISC_R_CANCELED)
   3296  1.1  christos 		return;
   3297  1.1  christos 
   3298  1.1  christos 	/* Cleanup if a previous attempt to go bound failed. */
   3299  1.1  christos 	if (client->old_lease != NULL) {
   3300  1.1  christos 		dhc6_lease_destroy(&client->old_lease, MDL);
   3301  1.1  christos 		client->old_lease = NULL;
   3302  1.1  christos 	}
   3303  1.1  christos 
   3304  1.1  christos 	/* Cache options in the active_lease. */
   3305  1.1  christos 	if (client->active_lease != NULL)
   3306  1.1  christos 		client->old_lease = client->active_lease;
   3307  1.1  christos 	client->active_lease = dmalloc(sizeof(struct dhc6_lease), MDL);
   3308  1.1  christos 	if (client->active_lease == NULL)
   3309  1.1  christos 		log_fatal("Out of memory for v6 lease structure.");
   3310  1.1  christos 	option_state_reference(&client->active_lease->options,
   3311  1.1  christos 			       packet->options, MDL);
   3312  1.1  christos 
   3313  1.1  christos 	execute_statements_in_scope(NULL, (struct packet *)packet, NULL, client,
   3314  1.1  christos 				    client->active_lease->options,
   3315  1.1  christos 				    client->active_lease->options,
   3316  1.1  christos 				    &global_scope, client->config->on_receipt,
   3317  1.1  christos 				    NULL, NULL);
   3318  1.1  christos 
   3319  1.1  christos 	start_informed(client);
   3320  1.1  christos }
   3321  1.1  christos 
   3322  1.1  christos /* Specific version of init_handler() for rapid-commit.
   3323  1.1  christos  */
   3324  1.1  christos void
   3325  1.1  christos rapid_commit_handler(struct packet *packet, struct client_state *client)
   3326  1.1  christos {
   3327  1.1  christos 	struct dhc6_lease *lease;
   3328  1.1  christos 	isc_result_t check_status;
   3329  1.1  christos 
   3330  1.1  christos 	/* On ADVERTISE just fall back to the init_handler().
   3331  1.1  christos 	 */
   3332  1.1  christos 	if (packet->dhcpv6_msg_type == DHCPV6_ADVERTISE) {
   3333  1.1  christos 		init_handler(packet, client);
   3334  1.1  christos 		return;
   3335  1.1  christos 	} else if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
   3336  1.1  christos 		return;
   3337  1.1  christos 
   3338  1.1  christos 	/* RFC3315 section 15.10 validation (same as 15.3 since we
   3339  1.1  christos 	 * always include a client id).
   3340  1.1  christos 	 */
   3341  1.1  christos 	if (!valid_reply(packet, client)) {
   3342  1.1  christos 		log_error("Invalid Reply - rejecting.");
   3343  1.1  christos 		return;
   3344  1.1  christos 	}
   3345  1.1  christos 
   3346  1.1  christos 	/* A rapid-commit option MUST be here. */
   3347  1.1  christos 	if (lookup_option(&dhcpv6_universe, packet->options,
   3348  1.1  christos 			  D6O_RAPID_COMMIT) == 0) {
   3349  1.1  christos 		log_error("Reply without Rapid-Commit - rejecting.");
   3350  1.1  christos 		return;
   3351  1.1  christos 	}
   3352  1.1  christos 
   3353  1.1  christos 	lease = dhc6_leaseify(packet, client);
   3354  1.1  christos 
   3355  1.1  christos 	/* Out of memory or corrupt packet condition...hopefully a temporary
   3356  1.1  christos 	 * problem.  Returning now makes us try to retransmit later.
   3357  1.1  christos 	 */
   3358  1.1  christos 	if (lease == NULL)
   3359  1.1  christos 		return;
   3360  1.1  christos 
   3361  1.1  christos 	check_status = dhc6_check_reply(client, lease);
   3362  1.1  christos 	if (check_status != ISC_R_SUCCESS) {
   3363  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
   3364  1.1  christos 		return;
   3365  1.1  christos 	}
   3366  1.1  christos 
   3367  1.1  christos 	/* Jump to the selecting state. */
   3368  1.1  christos 	cancel_timeout(do_init6, client);
   3369  1.1  christos 	client->state = S_SELECTING;
   3370  1.1  christos 
   3371  1.1  christos 	/* Merge any bindings in the active lease (if there is one) into
   3372  1.1  christos 	 * the new active lease.
   3373  1.1  christos 	 */
   3374  1.1  christos 	dhc6_merge_lease(client->active_lease, lease);
   3375  1.1  christos 
   3376  1.1  christos 	/* Cleanup if a previous attempt to go bound failed. */
   3377  1.1  christos 	if (client->old_lease != NULL) {
   3378  1.1  christos 		dhc6_lease_destroy(&client->old_lease, MDL);
   3379  1.1  christos 		client->old_lease = NULL;
   3380  1.1  christos 	}
   3381  1.1  christos 
   3382  1.1  christos 	/* Make this lease active and BIND to it. */
   3383  1.1  christos 	if (client->active_lease != NULL)
   3384  1.1  christos 		client->old_lease = client->active_lease;
   3385  1.1  christos 	client->active_lease = lease;
   3386  1.1  christos 
   3387  1.1  christos 	/* We're done with the ADVERTISEd leases, if any. */
   3388  1.1  christos 	while(client->advertised_leases != NULL) {
   3389  1.1  christos 		lease = client->advertised_leases;
   3390  1.1  christos 		client->advertised_leases = lease->next;
   3391  1.1  christos 
   3392  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
   3393  1.1  christos 	}
   3394  1.1  christos 
   3395  1.1  christos 	start_bound(client);
   3396  1.1  christos }
   3397  1.1  christos 
   3398  1.1  christos /* Find the 'best' lease in the cache of advertised leases (usually).  From
   3399  1.1  christos  * RFC3315 Section 17.1.3:
   3400  1.1  christos  *
   3401  1.1  christos  *   Upon receipt of one or more valid Advertise messages, the client
   3402  1.1  christos  *   selects one or more Advertise messages based upon the following
   3403  1.1  christos  *   criteria.
   3404  1.1  christos  *
   3405  1.1  christos  *   -  Those Advertise messages with the highest server preference value
   3406  1.1  christos  *      are preferred over all other Advertise messages.
   3407  1.1  christos  *
   3408  1.1  christos  *   -  Within a group of Advertise messages with the same server
   3409  1.1  christos  *      preference value, a client MAY select those servers whose
   3410  1.1  christos  *      Advertise messages advertise information of interest to the
   3411  1.1  christos  *      client.  For example, the client may choose a server that returned
   3412  1.1  christos  *      an advertisement with configuration options of interest to the
   3413  1.1  christos  *      client.
   3414  1.1  christos  *
   3415  1.1  christos  *   -  The client MAY choose a less-preferred server if that server has a
   3416  1.1  christos  *      better set of advertised parameters, such as the available
   3417  1.1  christos  *      addresses advertised in IAs.
   3418  1.1  christos  *
   3419  1.1  christos  * Note that the first and third contradict each other.  The third should
   3420  1.1  christos  * probably be taken to mean that the client should prefer answers that
   3421  1.1  christos  * offer bindings, even if that violates the preference rule.
   3422  1.1  christos  *
   3423  1.1  christos  * The above also isn't deterministic where there are ties.  So the final
   3424  1.1  christos  * tiebreaker we add, if all other values are equal, is to compare the
   3425  1.1  christos  * server identifiers and to select the numerically lower one.
   3426  1.1  christos  */
   3427  1.1  christos static struct dhc6_lease *
   3428  1.1  christos dhc6_best_lease(struct client_state *client, struct dhc6_lease **head)
   3429  1.1  christos {
   3430  1.1  christos 	struct dhc6_lease **rpos, *rval, **candp, *cand;
   3431  1.1  christos 	int cscore, rscore;
   3432  1.1  christos 
   3433  1.1  christos 	if (head == NULL || *head == NULL)
   3434  1.1  christos 		return NULL;
   3435  1.1  christos 
   3436  1.1  christos 	rpos = head;
   3437  1.1  christos 	rval = *rpos;
   3438  1.1  christos 	rscore = dhc6_score_lease(client, rval);
   3439  1.1  christos 	candp = &rval->next;
   3440  1.1  christos 	cand = *candp;
   3441  1.1  christos 
   3442  1.1  christos 	log_debug("PRC: Considering best lease.");
   3443  1.1  christos 	log_debug("PRC:  X-- Initial candidate %s (s: %d, p: %u).",
   3444  1.1  christos 		  print_hex_1(rval->server_id.len,
   3445  1.1  christos 			      rval->server_id.data, 48),
   3446  1.1  christos 		  rscore, (unsigned)rval->pref);
   3447  1.1  christos 
   3448  1.1  christos 	for (; cand != NULL ; candp = &cand->next, cand = *candp) {
   3449  1.1  christos 		cscore = dhc6_score_lease(client, cand);
   3450  1.1  christos 
   3451  1.1  christos 		log_debug("PRC:  X-- Candidate %s (s: %d, p: %u).",
   3452  1.1  christos 			  print_hex_1(cand->server_id.len,
   3453  1.1  christos 				      cand->server_id.data, 48),
   3454  1.1  christos 			  cscore, (unsigned)cand->pref);
   3455  1.1  christos 
   3456  1.1  christos 		/* Above you'll find quoted RFC3315 Section 17.1.3.
   3457  1.1  christos 		 *
   3458  1.1  christos 		 * The third clause tells us to give up on leases that
   3459  1.1  christos 		 * have no bindings even if their preference is better.
   3460  1.1  christos 		 * So where our 'selected' lease's score is less than
   3461  1.1  christos 		 * SCORE_MIN (1 ia + 1 addr), choose any candidate >= SCORE_MIN.
   3462  1.1  christos 		 *
   3463  1.1  christos 		 * The first clause tells us to make preference the primary
   3464  1.1  christos 		 * deciding factor.  So if it's lower, reject, if it's
   3465  1.1  christos 		 * higher, select.
   3466  1.1  christos 		 *
   3467  1.1  christos 		 * The second clause tells us where the preference is
   3468  1.1  christos 		 * equal, we should use 'our judgement' of what we like
   3469  1.1  christos 		 * to see in an advertisement primarily.
   3470  1.1  christos 		 *
   3471  1.1  christos 		 * But there can still be a tie.  To make this deterministic,
   3472  1.1  christos 		 * we compare the server identifiers and select the binary
   3473  1.1  christos 		 * lowest.
   3474  1.1  christos 		 *
   3475  1.1  christos 		 * Since server id's are unique in this list, there is
   3476  1.1  christos 		 * no further tie to break.
   3477  1.1  christos 		 */
   3478  1.1  christos 		if ((rscore < SCORE_MIN) && (cscore >= SCORE_MIN)) {
   3479  1.1  christos 			log_debug("PRC:  | X-- Selected, has bindings.");
   3480  1.1  christos 		} else if (cand->pref < rval->pref) {
   3481  1.1  christos 			log_debug("PRC:  | X-- Rejected, lower preference.");
   3482  1.1  christos 			continue;
   3483  1.1  christos 		} else if (cand->pref > rval->pref) {
   3484  1.1  christos 			log_debug("PRC:  | X-- Selected, higher preference.");
   3485  1.1  christos 		} else if (cscore > rscore) {
   3486  1.1  christos 			log_debug("PRC:  | X-- Selected, equal preference, "
   3487  1.1  christos 				  "higher score.");
   3488  1.1  christos 		} else if (cscore < rscore) {
   3489  1.1  christos 			log_debug("PRC:  | X-- Rejected, equal preference, "
   3490  1.1  christos 				  "lower score.");
   3491  1.1  christos 			continue;
   3492  1.1  christos 		} else if ((cand->server_id.len < rval->server_id.len) ||
   3493  1.1  christos 			   ((cand->server_id.len == rval->server_id.len) &&
   3494  1.1  christos 			    (memcmp(cand->server_id.data,
   3495  1.1  christos 				    rval->server_id.data,
   3496  1.1  christos 				    cand->server_id.len) < 0))) {
   3497  1.1  christos 			log_debug("PRC:  | X-- Selected, equal preference, "
   3498  1.1  christos 				  "equal score, binary lesser server ID.");
   3499  1.1  christos 		} else {
   3500  1.1  christos 			log_debug("PRC:  | X-- Rejected, equal preference, "
   3501  1.1  christos 				  "equal score, binary greater server ID.");
   3502  1.1  christos 			continue;
   3503  1.1  christos 		}
   3504  1.1  christos 
   3505  1.1  christos 		rpos = candp;
   3506  1.1  christos 		rval = cand;
   3507  1.1  christos 		rscore = cscore;
   3508  1.1  christos 	}
   3509  1.1  christos 
   3510  1.1  christos 	/* Remove the selected lease from the chain. */
   3511  1.1  christos 	*rpos = rval->next;
   3512  1.1  christos 
   3513  1.1  christos 	return rval;
   3514  1.1  christos }
   3515  1.1  christos 
   3516  1.1  christos /* Select a lease out of the advertised leases and setup state to try and
   3517  1.1  christos  * acquire that lease.
   3518  1.1  christos  */
   3519  1.1  christos void
   3520  1.1  christos start_selecting6(struct client_state *client)
   3521  1.1  christos {
   3522  1.1  christos 	struct dhc6_lease *lease;
   3523  1.1  christos 
   3524  1.1  christos 	if (client->advertised_leases == NULL) {
   3525  1.1  christos 		log_error("Can not enter DHCPv6 SELECTING state with no "
   3526  1.1  christos 			  "leases to select from!");
   3527  1.1  christos 		return;
   3528  1.1  christos 	}
   3529  1.1  christos 
   3530  1.1  christos 	log_debug("PRC: Selecting best advertised lease.");
   3531  1.1  christos 	client->state = S_SELECTING;
   3532  1.1  christos 
   3533  1.1  christos 	lease = dhc6_best_lease(client, &client->advertised_leases);
   3534  1.1  christos 
   3535  1.1  christos 	if (lease == NULL)
   3536  1.1  christos 		log_fatal("Impossible error at %s:%d.", MDL);
   3537  1.1  christos 
   3538  1.1  christos 	client->selected_lease = lease;
   3539  1.1  christos 
   3540  1.1  christos 	/* Set timers per RFC3315 section 18.1.1. */
   3541  1.1  christos 	client->IRT = REQ_TIMEOUT * 100;
   3542  1.1  christos 	client->MRT = REQ_MAX_RT * 100;
   3543  1.1  christos 	client->MRC = REQ_MAX_RC;
   3544  1.1  christos 	client->MRD = 0;
   3545  1.1  christos 
   3546  1.1  christos 	dhc6_retrans_init(client);
   3547  1.1  christos 
   3548  1.1  christos 	client->v6_handler = reply_handler;
   3549  1.1  christos 
   3550  1.1  christos 	/* ("re")transmit the first packet. */
   3551  1.1  christos 	do_select6(client);
   3552  1.1  christos }
   3553  1.1  christos 
   3554  1.1  christos /* Transmit a Request to select a lease offered in Advertisements.  In
   3555  1.1  christos  * the event of failure, either move on to the next-best advertised lease,
   3556  1.1  christos  * or head back to INIT state if there are none.
   3557  1.1  christos  */
   3558  1.1  christos void
   3559  1.1  christos do_select6(void *input)
   3560  1.1  christos {
   3561  1.1  christos 	struct client_state *client;
   3562  1.1  christos 	struct dhc6_lease *lease;
   3563  1.1  christos 	struct data_string ds;
   3564  1.1  christos 	struct timeval tv;
   3565  1.1  christos 	int send_ret, added;
   3566  1.1  christos 
   3567  1.1  christos 	client = input;
   3568  1.1  christos 
   3569  1.1  christos 	/* 'lease' is fewer characters to type. */
   3570  1.1  christos 	lease = client->selected_lease;
   3571  1.1  christos 	if (lease == NULL || lease->bindings == NULL) {
   3572  1.1  christos 		log_error("Illegal to attempt selection without selecting "
   3573  1.1  christos 			  "a lease.");
   3574  1.1  christos 		return;
   3575  1.1  christos 	}
   3576  1.1  christos 
   3577  1.1  christos 	switch(check_timing6(client, DHCPV6_REQUEST, "Request", lease, &ds)) {
   3578  1.1  christos 	      case CHK_TIM_MRC_EXCEEDED:
   3579  1.1  christos 	      case CHK_TIM_MRD_EXCEEDED:
   3580  1.1  christos 		log_debug("PRC: Lease %s failed.",
   3581  1.1  christos 			  print_hex_1(lease->server_id.len,
   3582  1.1  christos 				      lease->server_id.data, 56));
   3583  1.1  christos 
   3584  1.1  christos 		/* Get rid of the lease that timed/counted out. */
   3585  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
   3586  1.1  christos 		client->selected_lease = NULL;
   3587  1.1  christos 
   3588  1.1  christos 		/* If there are more leases great.  If not, get more. */
   3589  1.1  christos 		if (client->advertised_leases != NULL)
   3590  1.1  christos 			start_selecting6(client);
   3591  1.1  christos 		else
   3592  1.1  christos 			start_init6(client);
   3593  1.1  christos 		return;
   3594  1.1  christos 	      case CHK_TIM_ALLOC_FAILURE:
   3595  1.1  christos 		return;
   3596  1.1  christos 	      case CHK_TIM_SUCCESS:
   3597  1.1  christos 		break;
   3598  1.1  christos 	}
   3599  1.1  christos 
   3600  1.1  christos 	/* Now make a packet that looks suspiciously like the one we
   3601  1.1  christos 	 * got from the server.  But different.
   3602  1.1  christos 	 *
   3603  1.1  christos 	 * XXX: I guess IAID is supposed to be something the client
   3604  1.1  christos 	 * indicates and uses as a key to its internal state.  It is
   3605  1.1  christos 	 * kind of odd to ask the server for IA's whose IAID the client
   3606  1.1  christos 	 * did not manufacture.  We first need a formal dhclient.conf
   3607  1.1  christos 	 * construct for the iaid, then we can delve into this matter
   3608  1.1  christos 	 * more properly.  In the time being, this will work.
   3609  1.1  christos 	 */
   3610  1.1  christos 
   3611  1.1  christos 	/* Fetch any configured 'sent' options (includes DUID) in wire format.
   3612  1.1  christos 	 */
   3613  1.1  christos 	dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
   3614  1.1  christos 				    NULL, client->sent_options, &global_scope,
   3615  1.1  christos 				    &dhcpv6_universe);
   3616  1.1  christos 
   3617  1.1  christos 	/* Now append any IA's, and within them any IAADDR/IAPREFIXs.
   3618  1.1  christos 	 * For each type of IA (na, ta, pd) we start with the ones for
   3619  1.1  christos 	 * which we already have addresses (dhc6_add_ia_xx) and then
   3620  1.1  christos 	 * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
   3621  1.1  christos 	 */
   3622  1.1  christos 	if (wanted_ia_na &&
   3623  1.1  christos 	    ((dhc6_add_ia_na(client, &ds, lease, DHCPV6_REQUEST,
   3624  1.1  christos 			     wanted_ia_na, &added) != ISC_R_SUCCESS) ||
   3625  1.1  christos 	     (dhc6_bare_ia_xx(client, &ds, wanted_ia_na - added,
   3626  1.1  christos 			      D6O_IA_NA) != ISC_R_SUCCESS))) {
   3627  1.1  christos 		data_string_forget(&ds, MDL);
   3628  1.1  christos 		return;
   3629  1.1  christos 	}
   3630  1.1  christos 	if (wanted_ia_ta &&
   3631  1.1  christos 	    ((dhc6_add_ia_ta(client, &ds, lease, DHCPV6_REQUEST,
   3632  1.1  christos 			     wanted_ia_ta, &added) != ISC_R_SUCCESS) ||
   3633  1.1  christos 	     (dhc6_bare_ia_xx(client, &ds, wanted_ia_ta - added,
   3634  1.1  christos 			      D6O_IA_TA) != ISC_R_SUCCESS))) {
   3635  1.1  christos 		data_string_forget(&ds, MDL);
   3636  1.1  christos 		return;
   3637  1.1  christos 	}
   3638  1.1  christos 	if (wanted_ia_pd &&
   3639  1.1  christos 	    ((dhc6_add_ia_pd(client, &ds, lease, DHCPV6_REQUEST,
   3640  1.1  christos 			     wanted_ia_pd, &added) != ISC_R_SUCCESS) ||
   3641  1.1  christos 	     (dhc6_bare_ia_xx(client, &ds, wanted_ia_pd - added,
   3642  1.1  christos 			      D6O_IA_PD) != ISC_R_SUCCESS))) {
   3643  1.1  christos 		data_string_forget(&ds, MDL);
   3644  1.1  christos 		return;
   3645  1.1  christos 	}
   3646  1.1  christos 
   3647  1.1  christos 	log_info("XMT: Request on %s, interval %ld0ms.",
   3648  1.1  christos 		 client->name ? client->name : client->interface->name,
   3649  1.1  christos 		 (long int)client->RT);
   3650  1.1  christos 
   3651  1.1  christos 	send_ret = send_packet6(client->interface,
   3652  1.1  christos 				ds.data, ds.len, &DHCPv6DestAddr);
   3653  1.1  christos 	if (send_ret != ds.len) {
   3654  1.1  christos 		log_error("dhc6: send_packet6() sent %d of %d bytes",
   3655  1.1  christos 			  send_ret, ds.len);
   3656  1.1  christos 	}
   3657  1.1  christos 
   3658  1.1  christos 	data_string_forget(&ds, MDL);
   3659  1.1  christos 
   3660  1.1  christos 	/* Wait RT */
   3661  1.1  christos 	tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
   3662  1.1  christos 	tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
   3663  1.1  christos 	if (tv.tv_usec >= 1000000) {
   3664  1.1  christos 		tv.tv_sec += 1;
   3665  1.1  christos 		tv.tv_usec -= 1000000;
   3666  1.1  christos 	}
   3667  1.1  christos 	add_timeout(&tv, do_select6, client, NULL, NULL);
   3668  1.1  christos 
   3669  1.1  christos 	dhc6_retrans_advance(client);
   3670  1.1  christos }
   3671  1.1  christos 
   3672  1.1  christos /*!
   3673  1.1  christos  *
   3674  1.1  christos  * \brief Count the number of IAs in the bindings
   3675  1.1  christos  *
   3676  1.1  christos  * \param lease  the lease to count
   3677  1.1  christos  * \param ia_type the type of the IA we wish to count
   3678  1.1  christos  *
   3679  1.1  christos  * \return The number of IAs of the specified type we found
   3680  1.1  christos  */
   3681  1.1  christos static int
   3682  1.1  christos dhc6_count_ia(struct dhc6_lease *lease, u_int16_t ia_type)
   3683  1.1  christos {
   3684  1.1  christos 	struct dhc6_ia *ia;
   3685  1.1  christos 	int i = 0;
   3686  1.1  christos 
   3687  1.1  christos 	for (ia = lease->bindings; ia != NULL; ia = ia->next) {
   3688  1.1  christos 		if (ia->ia_type == ia_type)
   3689  1.1  christos 			/* bump the counter for the correct types */
   3690  1.1  christos 			i++;
   3691  1.1  christos 	}
   3692  1.1  christos 
   3693  1.1  christos 	return (i);
   3694  1.1  christos }
   3695  1.1  christos 
   3696  1.1  christos /*!
   3697  1.1  christos  *
   3698  1.1  christos  * \brief Add IA_NA information from the lease to the packet
   3699  1.1  christos  * we are building.
   3700  1.1  christos  *
   3701  1.1  christos  * Walk through the lease and for each IA_NA in the lease
   3702  1.1  christos  * and for each address in the IA_NA append that information
   3703  1.1  christos  * onto the packet-so-far.  If wanted is 0 include all IA_NAs
   3704  1.1  christos  * in the lease if wanted is non-zero include only that many
   3705  1.1  christos  * IA_NAs (this may occur if sommebody restarts a client with
   3706  1.1  christos  * arugments for a smaller number of NAs than before).
   3707  1.1  christos  *
   3708  1.1  christos  * \param client = the state of the entire client
   3709  1.1  christos  * \param packet = the packet we are building and where we
   3710  1.1  christos  *                 shall append the IA_NAs we create
   3711  1.1  christos  * \param lease  = the current lease
   3712  1.1  christos  * \param message = the type of the packet
   3713  1.1  christos  * \param wanted  = the number of IA_NAs to include in the packet
   3714  1.1  christos  *                  0 means include all
   3715  1.1  christos  * \param added   = the number of IA_NAs that were added to the packet
   3716  1.1  christos  *
   3717  1.1  christos  * \return ISC_R_SUCCESS - all is well continue, any other return
   3718  1.1  christos  *                         indicates an error (most likely memory issues)
   3719  1.1  christos  *                         and the packet should be tossed.
   3720  1.1  christos  */
   3721  1.1  christos static isc_result_t
   3722  1.1  christos dhc6_add_ia_na(struct client_state *client, struct data_string *packet,
   3723  1.1  christos 	       struct dhc6_lease *lease, u_int8_t message,
   3724  1.1  christos 	       int wanted, int *added)
   3725  1.1  christos {
   3726  1.1  christos 	struct data_string iads;
   3727  1.1  christos 	struct data_string addrds;
   3728  1.1  christos 	struct dhc6_addr *addr;
   3729  1.1  christos 	struct dhc6_ia *ia;
   3730  1.1  christos 	isc_result_t rval = ISC_R_SUCCESS;
   3731  1.1  christos 	TIME t1, t2;
   3732  1.1  christos 	int i;
   3733  1.1  christos 
   3734  1.1  christos 	*added = 0;
   3735  1.1  christos 	memset(&iads, 0, sizeof(iads));
   3736  1.1  christos 	memset(&addrds, 0, sizeof(addrds));
   3737  1.1  christos 	for (ia = lease->bindings, i = 0;
   3738  1.1  christos 	     ia != NULL && rval == ISC_R_SUCCESS && (wanted == 0 || i < wanted);
   3739  1.1  christos 	     ia = ia->next) {
   3740  1.1  christos 		if (ia->ia_type != D6O_IA_NA)
   3741  1.1  christos 			continue;
   3742  1.1  christos 
   3743  1.1  christos 		/* Now that we know this is an NA bump the counter */
   3744  1.1  christos 		i++;
   3745  1.1  christos 
   3746  1.1  christos 		if (!buffer_allocate(&iads.buffer, 12, MDL)) {
   3747  1.1  christos 			log_error("Unable to allocate memory for IA_NA.");
   3748  1.1  christos 			rval = ISC_R_NOMEMORY;
   3749  1.1  christos 			break;
   3750  1.1  christos 		}
   3751  1.1  christos 
   3752  1.1  christos 		/* Copy the IAID into the packet buffer. */
   3753  1.1  christos 		memcpy(iads.buffer->data, ia->iaid, 4);
   3754  1.1  christos 		iads.data = iads.buffer->data;
   3755  1.1  christos 		iads.len = 12;
   3756  1.1  christos 
   3757  1.1  christos 		switch (message) {
   3758  1.1  christos 		      case DHCPV6_REQUEST:
   3759  1.1  christos 		      case DHCPV6_RENEW:
   3760  1.1  christos 		      case DHCPV6_REBIND:
   3761  1.1  christos 
   3762  1.1  christos 			t1 = client->config->requested_lease / 2;
   3763  1.1  christos 			t2 = t1 + (t1 / 2);
   3764  1.1  christos #if MAX_TIME > 0xffffffff
   3765  1.1  christos 			if (t1 > 0xffffffff)
   3766  1.1  christos 				t1 = 0xffffffff;
   3767  1.1  christos 			if (t2 > 0xffffffff)
   3768  1.1  christos 				t2 = 0xffffffff;
   3769  1.1  christos #endif
   3770  1.1  christos 			putULong(iads.buffer->data + 4, t1);
   3771  1.1  christos 			putULong(iads.buffer->data + 8, t2);
   3772  1.1  christos 
   3773  1.1  christos 			log_debug("XMT:  X-- IA_NA %s",
   3774  1.1  christos 				  print_hex_1(4, iads.data, 59));
   3775  1.1  christos 			log_debug("XMT:  | X-- Requested renew  +%u",
   3776  1.1  christos 				  (unsigned) t1);
   3777  1.1  christos 			log_debug("XMT:  | X-- Requested rebind +%u",
   3778  1.1  christos 				  (unsigned) t2);
   3779  1.1  christos 			break;
   3780  1.1  christos 
   3781  1.1  christos 		      case DHCPV6_CONFIRM:
   3782  1.1  christos 		      case DHCPV6_RELEASE:
   3783  1.1  christos 		      case DHCPV6_DECLINE:
   3784  1.1  christos 			/* Set t1 and t2 to zero; server will ignore them */
   3785  1.1  christos 			memset(iads.buffer->data + 4, 0, 8);
   3786  1.1  christos 			log_debug("XMT:  X-- IA_NA %s",
   3787  1.1  christos 				  print_hex_1(4, iads.buffer->data, 55));
   3788  1.1  christos 
   3789  1.1  christos 			break;
   3790  1.1  christos 
   3791  1.1  christos 		      default:
   3792  1.1  christos 			log_fatal("Impossible condition at %s:%d.", MDL);
   3793  1.1  christos 		}
   3794  1.1  christos 
   3795  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   3796  1.1  christos 			/*
   3797  1.1  christos 			 * Do not confirm expired addresses, do not request
   3798  1.1  christos 			 * expired addresses (but we keep them around for
   3799  1.1  christos 			 * solicit).
   3800  1.1  christos 			 */
   3801  1.1  christos 			if (addr->flags & DHC6_ADDR_EXPIRED)
   3802  1.1  christos 				continue;
   3803  1.1  christos 
   3804  1.1  christos 			if (addr->address.len != 16) {
   3805  1.1  christos 				log_error("Illegal IPv6 address length (%d), "
   3806  1.1  christos 					  "ignoring.  (%s:%d)",
   3807  1.1  christos 					  addr->address.len, MDL);
   3808  1.1  christos 				continue;
   3809  1.1  christos 			}
   3810  1.1  christos 
   3811  1.1  christos 			if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
   3812  1.1  christos 				log_error("Unable to allocate memory for "
   3813  1.1  christos 					  "IAADDR.");
   3814  1.1  christos 				rval = ISC_R_NOMEMORY;
   3815  1.1  christos 				break;
   3816  1.1  christos 			}
   3817  1.1  christos 
   3818  1.1  christos 			addrds.data = addrds.buffer->data;
   3819  1.1  christos 			addrds.len = 24;
   3820  1.1  christos 
   3821  1.1  christos 			/* Copy the address into the packet buffer. */
   3822  1.1  christos 			memcpy(addrds.buffer->data, addr->address.iabuf, 16);
   3823  1.1  christos 
   3824  1.1  christos 			/* Copy in additional information as appropriate */
   3825  1.1  christos 			switch (message) {
   3826  1.1  christos 			      case DHCPV6_REQUEST:
   3827  1.1  christos 			      case DHCPV6_RENEW:
   3828  1.1  christos 			      case DHCPV6_REBIND:
   3829  1.1  christos 				t1 = client->config->requested_lease;
   3830  1.1  christos 				t2 = t1 + 300;
   3831  1.1  christos 				putULong(addrds.buffer->data + 16, t1);
   3832  1.1  christos 				putULong(addrds.buffer->data + 20, t2);
   3833  1.1  christos 
   3834  1.1  christos 				log_debug("XMT:  | | X-- IAADDR %s",
   3835  1.1  christos 					  piaddr(addr->address));
   3836  1.1  christos 				log_debug("XMT:  | | | X-- Preferred "
   3837  1.1  christos 					  "lifetime +%u", (unsigned)t1);
   3838  1.1  christos 				log_debug("XMT:  | | | X-- Max lifetime +%u",
   3839  1.1  christos 					  (unsigned)t2);
   3840  1.1  christos 
   3841  1.1  christos 				break;
   3842  1.1  christos 
   3843  1.1  christos 			      case DHCPV6_CONFIRM:
   3844  1.1  christos 				/*
   3845  1.1  christos 				 * Set preferred and max life to zero,
   3846  1.1  christos 				 * per 17.1.3.
   3847  1.1  christos 				 */
   3848  1.1  christos 				memset(addrds.buffer->data + 16, 0, 8);
   3849  1.1  christos 				log_debug("XMT:  | X-- Confirm Address %s",
   3850  1.1  christos 					  piaddr(addr->address));
   3851  1.1  christos 				break;
   3852  1.1  christos 
   3853  1.1  christos 			      case DHCPV6_RELEASE:
   3854  1.1  christos 				/* Preferred and max life are irrelevant */
   3855  1.1  christos 				memset(addrds.buffer->data + 16, 0, 8);
   3856  1.1  christos 				log_debug("XMT:  | X-- Release Address %s",
   3857  1.1  christos 					  piaddr(addr->address));
   3858  1.1  christos 				break;
   3859  1.1  christos 
   3860  1.1  christos 			      case DHCPV6_DECLINE:
   3861  1.1  christos 				/* Preferred and max life are irrelevant */
   3862  1.1  christos 				memset(addrds.buffer->data + 16, 0, 8);
   3863  1.1  christos 				log_debug("XMT:  | X-- Decline Address %s",
   3864  1.1  christos 					  piaddr(addr->address));
   3865  1.1  christos 				break;
   3866  1.1  christos 
   3867  1.1  christos 			      default:
   3868  1.1  christos 				log_fatal("Impossible condition at %s:%d.",
   3869  1.1  christos 					  MDL);
   3870  1.1  christos 			}
   3871  1.1  christos 
   3872  1.1  christos 			append_option(&iads, &dhcpv6_universe, iaaddr_option,
   3873  1.1  christos 				      &addrds);
   3874  1.1  christos 			data_string_forget(&addrds, MDL);
   3875  1.1  christos 		}
   3876  1.1  christos 
   3877  1.1  christos 		/*
   3878  1.1  christos 		 * It doesn't make sense to make a request without an
   3879  1.1  christos 		 * address.
   3880  1.1  christos 		 */
   3881  1.1  christos 		if (ia->addrs == NULL) {
   3882  1.1  christos 			log_debug("!!!:  V IA_NA has no IAADDRs - removed.");
   3883  1.1  christos 			rval = ISC_R_FAILURE;
   3884  1.1  christos 		} else if (rval == ISC_R_SUCCESS) {
   3885  1.1  christos 			log_debug("XMT:  V IA_NA appended.");
   3886  1.1  christos 			append_option(packet, &dhcpv6_universe, ia_na_option,
   3887  1.1  christos 				      &iads);
   3888  1.1  christos 		}
   3889  1.1  christos 
   3890  1.1  christos 		data_string_forget(&iads, MDL);
   3891  1.1  christos 	}
   3892  1.1  christos 
   3893  1.1  christos 	if (rval == ISC_R_SUCCESS)
   3894  1.1  christos 		*added = i;
   3895  1.1  christos 
   3896  1.1  christos 	return (rval);
   3897  1.1  christos }
   3898  1.1  christos 
   3899  1.1  christos /*!
   3900  1.1  christos  *
   3901  1.1  christos  * \brief Add IA_TA information from the lease to the packet
   3902  1.1  christos  * we are building.
   3903  1.1  christos  *
   3904  1.1  christos  * Walk through the lease and for each IA_TA in the lease
   3905  1.1  christos  * and for each address in the IA_TA append that information
   3906  1.1  christos  * onto the packet-so-far.  If wanted is 0 include all IA_TAs
   3907  1.1  christos  * in the lease if wanted is non-zero include only that many
   3908  1.1  christos  * IA_TAs (this may occur if sommebody restarts a client with
   3909  1.1  christos  * arugments for a smaller number of TAs than before).
   3910  1.1  christos  *
   3911  1.1  christos  * \param client = the state of the entire client
   3912  1.1  christos  * \param packet = the packet we are building and where we
   3913  1.1  christos  *                 shall append the IA_TAs we create
   3914  1.1  christos  * \param lease  = the current lease
   3915  1.1  christos  * \param message = the type of the packet
   3916  1.1  christos  * \param wanted  = the number of IA_TAs to include in the packet
   3917  1.1  christos  *                  0 means include all
   3918  1.1  christos  * \param added   = the number of IA_TAs that were added to the packet
   3919  1.1  christos  *
   3920  1.1  christos  * \return ISC_R_SUCCESS - all is well continue, any other return
   3921  1.1  christos  *                         indicates an error (most likely memory issues)
   3922  1.1  christos  *                         and the packet should be tossed.
   3923  1.1  christos  */
   3924  1.1  christos static isc_result_t
   3925  1.1  christos dhc6_add_ia_ta(struct client_state *client, struct data_string *packet,
   3926  1.1  christos 	       struct dhc6_lease *lease, u_int8_t message,
   3927  1.1  christos 	       int wanted, int *added)
   3928  1.1  christos {
   3929  1.1  christos 	struct data_string iads;
   3930  1.1  christos 	struct data_string addrds;
   3931  1.1  christos 	struct dhc6_addr *addr;
   3932  1.1  christos 	struct dhc6_ia *ia;
   3933  1.1  christos 	isc_result_t rval = ISC_R_SUCCESS;
   3934  1.1  christos 	TIME t1, t2;
   3935  1.1  christos 	int i;
   3936  1.1  christos 
   3937  1.1  christos 	*added = 0;
   3938  1.1  christos 	memset(&iads, 0, sizeof(iads));
   3939  1.1  christos 	memset(&addrds, 0, sizeof(addrds));
   3940  1.1  christos 	for (ia = lease->bindings, i = 0;
   3941  1.1  christos 	     ia != NULL && rval == ISC_R_SUCCESS && (wanted == 0 || i < wanted);
   3942  1.1  christos 	     ia = ia->next) {
   3943  1.1  christos 		if (ia->ia_type != D6O_IA_TA)
   3944  1.1  christos 			continue;
   3945  1.1  christos 
   3946  1.1  christos 		/* Now that we know this is an TA bump the counter */
   3947  1.1  christos 		i++;
   3948  1.1  christos 
   3949  1.1  christos 		if (!buffer_allocate(&iads.buffer, 4, MDL)) {
   3950  1.1  christos 			log_error("Unable to allocate memory for IA_TA.");
   3951  1.1  christos 			rval = ISC_R_NOMEMORY;
   3952  1.1  christos 			break;
   3953  1.1  christos 		}
   3954  1.1  christos 
   3955  1.1  christos 		/* Copy the IAID into the packet buffer. */
   3956  1.1  christos 		memcpy(iads.buffer->data, ia->iaid, 4);
   3957  1.1  christos 		iads.data = iads.buffer->data;
   3958  1.1  christos 		iads.len = 4;
   3959  1.1  christos 
   3960  1.1  christos 		log_debug("XMT:  X-- IA_TA %s",
   3961  1.1  christos 			  print_hex_1(4, iads.buffer->data, 55));
   3962  1.1  christos 
   3963  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   3964  1.1  christos 			/*
   3965  1.1  christos 			 * Do not confirm expired addresses, do not request
   3966  1.1  christos 			 * expired addresses (but we keep them around for
   3967  1.1  christos 			 * solicit).
   3968  1.1  christos 			 */
   3969  1.1  christos 			if (addr->flags & DHC6_ADDR_EXPIRED)
   3970  1.1  christos 				continue;
   3971  1.1  christos 
   3972  1.1  christos 			if (addr->address.len != 16) {
   3973  1.1  christos 				log_error("Illegal IPv6 address length (%d), "
   3974  1.1  christos 					  "ignoring.  (%s:%d)",
   3975  1.1  christos 					  addr->address.len, MDL);
   3976  1.1  christos 				continue;
   3977  1.1  christos 			}
   3978  1.1  christos 
   3979  1.1  christos 			if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
   3980  1.1  christos 				log_error("Unable to allocate memory for "
   3981  1.1  christos 					  "IAADDR.");
   3982  1.1  christos 				rval = ISC_R_NOMEMORY;
   3983  1.1  christos 				break;
   3984  1.1  christos 			}
   3985  1.1  christos 
   3986  1.1  christos 			addrds.data = addrds.buffer->data;
   3987  1.1  christos 			addrds.len = 24;
   3988  1.1  christos 
   3989  1.1  christos 			/* Copy the address into the packet buffer. */
   3990  1.1  christos 			memcpy(addrds.buffer->data, addr->address.iabuf, 16);
   3991  1.1  christos 
   3992  1.1  christos 			/* Copy in additional information as appropriate */
   3993  1.1  christos 			switch (message) {
   3994  1.1  christos 			      case DHCPV6_REQUEST:
   3995  1.1  christos 			      case DHCPV6_RENEW:
   3996  1.1  christos 			      case DHCPV6_REBIND:
   3997  1.1  christos 				t1 = client->config->requested_lease;
   3998  1.1  christos 				t2 = t1 + 300;
   3999  1.1  christos 				putULong(addrds.buffer->data + 16, t1);
   4000  1.1  christos 				putULong(addrds.buffer->data + 20, t2);
   4001  1.1  christos 
   4002  1.1  christos 				log_debug("XMT:  | | X-- IAADDR %s",
   4003  1.1  christos 					  piaddr(addr->address));
   4004  1.1  christos 				log_debug("XMT:  | | | X-- Preferred "
   4005  1.1  christos 					  "lifetime +%u", (unsigned)t1);
   4006  1.1  christos 				log_debug("XMT:  | | | X-- Max lifetime +%u",
   4007  1.1  christos 					  (unsigned)t2);
   4008  1.1  christos 
   4009  1.1  christos 				break;
   4010  1.1  christos 
   4011  1.1  christos 			      case DHCPV6_CONFIRM:
   4012  1.1  christos 				/*
   4013  1.1  christos 				 * Set preferred and max life to zero,
   4014  1.1  christos 				 * per 17.1.3.
   4015  1.1  christos 				 */
   4016  1.1  christos 				memset(addrds.buffer->data + 16, 0, 8);
   4017  1.1  christos 				log_debug("XMT:  | X-- Confirm Address %s",
   4018  1.1  christos 					  piaddr(addr->address));
   4019  1.1  christos 				break;
   4020  1.1  christos 
   4021  1.1  christos 			      case DHCPV6_RELEASE:
   4022  1.1  christos 				/* Preferred and max life are irrelevant */
   4023  1.1  christos 				memset(addrds.buffer->data + 16, 0, 8);
   4024  1.1  christos 				log_debug("XMT:  | X-- Release Address %s",
   4025  1.1  christos 					  piaddr(addr->address));
   4026  1.1  christos 				break;
   4027  1.1  christos 
   4028  1.1  christos 			      default:
   4029  1.1  christos 				log_fatal("Impossible condition at %s:%d.",
   4030  1.1  christos 					  MDL);
   4031  1.1  christos 			}
   4032  1.1  christos 
   4033  1.1  christos 			append_option(&iads, &dhcpv6_universe, iaaddr_option,
   4034  1.1  christos 				      &addrds);
   4035  1.1  christos 			data_string_forget(&addrds, MDL);
   4036  1.1  christos 		}
   4037  1.1  christos 
   4038  1.1  christos 		/*
   4039  1.1  christos 		 * It doesn't make sense to make a request without an
   4040  1.1  christos 		 * address.
   4041  1.1  christos 		 */
   4042  1.1  christos 		if (ia->addrs == NULL) {
   4043  1.1  christos 			log_debug("!!!:  V IA_TA has no IAADDRs - removed.");
   4044  1.1  christos 			rval = ISC_R_FAILURE;
   4045  1.1  christos 		} else if (rval == ISC_R_SUCCESS) {
   4046  1.1  christos 			log_debug("XMT:  V IA_TA appended.");
   4047  1.1  christos 			append_option(packet, &dhcpv6_universe, ia_ta_option,
   4048  1.1  christos 				      &iads);
   4049  1.1  christos 		}
   4050  1.1  christos 
   4051  1.1  christos 		data_string_forget(&iads, MDL);
   4052  1.1  christos 	}
   4053  1.1  christos 
   4054  1.1  christos 	if (rval == ISC_R_SUCCESS)
   4055  1.1  christos 		*added = i;
   4056  1.1  christos 
   4057  1.1  christos 	return (rval);
   4058  1.1  christos }
   4059  1.1  christos 
   4060  1.1  christos /*!
   4061  1.1  christos  *
   4062  1.1  christos  * \brief Add IA_PD information from the lease to the packet
   4063  1.1  christos  * we are building.
   4064  1.1  christos  *
   4065  1.1  christos  * Walk through the lease and for each IA_PD in the lease
   4066  1.1  christos  * and for each address in the IA_PD append that information
   4067  1.1  christos  * onto the packet-so-far.  If wanted is 0 include all IA_PDs
   4068  1.1  christos  * in the lease if wanted is non-zero include only that many
   4069  1.1  christos  * IA_PDs (this may occur if sommebody restarts a client with
   4070  1.1  christos  * arugments for a smaller number of PDs than before).
   4071  1.1  christos  *
   4072  1.1  christos  * \param client = the state of the entire client
   4073  1.1  christos  * \param packet = the packet we are building and where we
   4074  1.1  christos  *                 shall append the IA_PDs we create
   4075  1.1  christos  * \param lease  = the current lease
   4076  1.1  christos  * \param message = the type of the packet
   4077  1.1  christos  * \param wanted  = the number of IA_PDs to include in the packet
   4078  1.1  christos  *                  0 means include all
   4079  1.1  christos  * \param added   = the number of IA_PDs that were added to the packet
   4080  1.1  christos  *
   4081  1.1  christos  * \return ISC_R_SUCCESS - all is well continue, any other return
   4082  1.1  christos  *                         indicates an error (most likely memory issues)
   4083  1.1  christos  *                         and the packet should be tossed.
   4084  1.1  christos  */
   4085  1.1  christos static isc_result_t
   4086  1.1  christos dhc6_add_ia_pd(struct client_state *client, struct data_string *packet,
   4087  1.1  christos 	       struct dhc6_lease *lease, u_int8_t message,
   4088  1.1  christos 	       int wanted, int *added)
   4089  1.1  christos {
   4090  1.1  christos 	struct data_string iads;
   4091  1.1  christos 	struct data_string prefds;
   4092  1.1  christos 	struct dhc6_addr *pref;
   4093  1.1  christos 	struct dhc6_ia *ia;
   4094  1.1  christos 	isc_result_t rval = ISC_R_SUCCESS;
   4095  1.1  christos 	TIME t1, t2;
   4096  1.1  christos 	int i;
   4097  1.1  christos 
   4098  1.1  christos 	*added = 0;
   4099  1.1  christos 	memset(&iads, 0, sizeof(iads));
   4100  1.1  christos 	memset(&prefds, 0, sizeof(prefds));
   4101  1.1  christos 	for (ia = lease->bindings, i = 0;
   4102  1.1  christos 	     ia != NULL && rval == ISC_R_SUCCESS && (wanted == 0 || i < wanted);
   4103  1.1  christos 	     ia = ia->next) {
   4104  1.1  christos 		if (ia->ia_type != D6O_IA_PD)
   4105  1.1  christos 			continue;
   4106  1.1  christos 
   4107  1.1  christos 		/* Now that we know this is an PD bump the counter */
   4108  1.1  christos 		i++;
   4109  1.1  christos 
   4110  1.1  christos 		if (!buffer_allocate(&iads.buffer, 12, MDL)) {
   4111  1.1  christos 			log_error("Unable to allocate memory for IA_PD.");
   4112  1.1  christos 			rval = ISC_R_NOMEMORY;
   4113  1.1  christos 			break;
   4114  1.1  christos 		}
   4115  1.1  christos 
   4116  1.1  christos 		/* Copy the IAID into the packet buffer. */
   4117  1.1  christos 		memcpy(iads.buffer->data, ia->iaid, 4);
   4118  1.1  christos 		iads.data = iads.buffer->data;
   4119  1.1  christos 		iads.len = 12;
   4120  1.1  christos 
   4121  1.1  christos 		switch (message) {
   4122  1.1  christos 		      case DHCPV6_REQUEST:
   4123  1.1  christos 		      case DHCPV6_RENEW:
   4124  1.1  christos 		      case DHCPV6_REBIND:
   4125  1.1  christos 
   4126  1.1  christos 			t1 = client->config->requested_lease / 2;
   4127  1.1  christos 			t2 = t1 + (t1 / 2);
   4128  1.1  christos #if MAX_TIME > 0xffffffff
   4129  1.1  christos 			if (t1 > 0xffffffff)
   4130  1.1  christos 				t1 = 0xffffffff;
   4131  1.1  christos 			if (t2 > 0xffffffff)
   4132  1.1  christos 				t2 = 0xffffffff;
   4133  1.1  christos #endif
   4134  1.1  christos 			putULong(iads.buffer->data + 4, t1);
   4135  1.1  christos 			putULong(iads.buffer->data + 8, t2);
   4136  1.1  christos 
   4137  1.1  christos 			log_debug("XMT:  X-- IA_PD %s",
   4138  1.1  christos 				  print_hex_1(4, iads.data, 59));
   4139  1.1  christos 			log_debug("XMT:  | X-- Requested renew  +%u",
   4140  1.1  christos 				  (unsigned) t1);
   4141  1.1  christos 			log_debug("XMT:  | X-- Requested rebind +%u",
   4142  1.1  christos 				  (unsigned) t2);
   4143  1.1  christos 			break;
   4144  1.1  christos 
   4145  1.1  christos 		      case DHCPV6_RELEASE:
   4146  1.1  christos 			/* Set t1 and t2 to zero; server will ignore them */
   4147  1.1  christos 			memset(iads.buffer->data + 4, 0, 8);
   4148  1.1  christos 			log_debug("XMT:  X-- IA_PD %s",
   4149  1.1  christos 				  print_hex_1(4, iads.buffer->data, 55));
   4150  1.1  christos 
   4151  1.1  christos 			break;
   4152  1.1  christos 
   4153  1.1  christos 		      default:
   4154  1.1  christos 			log_fatal("Impossible condition at %s:%d.", MDL);
   4155  1.1  christos 		}
   4156  1.1  christos 
   4157  1.1  christos 		for (pref = ia->addrs ; pref != NULL ; pref = pref->next) {
   4158  1.1  christos 			/*
   4159  1.1  christos 			 * Do not confirm expired prefixes, do not request
   4160  1.1  christos 			 * expired prefixes (but we keep them around for
   4161  1.1  christos 			 * solicit).
   4162  1.1  christos 			 */
   4163  1.1  christos 			if (pref->flags & DHC6_ADDR_EXPIRED)
   4164  1.1  christos 				continue;
   4165  1.1  christos 
   4166  1.1  christos 			if (pref->address.len != 16) {
   4167  1.1  christos 				log_error("Illegal IPv6 prefix "
   4168  1.1  christos 					  "ignoring.  (%s:%d)",
   4169  1.1  christos 					  MDL);
   4170  1.1  christos 				continue;
   4171  1.1  christos 			}
   4172  1.1  christos 
   4173  1.1  christos 			if (pref->plen == 0) {
   4174  1.1  christos 				log_info("Null IPv6 prefix, "
   4175  1.1  christos 					 "ignoring. (%s:%d)",
   4176  1.1  christos 					 MDL);
   4177  1.1  christos 			}
   4178  1.1  christos 
   4179  1.1  christos 			if (!buffer_allocate(&prefds.buffer, 25, MDL)) {
   4180  1.1  christos 				log_error("Unable to allocate memory for "
   4181  1.1  christos 					  "IAPREFIX.");
   4182  1.1  christos 				rval = ISC_R_NOMEMORY;
   4183  1.1  christos 				break;
   4184  1.1  christos 			}
   4185  1.1  christos 
   4186  1.1  christos 			prefds.data = prefds.buffer->data;
   4187  1.1  christos 			prefds.len = 25;
   4188  1.1  christos 
   4189  1.1  christos 			/* Copy the prefix into the packet buffer. */
   4190  1.1  christos 			putUChar(prefds.buffer->data + 8, pref->plen);
   4191  1.1  christos 			memcpy(prefds.buffer->data + 9,
   4192  1.1  christos 			       pref->address.iabuf,
   4193  1.1  christos 			       16);
   4194  1.1  christos 
   4195  1.1  christos 			/* Copy in additional information as appropriate */
   4196  1.1  christos 			switch (message) {
   4197  1.1  christos 			      case DHCPV6_REQUEST:
   4198  1.1  christos 			      case DHCPV6_RENEW:
   4199  1.1  christos 			      case DHCPV6_REBIND:
   4200  1.1  christos 				t1 = client->config->requested_lease;
   4201  1.1  christos 				t2 = t1 + 300;
   4202  1.1  christos 				putULong(prefds.buffer->data, t1);
   4203  1.1  christos 				putULong(prefds.buffer->data + 4, t2);
   4204  1.1  christos 
   4205  1.1  christos 				log_debug("XMT:  | | X-- IAPREFIX %s/%u",
   4206  1.1  christos 					  piaddr(pref->address),
   4207  1.1  christos 					  (unsigned) pref->plen);
   4208  1.1  christos 				log_debug("XMT:  | | | X-- Preferred "
   4209  1.1  christos 					  "lifetime +%u", (unsigned)t1);
   4210  1.1  christos 				log_debug("XMT:  | | | X-- Max lifetime +%u",
   4211  1.1  christos 					  (unsigned)t2);
   4212  1.1  christos 
   4213  1.1  christos 				break;
   4214  1.1  christos 
   4215  1.1  christos 			      case DHCPV6_RELEASE:
   4216  1.1  christos 				/* Preferred and max life are irrelevant */
   4217  1.1  christos 				memset(prefds.buffer->data, 0, 8);
   4218  1.1  christos 				log_debug("XMT:  | X-- Release Prefix %s/%u",
   4219  1.1  christos 					  piaddr(pref->address),
   4220  1.1  christos 					  (unsigned) pref->plen);
   4221  1.1  christos 				break;
   4222  1.1  christos 
   4223  1.1  christos 			      default:
   4224  1.1  christos 				log_fatal("Impossible condition at %s:%d.",
   4225  1.1  christos 					  MDL);
   4226  1.1  christos 			}
   4227  1.1  christos 
   4228  1.1  christos 			append_option(&iads, &dhcpv6_universe,
   4229  1.1  christos 				      iaprefix_option, &prefds);
   4230  1.1  christos 			data_string_forget(&prefds, MDL);
   4231  1.1  christos 		}
   4232  1.1  christos 
   4233  1.1  christos 		/*
   4234  1.1  christos 		 * It doesn't make sense to make a request without an
   4235  1.1  christos 		 * address.
   4236  1.1  christos 		 */
   4237  1.1  christos 		if (ia->addrs == NULL) {
   4238  1.1  christos 			log_debug("!!!:  V IA_PD has no IAPREFIXs - removed.");
   4239  1.1  christos 			rval = ISC_R_FAILURE;
   4240  1.1  christos 		} else if (rval == ISC_R_SUCCESS) {
   4241  1.1  christos 			log_debug("XMT:  V IA_PD appended.");
   4242  1.1  christos 			append_option(packet, &dhcpv6_universe,
   4243  1.1  christos 				      ia_pd_option, &iads);
   4244  1.1  christos 		}
   4245  1.1  christos 
   4246  1.1  christos 		data_string_forget(&iads, MDL);
   4247  1.1  christos 	}
   4248  1.1  christos 
   4249  1.1  christos 	if (rval == ISC_R_SUCCESS)
   4250  1.1  christos 		*added = i;
   4251  1.1  christos 
   4252  1.1  christos 	return (rval);
   4253  1.1  christos }
   4254  1.1  christos 
   4255  1.1  christos /* stopping_finished() checks if there is a remaining work to do.
   4256  1.1  christos  */
   4257  1.1  christos static isc_boolean_t
   4258  1.1  christos stopping_finished(void)
   4259  1.1  christos {
   4260  1.1  christos 	struct interface_info *ip;
   4261  1.1  christos 	struct client_state *client;
   4262  1.1  christos 
   4263  1.1  christos 	for (ip = interfaces; ip; ip = ip -> next) {
   4264  1.1  christos 		for (client = ip -> client; client; client = client -> next) {
   4265  1.1  christos 			if (client->state != S_STOPPED)
   4266  1.1  christos 				return ISC_FALSE;
   4267  1.1  christos 			if (client->active_lease != NULL)
   4268  1.1  christos 				return ISC_FALSE;
   4269  1.1  christos 		}
   4270  1.1  christos 	}
   4271  1.1  christos 	return ISC_TRUE;
   4272  1.1  christos }
   4273  1.1  christos 
   4274  1.1  christos /* reply_handler() accepts a Reply while we're attempting Select or Renew or
   4275  1.1  christos  * Rebind.  Basically any Reply packet.
   4276  1.1  christos  */
   4277  1.1  christos void
   4278  1.1  christos reply_handler(struct packet *packet, struct client_state *client)
   4279  1.1  christos {
   4280  1.1  christos 	struct dhc6_lease *lease;
   4281  1.1  christos 	isc_result_t check_status;
   4282  1.1  christos 
   4283  1.1  christos 	if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
   4284  1.1  christos 		return;
   4285  1.1  christos 
   4286  1.1  christos 	/* RFC3315 section 15.10 validation (same as 15.3 since we
   4287  1.1  christos 	 * always include a client id).
   4288  1.1  christos 	 */
   4289  1.1  christos 	if (!valid_reply(packet, client)) {
   4290  1.1  christos 		log_error("Invalid Reply - rejecting.");
   4291  1.1  christos 		return;
   4292  1.1  christos 	}
   4293  1.1  christos 
   4294  1.1  christos 	lease = dhc6_leaseify(packet, client);
   4295  1.1  christos 
   4296  1.1  christos 	/* Out of memory or corrupt packet condition...hopefully a temporary
   4297  1.1  christos 	 * problem.  Returning now makes us try to retransmit later.
   4298  1.1  christos 	 */
   4299  1.1  christos 	if (lease == NULL)
   4300  1.1  christos 		return;
   4301  1.1  christos 
   4302  1.1  christos 	check_status = dhc6_check_reply(client, lease);
   4303  1.1  christos 	if (check_status != ISC_R_SUCCESS) {
   4304  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
   4305  1.1  christos 
   4306  1.1  christos 		/* If no action was taken, but there is an error, then
   4307  1.1  christos 		 * we wait for a retransmission.
   4308  1.1  christos 		 */
   4309  1.1  christos 		if (check_status != ISC_R_CANCELED)
   4310  1.1  christos 			return;
   4311  1.1  christos 	}
   4312  1.1  christos 
   4313  1.1  christos 	/* We're done retransmitting at this point. */
   4314  1.1  christos 	cancel_timeout(do_confirm6, client);
   4315  1.1  christos 	cancel_timeout(do_select6, client);
   4316  1.1  christos 	cancel_timeout(do_refresh6, client);
   4317  1.1  christos 	cancel_timeout(do_release6, client);
   4318  1.1  christos 	cancel_timeout(do_decline6, client);
   4319  1.1  christos 
   4320  1.1  christos 	/* If this is in response to a Release, clean up and return. */
   4321  1.1  christos 	if (client->state == S_STOPPED) {
   4322  1.1  christos 		if (client->active_lease != NULL) {
   4323  1.1  christos 			dhc6_lease_destroy(&client->active_lease, MDL);
   4324  1.1  christos 			client->active_lease = NULL;
   4325  1.1  christos 			/* We should never wait for nothing!? */
   4326  1.1  christos 			if (stopping_finished()) {
   4327  1.1  christos 				finish(0);
   4328  1.1  christos 			}
   4329  1.1  christos 		}
   4330  1.1  christos 
   4331  1.1  christos 		return;
   4332  1.1  christos 	}
   4333  1.1  christos 
   4334  1.1  christos 	if (client->state == S_DECLINING) {
   4335  1.1  christos 		/* Weed thru the lease and delete all declined addresses.
   4336  1.1  christos 		 * Toss the lease if there aren't any addresses left */
   4337  1.1  christos 		int live_cnt = drop_declined_addrs(client->active_lease);
   4338  1.1  christos 		if (live_cnt == 0) {
   4339  1.1  christos 			dhc6_lease_destroy(&client->active_lease, MDL);
   4340  1.1  christos 			client->active_lease = NULL;
   4341  1.1  christos 		}
   4342  1.1  christos 
   4343  1.1  christos 		/* Solicit with any live addresses we have so far, and
   4344  1.1  christos 		* add additional empty NA iasubopts for those we had
   4345  1.1  christos 		* to decline. */
   4346  1.1  christos 		start_init6(client);
   4347  1.1  christos 		return;
   4348  1.1  christos 	}
   4349  1.1  christos 
   4350  1.1  christos 	/* Action was taken, so now that we've torn down our scheduled
   4351  1.1  christos 	 * retransmissions, return.
   4352  1.1  christos 	 */
   4353  1.1  christos 	if (check_status == ISC_R_CANCELED)
   4354  1.1  christos 		return;
   4355  1.1  christos 
   4356  1.1  christos 	if (client->selected_lease != NULL) {
   4357  1.1  christos 		dhc6_lease_destroy(&client->selected_lease, MDL);
   4358  1.1  christos 		client->selected_lease = NULL;
   4359  1.1  christos 	}
   4360  1.1  christos 
   4361  1.1  christos 	/* If this is in response to a confirm, we use the lease we've
   4362  1.1  christos 	 * already got, not the reply we were sent.
   4363  1.1  christos 	 */
   4364  1.1  christos 	if (client->state == S_REBOOTING) {
   4365  1.1  christos 		if (client->active_lease == NULL)
   4366  1.1  christos 			log_fatal("Impossible condition at %s:%d.", MDL);
   4367  1.1  christos 
   4368  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
   4369  1.1  christos 		start_bound(client);
   4370  1.1  christos 		return;
   4371  1.1  christos 	}
   4372  1.1  christos 
   4373  1.1  christos 	/* Merge any bindings in the active lease (if there is one) into
   4374  1.1  christos 	 * the new active lease.
   4375  1.1  christos 	 */
   4376  1.1  christos 	dhc6_merge_lease(client->active_lease, lease);
   4377  1.1  christos 
   4378  1.1  christos 	/* Cleanup if a previous attempt to go bound failed. */
   4379  1.1  christos 	if (client->old_lease != NULL) {
   4380  1.1  christos 		dhc6_lease_destroy(&client->old_lease, MDL);
   4381  1.1  christos 		client->old_lease = NULL;
   4382  1.1  christos 	}
   4383  1.1  christos 
   4384  1.1  christos 	/* Make this lease active and BIND to it. */
   4385  1.1  christos 	if (client->active_lease != NULL)
   4386  1.1  christos 		client->old_lease = client->active_lease;
   4387  1.1  christos 	client->active_lease = lease;
   4388  1.1  christos 
   4389  1.1  christos 	/* We're done with the ADVERTISEd leases, if any. */
   4390  1.1  christos 	while(client->advertised_leases != NULL) {
   4391  1.1  christos 		lease = client->advertised_leases;
   4392  1.1  christos 		client->advertised_leases = lease->next;
   4393  1.1  christos 
   4394  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
   4395  1.1  christos 	}
   4396  1.1  christos 
   4397  1.1  christos 	start_bound(client);
   4398  1.1  christos }
   4399  1.1  christos 
   4400  1.1  christos /* DHCPv6 packets are a little sillier than they needed to be - the root
   4401  1.1  christos  * packet contains options, then IA's which contain options, then within
   4402  1.1  christos  * that IAADDR's which contain options.
   4403  1.1  christos  *
   4404  1.1  christos  * To sort this out at dhclient-script time (which fetches config parameters
   4405  1.1  christos  * in environment variables), start_bound() iterates over each IAADDR, and
   4406  1.1  christos  * calls this function to marshall an environment variable set that includes
   4407  1.1  christos  * the most-specific option values related to that IAADDR in particular.
   4408  1.1  christos  *
   4409  1.1  christos  * To achieve this, we load environment variables for the root options space,
   4410  1.1  christos  * then the IA, then the IAADDR.  Any duplicate option names will be
   4411  1.1  christos  * over-written by the later versions.
   4412  1.1  christos  */
   4413  1.1  christos static void
   4414  1.1  christos dhc6_marshall_values(const char *prefix, struct client_state *client,
   4415  1.1  christos 		     struct dhc6_lease *lease, struct dhc6_ia *ia,
   4416  1.1  christos 		     struct dhc6_addr *addr)
   4417  1.1  christos {
   4418  1.1  christos 	/* Option cache contents, in descending order of
   4419  1.1  christos 	 * scope.
   4420  1.1  christos 	 */
   4421  1.1  christos 	if ((lease != NULL) && (lease->options != NULL))
   4422  1.1  christos 		script_write_params6(client, prefix, lease->options);
   4423  1.1  christos 	if ((ia != NULL) && (ia->options != NULL))
   4424  1.1  christos 		script_write_params6(client, prefix, ia->options);
   4425  1.1  christos 	if ((addr != NULL) && (addr->options != NULL))
   4426  1.1  christos 		script_write_params6(client, prefix, addr->options);
   4427  1.1  christos 
   4428  1.1  christos 	/* addr fields. */
   4429  1.1  christos 	if (addr != NULL) {
   4430  1.1  christos 		if ((ia != NULL) && (ia->ia_type == D6O_IA_PD)) {
   4431  1.1  christos 			client_envadd(client, prefix,
   4432  1.1  christos 				      "ip6_prefix", "%s/%u",
   4433  1.1  christos 				      piaddr(addr->address),
   4434  1.1  christos 				      (unsigned) addr->plen);
   4435  1.1  christos 		} else {
   4436  1.1  christos 			client_envadd(client, prefix, "ip6_prefixlen",
   4437  1.1  christos 				      "%d", address_prefix_len);
   4438  1.1  christos 			client_envadd(client, prefix, "ip6_address",
   4439  1.1  christos 				      "%s", piaddr(addr->address));
   4440  1.1  christos 		}
   4441  1.1  christos 		if ((ia != NULL) && (ia->ia_type == D6O_IA_TA)) {
   4442  1.1  christos 			client_envadd(client, prefix,
   4443  1.1  christos 				      "ip6_type", "temporary");
   4444  1.1  christos 		}
   4445  1.1  christos 		client_envadd(client, prefix, "life_starts", "%d",
   4446  1.1  christos 			      (int)(addr->starts));
   4447  1.1  christos 		client_envadd(client, prefix, "preferred_life", "%u",
   4448  1.1  christos 			      addr->preferred_life);
   4449  1.1  christos 		client_envadd(client, prefix, "max_life", "%u",
   4450  1.1  christos 			      addr->max_life);
   4451  1.1  christos 	}
   4452  1.1  christos 
   4453  1.1  christos 	/* ia fields. */
   4454  1.1  christos 	if (ia != NULL) {
   4455  1.1  christos 		client_envadd(client, prefix, "iaid", "%s",
   4456  1.1  christos 			      print_hex_1(4, ia->iaid, 12));
   4457  1.1  christos 		client_envadd(client, prefix, "starts", "%d",
   4458  1.1  christos 			      (int)(ia->starts));
   4459  1.1  christos 		client_envadd(client, prefix, "renew", "%u", ia->renew);
   4460  1.1  christos 		client_envadd(client, prefix, "rebind", "%u", ia->rebind);
   4461  1.1  christos 	}
   4462  1.1  christos }
   4463  1.1  christos 
   4464  1.1  christos /* Look at where the client's active lease is sitting.  If it's looking to
   4465  1.1  christos  * time out on renew, rebind, depref, or expiration, do those things.
   4466  1.1  christos  */
   4467  1.1  christos static void
   4468  1.1  christos dhc6_check_times(struct client_state *client)
   4469  1.1  christos {
   4470  1.1  christos 	struct dhc6_lease *lease;
   4471  1.1  christos 	struct dhc6_ia *ia;
   4472  1.1  christos 	struct dhc6_addr *addr;
   4473  1.1  christos 	TIME renew=MAX_TIME, rebind=MAX_TIME, depref=MAX_TIME,
   4474  1.1  christos 	     lo_expire=MAX_TIME, hi_expire=0, max_ia_starts = 0, tmp;
   4475  1.1  christos 	int has_addrs = ISC_FALSE;
   4476  1.1  christos 	int has_preferred_addrs = ISC_FALSE;
   4477  1.1  christos 	struct timeval tv;
   4478  1.1  christos 
   4479  1.1  christos 	lease = client->active_lease;
   4480  1.1  christos 
   4481  1.1  christos 	/* Bit spammy.  We should probably keep record of scheduled
   4482  1.1  christos 	 * events instead.
   4483  1.1  christos 	 */
   4484  1.1  christos 	cancel_timeout(start_renew6, client);
   4485  1.1  christos 	cancel_timeout(start_rebind6, client);
   4486  1.1  christos 	cancel_timeout(do_depref, client);
   4487  1.1  christos 	cancel_timeout(do_expire, client);
   4488  1.1  christos 
   4489  1.1  christos 	for(ia = lease->bindings ; ia != NULL ; ia = ia->next) {
   4490  1.1  christos 		TIME this_ia_lo_expire, this_ia_hi_expire, use_expire;
   4491  1.1  christos 
   4492  1.1  christos 		this_ia_lo_expire = MAX_TIME;
   4493  1.1  christos 		this_ia_hi_expire = 0;
   4494  1.1  christos 
   4495  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   4496  1.1  christos 			if(!(addr->flags & DHC6_ADDR_DEPREFFED)) {
   4497  1.1  christos 				if (addr->preferred_life == 0xffffffff)
   4498  1.1  christos 					tmp = MAX_TIME;
   4499  1.1  christos 				else
   4500  1.1  christos 					tmp = addr->starts +
   4501  1.1  christos 					      addr->preferred_life;
   4502  1.1  christos 
   4503  1.1  christos 				if (tmp < depref)
   4504  1.1  christos 					depref = tmp;
   4505  1.1  christos 
   4506  1.1  christos 				if (!(addr->flags & DHC6_ADDR_EXPIRED)) {
   4507  1.1  christos 					has_preferred_addrs = ISC_TRUE;
   4508  1.1  christos 				}
   4509  1.1  christos 			}
   4510  1.1  christos 
   4511  1.1  christos 			if (!(addr->flags & DHC6_ADDR_EXPIRED)) {
   4512  1.1  christos 				/* Find EPOCH-relative expiration. */
   4513  1.1  christos 				if (addr->max_life == 0xffffffff)
   4514  1.1  christos 					tmp = MAX_TIME;
   4515  1.1  christos 				else
   4516  1.1  christos 					tmp = addr->starts + addr->max_life;
   4517  1.1  christos 
   4518  1.1  christos 				/* Make the times ia->starts relative. */
   4519  1.1  christos 				tmp -= ia->starts;
   4520  1.1  christos 
   4521  1.1  christos 				if (tmp > this_ia_hi_expire)
   4522  1.1  christos 					this_ia_hi_expire = tmp;
   4523  1.1  christos 				if (tmp < this_ia_lo_expire)
   4524  1.1  christos 					this_ia_lo_expire = tmp;
   4525  1.1  christos 
   4526  1.1  christos 				has_addrs = ISC_TRUE;
   4527  1.1  christos 			}
   4528  1.1  christos 		}
   4529  1.1  christos 
   4530  1.1  christos 		/* These times are ia->starts relative. */
   4531  1.1  christos 		if (this_ia_lo_expire <= (this_ia_hi_expire / 2))
   4532  1.1  christos 			use_expire = this_ia_hi_expire;
   4533  1.1  christos 		else
   4534  1.1  christos 			use_expire = this_ia_lo_expire;
   4535  1.1  christos 
   4536  1.1  christos 		/*
   4537  1.1  christos 		 * If the auto-selected expiration time is "infinite", or
   4538  1.1  christos 		 * zero, assert a reasonable default.
   4539  1.1  christos 		 */
   4540  1.1  christos 		if ((use_expire == MAX_TIME) || (use_expire <= 1))
   4541  1.1  christos 			use_expire = client->config->requested_lease / 2;
   4542  1.1  christos 		else
   4543  1.1  christos 			use_expire /= 2;
   4544  1.1  christos 
   4545  1.1  christos 		/* Don't renew/rebind temporary addresses. */
   4546  1.1  christos 		/* For NA and PD we find the most recent IA and the smallest
   4547  1.1  christos 		 * values for the renew and rebind then base the timer on
   4548  1.1  christos 		 * the sum of the them.
   4549  1.1  christos 		 * Normally all the IAs will have the same time as they
   4550  1.1  christos 		 * are requested and served as a group but in some cases the
   4551  1.1  christos 		 * client isn't asking for all of the IAs (for example
   4552  1.1  christos 		 * restarted with a different set of arguments) or the server
   4553  1.1  christos 		 * isn't updating the client on all of them (probably a
   4554  1.1  christos 		 * broken server).
   4555  1.1  christos 		 */
   4556  1.1  christos 		if (ia->ia_type != D6O_IA_TA) {
   4557  1.1  christos 			if (ia->starts > max_ia_starts)
   4558  1.1  christos 				max_ia_starts = ia->starts;
   4559  1.1  christos 
   4560  1.1  christos 			if (ia->renew == 0) {
   4561  1.1  christos 				tmp = use_expire;
   4562  1.1  christos 			} else if (ia->renew == 0xffffffff)
   4563  1.1  christos 				tmp = MAX_TIME;
   4564  1.1  christos 			else
   4565  1.1  christos 				tmp = ia->renew;
   4566  1.1  christos 
   4567  1.1  christos 			if (tmp < renew)
   4568  1.1  christos 				renew = tmp;
   4569  1.1  christos 
   4570  1.1  christos 			if (ia->rebind == 0) {
   4571  1.1  christos 				/* Set rebind to 3/4 expiration interval. */
   4572  1.1  christos 				tmp = use_expire + (use_expire / 2);
   4573  1.1  christos 			} else if (ia->rebind == 0xffffffff)
   4574  1.1  christos 				tmp = MAX_TIME;
   4575  1.1  christos 			else
   4576  1.1  christos 				tmp = ia->rebind;
   4577  1.1  christos 
   4578  1.1  christos 			if (tmp < rebind)
   4579  1.1  christos 				rebind = tmp;
   4580  1.1  christos 		}
   4581  1.1  christos 
   4582  1.1  christos 		/*
   4583  1.1  christos 		 * Return expiration ranges to EPOCH relative for event
   4584  1.1  christos 		 * scheduling (add_timeout()).
   4585  1.1  christos 		 */
   4586  1.1  christos 		this_ia_hi_expire += ia->starts;
   4587  1.1  christos 		this_ia_lo_expire += ia->starts;
   4588  1.1  christos 
   4589  1.1  christos 		if (this_ia_hi_expire > hi_expire)
   4590  1.1  christos 			hi_expire = this_ia_hi_expire;
   4591  1.1  christos 		if (this_ia_lo_expire < lo_expire)
   4592  1.1  christos 			lo_expire = this_ia_lo_expire;
   4593  1.1  christos 	}
   4594  1.1  christos 
   4595  1.1  christos 	/* If there are no addresses, give up, go to INIT.
   4596  1.1  christos 	 * Note that if an address is unexpired with a date in the past,
   4597  1.1  christos 	 * we're scheduling an expiration event to ocurr in the past.  We
   4598  1.1  christos 	 * could probably optimize this to expire now (but then there's
   4599  1.1  christos 	 * recursion).
   4600  1.1  christos 	 *
   4601  1.1  christos 	 * In the future, we may decide that we're done here, or to
   4602  1.1  christos 	 * schedule a future request (using 4-pkt info-request model).
   4603  1.1  christos 	 */
   4604  1.1  christos 	if (has_addrs == ISC_FALSE) {
   4605  1.1  christos 		dhc6_lease_destroy(&client->active_lease, MDL);
   4606  1.1  christos 		client->active_lease = NULL;
   4607  1.1  christos 
   4608  1.1  christos 		/* Go back to the beginning. */
   4609  1.1  christos 		start_init6(client);
   4610  1.1  christos 		return;
   4611  1.1  christos 	}
   4612  1.1  christos 
   4613  1.1  christos 	/* Second part of calculating the renew and rebind times.
   4614  1.1  christos 	 * We have the start time and the desired periods for renew
   4615  1.1  christos 	 * and rebind, just add them to get the desired end time.
   4616  1.1  christos 	 */
   4617  1.1  christos 	if (renew != MAX_TIME)
   4618  1.1  christos 		renew += max_ia_starts;
   4619  1.1  christos 	if (rebind != MAX_TIME)
   4620  1.1  christos 		rebind += max_ia_starts;
   4621  1.1  christos 
   4622  1.1  christos 	switch(client->state) {
   4623  1.1  christos 	      case S_BOUND:
   4624  1.1  christos 		/* We'd like to hit renewing, but if rebinding has already
   4625  1.1  christos 		 * passed (time warp), head straight there.
   4626  1.1  christos 		 */
   4627  1.1  christos 		if ((rebind > cur_time) && (renew < rebind)) {
   4628  1.1  christos 			log_debug("PRC: Renewal event scheduled in %d seconds, "
   4629  1.1  christos 				  "to run for %u seconds.",
   4630  1.1  christos 				  (int)(renew - cur_time),
   4631  1.1  christos 				  (unsigned)(rebind - renew));
   4632  1.1  christos 			client->next_MRD = rebind;
   4633  1.1  christos 			tv.tv_sec = renew;
   4634  1.1  christos 			tv.tv_usec = 0;
   4635  1.1  christos 			add_timeout(&tv, start_renew6, client, NULL, NULL);
   4636  1.1  christos 
   4637  1.1  christos 			break;
   4638  1.1  christos 		}
   4639  1.1  christos 		/* FALL THROUGH */
   4640  1.1  christos 	      case S_RENEWING:
   4641  1.1  christos 		/* While actively renewing, MRD is bounded by the time
   4642  1.1  christos 		 * we stop renewing and start rebinding.  This helps us
   4643  1.1  christos 		 * process the state change on time.
   4644  1.1  christos 		 */
   4645  1.1  christos 		client->MRD = rebind - cur_time;
   4646  1.1  christos 		if (rebind != MAX_TIME) {
   4647  1.1  christos 			log_debug("PRC: Rebind event scheduled in %d seconds, "
   4648  1.1  christos 				  "to run for %d seconds.",
   4649  1.1  christos 				  (int)(rebind - cur_time),
   4650  1.1  christos 				  (int)(hi_expire - rebind));
   4651  1.1  christos 			client->next_MRD = hi_expire;
   4652  1.1  christos 			tv.tv_sec = rebind;
   4653  1.1  christos 			tv.tv_usec = 0;
   4654  1.1  christos 			add_timeout(&tv, start_rebind6, client, NULL, NULL);
   4655  1.1  christos 		}
   4656  1.1  christos 		break;
   4657  1.1  christos 
   4658  1.1  christos 	      case S_REBINDING:
   4659  1.1  christos 		/* For now, we rebind up until the last lease expires.  In
   4660  1.1  christos 		 * the future, we might want to start SOLICITing when we've
   4661  1.1  christos 		 * depreffed an address.
   4662  1.1  christos 		 */
   4663  1.1  christos 		client->MRD = hi_expire - cur_time;
   4664  1.1  christos 		break;
   4665  1.1  christos 
   4666  1.1  christos 	      default:
   4667  1.1  christos 		if (has_preferred_addrs) {
   4668  1.1  christos 			log_fatal("Impossible condition, state %d at %s:%d.",
   4669  1.1  christos 				  client->state, MDL);
   4670  1.1  christos 		}
   4671  1.1  christos 	}
   4672  1.1  christos 
   4673  1.1  christos 	/* Separately, set a time at which we will depref and expire
   4674  1.1  christos 	 * leases.  This might happen with multiple addresses while we
   4675  1.1  christos 	 * keep trying to refresh.
   4676  1.1  christos 	 */
   4677  1.1  christos 	if (depref != MAX_TIME) {
   4678  1.1  christos 		log_debug("PRC: Depreference scheduled in %d seconds.",
   4679  1.1  christos 			  (int)(depref - cur_time));
   4680  1.1  christos 		tv.tv_sec = depref;
   4681  1.1  christos 		tv.tv_usec = 0;
   4682  1.1  christos 		add_timeout(&tv, do_depref, client, NULL, NULL);
   4683  1.1  christos 	}
   4684  1.1  christos 	if (lo_expire != MAX_TIME) {
   4685  1.1  christos 		log_debug("PRC: Expiration scheduled in %d seconds.",
   4686  1.1  christos 			  (int)(lo_expire - cur_time));
   4687  1.1  christos 		tv.tv_sec = lo_expire;
   4688  1.1  christos 		tv.tv_usec = 0;
   4689  1.1  christos 		add_timeout(&tv, do_expire, client, NULL, NULL);
   4690  1.1  christos 	}
   4691  1.1  christos }
   4692  1.1  christos 
   4693  1.1  christos /* In a given IA chain, find the IA with the same type and 'iaid'. */
   4694  1.1  christos static struct dhc6_ia *
   4695  1.1  christos find_ia(struct dhc6_ia *head, u_int16_t type, const char *id)
   4696  1.1  christos {
   4697  1.1  christos 	struct dhc6_ia *ia;
   4698  1.1  christos 
   4699  1.1  christos 	for (ia = head ; ia != NULL ; ia = ia->next) {
   4700  1.1  christos 		if (ia->ia_type != type)
   4701  1.1  christos 			continue;
   4702  1.1  christos 		if (memcmp(ia->iaid, id, 4) == 0)
   4703  1.1  christos 			return ia;
   4704  1.1  christos 	}
   4705  1.1  christos 
   4706  1.1  christos 	return NULL;
   4707  1.1  christos }
   4708  1.1  christos 
   4709  1.1  christos /* In a given address chain, find a matching address. */
   4710  1.1  christos static struct dhc6_addr *
   4711  1.1  christos find_addr(struct dhc6_addr *head, struct iaddr *address)
   4712  1.1  christos {
   4713  1.1  christos 	struct dhc6_addr *addr;
   4714  1.1  christos 
   4715  1.1  christos 	for (addr = head ; addr != NULL ; addr = addr->next) {
   4716  1.1  christos 		if ((addr->address.len == address->len) &&
   4717  1.1  christos 		    (memcmp(addr->address.iabuf, address->iabuf,
   4718  1.1  christos 			    address->len) == 0))
   4719  1.1  christos 			return addr;
   4720  1.1  christos 	}
   4721  1.1  christos 
   4722  1.1  christos 	return NULL;
   4723  1.1  christos }
   4724  1.1  christos 
   4725  1.1  christos /* In a given prefix chain, find a matching prefix. */
   4726  1.1  christos static struct dhc6_addr *
   4727  1.1  christos find_pref(struct dhc6_addr *head, struct iaddr *prefix, u_int8_t plen)
   4728  1.1  christos {
   4729  1.1  christos 	struct dhc6_addr *pref;
   4730  1.1  christos 
   4731  1.1  christos 	for (pref = head ; pref != NULL ; pref = pref->next) {
   4732  1.1  christos 		if ((pref->address.len == prefix->len) &&
   4733  1.1  christos 		    (pref->plen == plen) &&
   4734  1.1  christos 		    (memcmp(pref->address.iabuf, prefix->iabuf,
   4735  1.1  christos 			    prefix->len) == 0))
   4736  1.1  christos 			return pref;
   4737  1.1  christos 	}
   4738  1.1  christos 
   4739  1.1  christos 	return NULL;
   4740  1.1  christos }
   4741  1.1  christos 
   4742  1.1  christos /*
   4743  1.1  christos  *
   4744  1.1  christos  * \brief  Merge the bindings from the source lease into the destination
   4745  1.1  christos  * lease structure, where they are missing.
   4746  1.1  christos  *
   4747  1.1  christos  * This is used to merge any extra information we have in the current
   4748  1.1  christos  * (older, src) lease into the lease we have just received.  For example
   4749  1.1  christos  * the src lease might include a binding for an NA that is still usable
   4750  1.1  christos  * but that we didn't request or that the server is no longer serving.
   4751  1.1  christos  * We want to keep that information until we toss the binding (expire,
   4752  1.1  christos  * release) so we move it to the new lease.
   4753  1.1  christos  *
   4754  1.1  christos  * We have to copy the stateful objects rather than move them over,
   4755  1.1  christos  * because later code needs to be able to compare new versus old if
   4756  1.1  christos  * they contain any bindings.
   4757  1.1  christos  *
   4758  1.1  christos  * \param src The older lease to copy the objects from
   4759  1.1  christos  * \param dst The newer lease to copy the objects to
   4760  1.1  christos  */
   4761  1.1  christos static void
   4762  1.1  christos dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst)
   4763  1.1  christos {
   4764  1.1  christos 	struct dhc6_ia *sia, *dia, *tia, **eia;
   4765  1.1  christos 	struct dhc6_addr *saddr, *daddr, *taddr;
   4766  1.1  christos 	int changes = 0;
   4767  1.1  christos 
   4768  1.1  christos 	if ((dst == NULL) || (src == NULL))
   4769  1.1  christos 		return;
   4770  1.1  christos 
   4771  1.1  christos 	for (sia = src->bindings ; sia != NULL ; sia = sia->next) {
   4772  1.1  christos 		dia = find_ia(dst->bindings, sia->ia_type, (char *)sia->iaid);
   4773  1.1  christos 
   4774  1.1  christos 		if (dia == NULL) {
   4775  1.1  christos 			tia = dhc6_dup_ia(sia, MDL);
   4776  1.1  christos 
   4777  1.1  christos 			if (tia == NULL)
   4778  1.1  christos 				log_fatal("Out of memory merging lease - "
   4779  1.1  christos 					  "Unable to continue without losing "
   4780  1.1  christos 					  "state! (%s:%d)", MDL);
   4781  1.1  christos 
   4782  1.1  christos 			/* Put any bindings that aren't in the new lease at the
   4783  1.1  christos 			 * end of the list.  If the user or server reduces the
   4784  1.1  christos 			 * number of IAs the ones in use will be at the front
   4785  1.1  christos 			 * and will be used when building the next requests
   4786  1.1  christos 			 * We could be more efficient by finding the end
   4787  1.1  christos 			 * of the list once but we don't expect to do this
   4788  1.1  christos 			 * often.
   4789  1.1  christos 			 */
   4790  1.1  christos 			for (eia = &dst->bindings;
   4791  1.1  christos 			     *eia != NULL;
   4792  1.1  christos 			     eia = &(*eia)->next) {
   4793  1.1  christos 				; /* no work just find the end */
   4794  1.1  christos 			}
   4795  1.1  christos 			*eia = tia;
   4796  1.1  christos 			changes = 1;
   4797  1.1  christos 		} else {
   4798  1.1  christos 			for (saddr = sia->addrs ; saddr != NULL ;
   4799  1.1  christos 			     saddr = saddr->next) {
   4800  1.1  christos 				if (sia->ia_type != D6O_IA_PD)
   4801  1.1  christos 					daddr = find_addr(dia->addrs,
   4802  1.1  christos 							  &saddr->address);
   4803  1.1  christos 				else
   4804  1.1  christos 					daddr = find_pref(dia->addrs,
   4805  1.1  christos 							  &saddr->address,
   4806  1.1  christos 							  saddr->plen);
   4807  1.1  christos 
   4808  1.1  christos 				if (daddr == NULL) {
   4809  1.1  christos 					taddr = dhc6_dup_addr(saddr, MDL);
   4810  1.1  christos 
   4811  1.1  christos 					if (taddr == NULL)
   4812  1.1  christos 						log_fatal("Out of memory "
   4813  1.1  christos 							  "merging lease - "
   4814  1.1  christos 							  "Unable to continue "
   4815  1.1  christos 							  "without losing "
   4816  1.1  christos 							  "state! (%s:%d)",
   4817  1.1  christos 							  MDL);
   4818  1.1  christos 
   4819  1.1  christos 					/* XXX: consider sorting? */
   4820  1.1  christos 					taddr->next = dia->addrs;
   4821  1.1  christos 					dia->addrs = taddr;
   4822  1.1  christos 					changes = 1;
   4823  1.1  christos 				}
   4824  1.1  christos 			}
   4825  1.1  christos 		}
   4826  1.1  christos 	}
   4827  1.1  christos 
   4828  1.1  christos 	/* If we made changes, reset the score to 0 so it is recalculated. */
   4829  1.1  christos 	if (changes)
   4830  1.1  christos 		dst->score = 0;
   4831  1.1  christos }
   4832  1.1  christos 
   4833  1.1  christos /* We've either finished selecting or succeeded in Renew or Rebinding our
   4834  1.1  christos  * lease.  In all cases we got a Reply.  Give dhclient-script a tickle
   4835  1.1  christos  * to inform it about the new values, and then lay in wait for the next
   4836  1.1  christos  * event.
   4837  1.1  christos  */
   4838  1.1  christos static void
   4839  1.1  christos start_bound(struct client_state *client)
   4840  1.1  christos {
   4841  1.1  christos 	struct dhc6_ia *ia, *oldia;
   4842  1.1  christos 	struct dhc6_addr *addr, *oldaddr;
   4843  1.1  christos 	struct dhc6_lease *lease, *old;
   4844  1.1  christos 	const char *reason;
   4845  1.1  christos 	int decline_cnt = 0;
   4846  1.1  christos #if defined (NSUPDATE)
   4847  1.1  christos 	TIME dns_update_offset = 1;
   4848  1.1  christos #endif
   4849  1.1  christos 
   4850  1.1  christos 	lease = client->active_lease;
   4851  1.1  christos 	if (lease == NULL) {
   4852  1.1  christos 		log_error("Cannot enter bound state unless an active lease "
   4853  1.1  christos 			  "is selected.");
   4854  1.1  christos 		return;
   4855  1.1  christos 	}
   4856  1.1  christos 	lease->released = ISC_FALSE;
   4857  1.1  christos 	old = client->old_lease;
   4858  1.1  christos 
   4859  1.1  christos 	client->v6_handler = bound_handler;
   4860  1.1  christos 
   4861  1.1  christos 	switch (client->state) {
   4862  1.1  christos 	      case S_SELECTING:
   4863  1.1  christos 	      case S_REBOOTING: /* Pretend we got bound. */
   4864  1.1  christos 		reason = "BOUND6";
   4865  1.1  christos 		break;
   4866  1.1  christos 
   4867  1.1  christos 	      case S_RENEWING:
   4868  1.1  christos 		reason = "RENEW6";
   4869  1.1  christos 		break;
   4870  1.1  christos 
   4871  1.1  christos 	      case S_REBINDING:
   4872  1.1  christos 		reason = "REBIND6";
   4873  1.1  christos 		break;
   4874  1.1  christos 
   4875  1.1  christos 	      default:
   4876  1.1  christos 		log_fatal("Impossible condition at %s:%d.", MDL);
   4877  1.1  christos 		/* Silence compiler warnings. */
   4878  1.1  christos 		return;
   4879  1.1  christos 	}
   4880  1.1  christos 
   4881  1.1  christos 	log_debug("PRC: Bound to lease %s.",
   4882  1.1  christos 		  print_hex_1(client->active_lease->server_id.len,
   4883  1.1  christos 			      client->active_lease->server_id.data, 55));
   4884  1.1  christos 	client->state = S_BOUND;
   4885  1.1  christos 
   4886  1.1  christos 	write_client6_lease(client, lease, 0, 1);
   4887  1.1  christos 
   4888  1.1  christos 	oldia = NULL;
   4889  1.1  christos 	for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
   4890  1.1  christos 		if (old != NULL)
   4891  1.1  christos 			oldia = find_ia(old->bindings,
   4892  1.1  christos 					ia->ia_type,
   4893  1.1  christos 					(char *)ia->iaid);
   4894  1.1  christos 		else
   4895  1.1  christos 			oldia = NULL;
   4896  1.1  christos 
   4897  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   4898  1.1  christos 			/* Don't try to use the address if it's already expired */
   4899  1.1  christos 			if (addr->flags & DHC6_ADDR_EXPIRED)
   4900  1.1  christos 				continue;
   4901  1.1  christos 
   4902  1.1  christos 			if (oldia != NULL) {
   4903  1.1  christos 				if (ia->ia_type != D6O_IA_PD)
   4904  1.1  christos 					oldaddr = find_addr(oldia->addrs,
   4905  1.1  christos 							    &addr->address);
   4906  1.1  christos 				else
   4907  1.1  christos 					oldaddr = find_pref(oldia->addrs,
   4908  1.1  christos 							    &addr->address,
   4909  1.1  christos 							    addr->plen);
   4910  1.1  christos 			} else
   4911  1.1  christos 				oldaddr = NULL;
   4912  1.1  christos 
   4913  1.1  christos #if defined (NSUPDATE)
   4914  1.1  christos 			if ((oldaddr == NULL) && (ia->ia_type == D6O_IA_NA))
   4915  1.1  christos 				dhclient_schedule_updates(client,
   4916  1.1  christos 							  &addr->address,
   4917  1.1  christos 							  dns_update_offset++);
   4918  1.1  christos #endif
   4919  1.1  christos 
   4920  1.1  christos 			/* Shell out to setup the new binding. */
   4921  1.1  christos 			script_init(client, reason, NULL);
   4922  1.1  christos 
   4923  1.1  christos 			if (old != NULL)
   4924  1.1  christos 				dhc6_marshall_values("old_", client, old,
   4925  1.1  christos 						     oldia, oldaddr);
   4926  1.1  christos 			dhc6_marshall_values("new_", client, lease, ia, addr);
   4927  1.1  christos 			script_write_requested6(client);
   4928  1.1  christos 
   4929  1.1  christos 			/* When script returns 3, DAD failed */
   4930  1.1  christos 			if (script_go(client) == 3) {
   4931  1.1  christos 				if (ia->ia_type == D6O_IA_NA) {
   4932  1.1  christos 					addr->flags |= DHC6_ADDR_DECLINED;
   4933  1.1  christos 					log_debug ("Flag address declined:%s",
   4934  1.1  christos 						   piaddr(addr->address));
   4935  1.1  christos 					decline_cnt++;
   4936  1.1  christos 				}
   4937  1.1  christos 			}
   4938  1.1  christos 		}
   4939  1.1  christos 
   4940  1.1  christos 		/* If the client script DAD failed any addresses we need
   4941  1.1  christos 		* build and issue a DECLINE */
   4942  1.1  christos 		if (decline_cnt) {
   4943  1.1  christos 			start_decline6(client);
   4944  1.1  christos 			return;
   4945  1.1  christos 		}
   4946  1.1  christos 
   4947  1.1  christos 		/* XXX: maybe we should loop on the old values instead? */
   4948  1.1  christos 		if (ia->addrs == NULL) {
   4949  1.1  christos 			script_init(client, reason, NULL);
   4950  1.1  christos 
   4951  1.1  christos 			if (old != NULL)
   4952  1.1  christos 				dhc6_marshall_values("old_", client, old,
   4953  1.1  christos 						     oldia,
   4954  1.1  christos 						     oldia != NULL ?
   4955  1.1  christos 							 oldia->addrs : NULL);
   4956  1.1  christos 
   4957  1.1  christos 			dhc6_marshall_values("new_", client, lease, ia,
   4958  1.1  christos 					     NULL);
   4959  1.1  christos 			script_write_requested6(client);
   4960  1.1  christos 
   4961  1.1  christos 			script_go(client);
   4962  1.1  christos 		}
   4963  1.1  christos 	}
   4964  1.1  christos 
   4965  1.1  christos 	/* XXX: maybe we should loop on the old values instead? */
   4966  1.1  christos 	if (lease->bindings == NULL) {
   4967  1.1  christos 		script_init(client, reason, NULL);
   4968  1.1  christos 
   4969  1.1  christos 		if (old != NULL)
   4970  1.1  christos 			dhc6_marshall_values("old_", client, old,
   4971  1.1  christos 					     old->bindings,
   4972  1.1  christos 					     (old->bindings != NULL) ?
   4973  1.1  christos 						old->bindings->addrs : NULL);
   4974  1.1  christos 
   4975  1.1  christos 		dhc6_marshall_values("new_", client, lease, NULL, NULL);
   4976  1.1  christos 		script_write_requested6(client);
   4977  1.1  christos 
   4978  1.1  christos 		script_go(client);
   4979  1.1  christos 	}
   4980  1.1  christos 
   4981  1.1  christos #ifdef DHCP4o6
   4982  1.1  christos 	if (dhcpv4_over_dhcpv6)
   4983  1.1  christos 		dhcp4o6_start();
   4984  1.1  christos #endif
   4985  1.1  christos 
   4986  1.1  christos 	detach();
   4987  1.1  christos 
   4988  1.1  christos 	if (client->old_lease != NULL) {
   4989  1.1  christos 		dhc6_lease_destroy(&client->old_lease, MDL);
   4990  1.1  christos 		client->old_lease = NULL;
   4991  1.1  christos 	}
   4992  1.1  christos 
   4993  1.1  christos 	/* Schedule events. */
   4994  1.1  christos 	dhc6_check_times(client);
   4995  1.1  christos }
   4996  1.1  christos 
   4997  1.1  christos /* While bound, ignore packets.  In the future we'll want to answer
   4998  1.1  christos  * Reconfigure-Request messages and the like.
   4999  1.1  christos  */
   5000  1.1  christos void
   5001  1.1  christos bound_handler(struct packet *packet, struct client_state *client)
   5002  1.1  christos {
   5003  1.1  christos 	log_debug("RCV: Input packets are ignored once bound.");
   5004  1.1  christos }
   5005  1.1  christos 
   5006  1.1  christos /*
   5007  1.1  christos  * start_decline6() kicks off the decline process, transmitting
   5008  1.1  christos  * an decline packet and scheduling a retransmission event.
   5009  1.1  christos  */
   5010  1.1  christos void
   5011  1.1  christos start_decline6(struct client_state *client)
   5012  1.1  christos {
   5013  1.1  christos 	/* Cancel any pending transmissions */
   5014  1.1  christos 	cancel_timeout(do_confirm6, client);
   5015  1.1  christos 	cancel_timeout(do_select6, client);
   5016  1.1  christos 	cancel_timeout(do_refresh6, client);
   5017  1.1  christos 	cancel_timeout(do_release6, client);
   5018  1.1  christos 	cancel_timeout(do_decline6, client);
   5019  1.1  christos 	client->state = S_DECLINING;
   5020  1.1  christos 
   5021  1.1  christos 	if (client->active_lease == NULL)
   5022  1.1  christos 		return;
   5023  1.1  christos 
   5024  1.1  christos 	/* Set timers per RFC3315 section 18.1.7. */
   5025  1.1  christos 	client->IRT = DEC_TIMEOUT * 100;
   5026  1.1  christos 	client->MRT = 0;
   5027  1.1  christos 	client->MRC = DEC_MAX_RC;
   5028  1.1  christos 	client->MRD = 0;
   5029  1.1  christos 
   5030  1.1  christos 	dhc6_retrans_init(client);
   5031  1.1  christos 	client->v6_handler = reply_handler;
   5032  1.1  christos 
   5033  1.1  christos 	client->refresh_type = DHCPV6_DECLINE;
   5034  1.1  christos 	do_decline6(client);
   5035  1.1  christos }
   5036  1.1  christos 
   5037  1.1  christos /*
   5038  1.1  christos  * do_decline6() creates a Decline packet and transmits it.
   5039  1.1  christos  * The decline will contain an IA_NA with iasubopt(s) for
   5040  1.1  christos  * each IA_NA containing declined address(es) in the active
   5041  1.1  christos  * lease.
   5042  1.1  christos  */
   5043  1.1  christos static void
   5044  1.1  christos do_decline6(void *input)
   5045  1.1  christos {
   5046  1.1  christos 	struct client_state *client;
   5047  1.1  christos 	struct data_string ds;
   5048  1.1  christos 	int send_ret;
   5049  1.1  christos 	struct timeval elapsed, tv;
   5050  1.1  christos 
   5051  1.1  christos 	client = input;
   5052  1.1  christos 	if (client == NULL || client->active_lease == NULL) {
   5053  1.1  christos 		return;
   5054  1.1  christos 	}
   5055  1.1  christos 
   5056  1.1  christos 	if ((client->MRC != 0) && (client->txcount > client->MRC))  {
   5057  1.1  christos 		log_info("Max retransmission count exceeded.");
   5058  1.1  christos 		goto decline_done;
   5059  1.1  christos 	}
   5060  1.1  christos 
   5061  1.1  christos 	/*
   5062  1.1  christos 	 * Start_time starts at the first transmission.
   5063  1.1  christos 	 */
   5064  1.1  christos 	if (client->txcount == 0) {
   5065  1.1  christos 		client->start_time.tv_sec = cur_tv.tv_sec;
   5066  1.1  christos 		client->start_time.tv_usec = cur_tv.tv_usec;
   5067  1.1  christos 	}
   5068  1.1  christos 
   5069  1.1  christos 	/* elapsed = cur - start */
   5070  1.1  christos 	elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
   5071  1.1  christos 	elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
   5072  1.1  christos 	if (elapsed.tv_usec < 0) {
   5073  1.1  christos 		elapsed.tv_sec -= 1;
   5074  1.1  christos 		elapsed.tv_usec += 1000000;
   5075  1.1  christos 	}
   5076  1.1  christos 
   5077  1.1  christos 	memset(&ds, 0, sizeof(ds));
   5078  1.1  christos 	if (!buffer_allocate(&ds.buffer, 4, MDL)) {
   5079  1.1  christos 		log_error("Unable to allocate memory for Decline.");
   5080  1.1  christos 		goto decline_done;
   5081  1.1  christos 	}
   5082  1.1  christos 
   5083  1.1  christos 	ds.data = ds.buffer->data;
   5084  1.1  christos 	ds.len = 4;
   5085  1.1  christos 	ds.buffer->data[0] = DHCPV6_DECLINE;
   5086  1.1  christos 	memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
   5087  1.1  christos 
   5088  1.1  christos 	/* Form an elapsed option. */
   5089  1.1  christos 	/* Maximum value is 65535 1/100s coded as 0xffff. */
   5090  1.1  christos 	if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
   5091  1.1  christos 	    ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
   5092  1.1  christos 		client->elapsed = 0xffff;
   5093  1.1  christos 	} else {
   5094  1.1  christos 		client->elapsed = elapsed.tv_sec * 100;
   5095  1.1  christos 		client->elapsed += elapsed.tv_usec / 10000;
   5096  1.1  christos 	}
   5097  1.1  christos 
   5098  1.1  christos 	client->elapsed = htons(client->elapsed);
   5099  1.1  christos 
   5100  1.1  christos 	log_debug("XMT: Forming Decline.");
   5101  1.1  christos 	make_client6_options(client, &client->sent_options,
   5102  1.1  christos 			     client->active_lease, DHCPV6_DECLINE);
   5103  1.1  christos 	dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
   5104  1.1  christos 				    client->sent_options, &global_scope,
   5105  1.1  christos 				    &dhcpv6_universe);
   5106  1.1  christos 
   5107  1.1  christos 	/* Append IA_NA's. */
   5108  1.1  christos 	if (dhc6_add_ia_na_decline(client, &ds, client->active_lease)
   5109  1.1  christos 	    != ISC_R_SUCCESS) {
   5110  1.1  christos 		data_string_forget(&ds, MDL);
   5111  1.1  christos 		goto decline_done;
   5112  1.1  christos 	}
   5113  1.1  christos 
   5114  1.1  christos 	/* Transmit and wait. */
   5115  1.1  christos 	log_info("XMT: Decline on %s, interval %ld0ms.",
   5116  1.1  christos 		 client->name ? client->name : client->interface->name,
   5117  1.1  christos 		 (long int)client->RT);
   5118  1.1  christos 
   5119  1.1  christos 	send_ret = send_packet6(client->interface, ds.data, ds.len,
   5120  1.1  christos 				&DHCPv6DestAddr);
   5121  1.1  christos 	if (send_ret != ds.len) {
   5122  1.1  christos 		log_error("dhc6: sendpacket6() sent %d of %d bytes",
   5123  1.1  christos 			  send_ret, ds.len);
   5124  1.1  christos 	}
   5125  1.1  christos 
   5126  1.1  christos 	data_string_forget(&ds, MDL);
   5127  1.1  christos 
   5128  1.1  christos 	/* Wait RT */
   5129  1.1  christos 	tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
   5130  1.1  christos 	tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
   5131  1.1  christos 	if (tv.tv_usec >= 1000000) {
   5132  1.1  christos 		tv.tv_sec += 1;
   5133  1.1  christos 		tv.tv_usec -= 1000000;
   5134  1.1  christos 	}
   5135  1.1  christos 	add_timeout(&tv, do_decline6, client, NULL, NULL);
   5136  1.1  christos 	dhc6_retrans_advance(client);
   5137  1.1  christos 	return;
   5138  1.1  christos 
   5139  1.1  christos decline_done:
   5140  1.1  christos 	/* We here because we've exhausted our retry limits or
   5141  1.1  christos 	 * something else has gone wrong with the decline process.
   5142  1.1  christos 	 * So let's just toss the existing lease and start over. */
   5143  1.1  christos 	dhc6_lease_destroy(&client->active_lease, MDL);
   5144  1.1  christos 	client->active_lease = NULL;
   5145  1.1  christos 
   5146  1.1  christos 	start_init6(client);
   5147  1.1  christos 	return;
   5148  1.1  christos }
   5149  1.1  christos 
   5150  1.1  christos /* start_renew6() gets us all ready to go to start transmitting Renew packets.
   5151  1.1  christos  * Note that client->next_MRD must be set before entering this function -
   5152  1.1  christos  * it must be set to the time at which the client should start Rebinding.
   5153  1.1  christos  */
   5154  1.1  christos void
   5155  1.1  christos start_renew6(void *input)
   5156  1.1  christos {
   5157  1.1  christos 	struct client_state *client;
   5158  1.1  christos 
   5159  1.1  christos 	client = (struct client_state *)input;
   5160  1.1  christos 
   5161  1.1  christos 	log_info("PRC: Renewing lease on %s.",
   5162  1.1  christos 		 client->name ? client->name : client->interface->name);
   5163  1.1  christos 	client->state = S_RENEWING;
   5164  1.1  christos 
   5165  1.1  christos 	client->v6_handler = reply_handler;
   5166  1.1  christos 
   5167  1.1  christos 	/* Times per RFC3315 section 18.1.3. */
   5168  1.1  christos 	client->IRT = REN_TIMEOUT * 100;
   5169  1.1  christos 	client->MRT = REN_MAX_RT * 100;
   5170  1.1  christos 	client->MRC = 0;
   5171  1.1  christos 	/* MRD is special in renew - we need to set it by checking timer
   5172  1.1  christos 	 * state.
   5173  1.1  christos 	 */
   5174  1.1  christos 	client->MRD = client->next_MRD - cur_time;
   5175  1.1  christos 
   5176  1.1  christos 	dhc6_retrans_init(client);
   5177  1.1  christos 
   5178  1.1  christos 	client->refresh_type = DHCPV6_RENEW;
   5179  1.1  christos 	do_refresh6(client);
   5180  1.1  christos }
   5181  1.1  christos 
   5182  1.1  christos /* do_refresh6() transmits one DHCPv6 packet, be it a Renew or Rebind, and
   5183  1.1  christos  * gives the retransmission state a bump for the next time.  Note that
   5184  1.1  christos  * client->refresh_type must be set before entering this function.
   5185  1.1  christos  */
   5186  1.1  christos void
   5187  1.1  christos do_refresh6(void *input)
   5188  1.1  christos {
   5189  1.1  christos 	struct option_cache *oc;
   5190  1.1  christos 	struct sockaddr_in6 unicast, *dest_addr = &DHCPv6DestAddr;
   5191  1.1  christos 	struct data_string ds;
   5192  1.1  christos 	struct client_state *client;
   5193  1.1  christos 	struct dhc6_lease *lease;
   5194  1.1  christos 	struct timeval elapsed, tv;
   5195  1.1  christos 	int send_ret, added;
   5196  1.1  christos 
   5197  1.1  christos 	client = (struct client_state *)input;
   5198  1.1  christos 	memset(&ds, 0, sizeof(ds));
   5199  1.1  christos 
   5200  1.1  christos 	lease = client->active_lease;
   5201  1.1  christos 	if (lease == NULL) {
   5202  1.1  christos 		log_error("Cannot renew without an active binding.");
   5203  1.1  christos 		return;
   5204  1.1  christos 	}
   5205  1.1  christos 
   5206  1.1  christos 	/* Ensure we're emitting a valid message type. */
   5207  1.1  christos 	switch (client->refresh_type) {
   5208  1.1  christos 	      case DHCPV6_RENEW:
   5209  1.1  christos 	      case DHCPV6_REBIND:
   5210  1.1  christos 		break;
   5211  1.1  christos 
   5212  1.1  christos 	      default:
   5213  1.1  christos 		log_fatal("Internal inconsistency (%d) at %s:%d.",
   5214  1.1  christos 			  client->refresh_type, MDL);
   5215  1.1  christos 	}
   5216  1.1  christos 
   5217  1.1  christos 	/*
   5218  1.1  christos 	 * Start_time starts at the first transmission.
   5219  1.1  christos 	 */
   5220  1.1  christos 	if (client->txcount == 0) {
   5221  1.1  christos 		client->start_time.tv_sec = cur_tv.tv_sec;
   5222  1.1  christos 		client->start_time.tv_usec = cur_tv.tv_usec;
   5223  1.1  christos 	}
   5224  1.1  christos 
   5225  1.1  christos 	/* elapsed = cur - start */
   5226  1.1  christos 	elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
   5227  1.1  christos 	elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
   5228  1.1  christos 	if (elapsed.tv_usec < 0) {
   5229  1.1  christos 		elapsed.tv_sec -= 1;
   5230  1.1  christos 		elapsed.tv_usec += 1000000;
   5231  1.1  christos 	}
   5232  1.1  christos 	if (((client->MRC != 0) && (client->txcount > client->MRC)) ||
   5233  1.1  christos 	    ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD))) {
   5234  1.1  christos 		/* We're done.  Move on to the next phase, if any. */
   5235  1.1  christos 		dhc6_check_times(client);
   5236  1.1  christos 		return;
   5237  1.1  christos 	}
   5238  1.1  christos 
   5239  1.1  christos 	/*
   5240  1.1  christos 	 * Check whether the server has sent a unicast option; if so, we can
   5241  1.1  christos 	 * use the address it specified for RENEWs.
   5242  1.1  christos 	 */
   5243  1.1  christos 	oc = lookup_option(&dhcpv6_universe, lease->options, D6O_UNICAST);
   5244  1.1  christos 	if (oc && evaluate_option_cache(&ds, NULL, NULL, NULL,
   5245  1.1  christos 					lease->options, NULL, &global_scope,
   5246  1.1  christos 					oc, MDL)) {
   5247  1.1  christos 		if (ds.len < 16) {
   5248  1.1  christos 			log_error("Invalid unicast option length %d.", ds.len);
   5249  1.1  christos 		} else {
   5250  1.1  christos 			memset(&unicast, 0, sizeof(DHCPv6DestAddr));
   5251  1.1  christos 			unicast.sin6_family = AF_INET6;
   5252  1.1  christos 			unicast.sin6_port = remote_port;
   5253  1.1  christos 			memcpy(&unicast.sin6_addr, ds.data, 16);
   5254  1.1  christos 			if (client->refresh_type == DHCPV6_RENEW) {
   5255  1.1  christos 				dest_addr = &unicast;
   5256  1.1  christos 			}
   5257  1.1  christos 		}
   5258  1.1  christos 
   5259  1.1  christos 		data_string_forget(&ds, MDL);
   5260  1.1  christos 	}
   5261  1.1  christos 
   5262  1.1  christos 	/* Commence forming a renew packet. */
   5263  1.1  christos 	memset(&ds, 0, sizeof(ds));
   5264  1.1  christos 	if (!buffer_allocate(&ds.buffer, 4, MDL)) {
   5265  1.1  christos 		log_error("Unable to allocate memory for packet.");
   5266  1.1  christos 		return;
   5267  1.1  christos 	}
   5268  1.1  christos 	ds.data = ds.buffer->data;
   5269  1.1  christos 	ds.len = 4;
   5270  1.1  christos 
   5271  1.1  christos 	ds.buffer->data[0] = client->refresh_type;
   5272  1.1  christos 	memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
   5273  1.1  christos 
   5274  1.1  christos 	/* Form an elapsed option. */
   5275  1.1  christos 	/* Maximum value is 65535 1/100s coded as 0xffff. */
   5276  1.1  christos 	if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
   5277  1.1  christos 	    ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
   5278  1.1  christos 		client->elapsed = 0xffff;
   5279  1.1  christos 	} else {
   5280  1.1  christos 		client->elapsed = elapsed.tv_sec * 100;
   5281  1.1  christos 		client->elapsed += elapsed.tv_usec / 10000;
   5282  1.1  christos 	}
   5283  1.1  christos 
   5284  1.1  christos 	if (client->elapsed == 0)
   5285  1.1  christos 		log_debug("XMT: Forming %s, 0 ms elapsed.",
   5286  1.1  christos 			  dhcpv6_type_names[client->refresh_type]);
   5287  1.1  christos 	else
   5288  1.1  christos 		log_debug("XMT: Forming %s, %u0 ms elapsed.",
   5289  1.1  christos 			  dhcpv6_type_names[client->refresh_type],
   5290  1.1  christos 			  (unsigned)client->elapsed);
   5291  1.1  christos 
   5292  1.1  christos 	client->elapsed = htons(client->elapsed);
   5293  1.1  christos 
   5294  1.1  christos 	make_client6_options(client, &client->sent_options, lease,
   5295  1.1  christos 			     client->refresh_type);
   5296  1.1  christos 
   5297  1.1  christos 	/* Put in any options from the sent cache. */
   5298  1.1  christos 	dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
   5299  1.1  christos 				    client->sent_options, &global_scope,
   5300  1.1  christos 				    &dhcpv6_universe);
   5301  1.1  christos 
   5302  1.1  christos 	/* Now append any IA's, and within them any IAADDR/IAPREFIXs.
   5303  1.1  christos 	 * For each type of IA (na, ta, pd) we start with the ones for
   5304  1.1  christos 	 * which we already have addresses (dhc6_add_ia_xx) and then
   5305  1.1  christos 	 * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
   5306  1.1  christos 	 */
   5307  1.1  christos 	if (wanted_ia_na &&
   5308  1.1  christos 	    ((dhc6_add_ia_na(client, &ds, lease, client->refresh_type,
   5309  1.1  christos 			     wanted_ia_na, &added) != ISC_R_SUCCESS) ||
   5310  1.1  christos 	     (dhc6_bare_ia_xx(client, &ds, wanted_ia_na - added,
   5311  1.1  christos 			      D6O_IA_NA) != ISC_R_SUCCESS))) {
   5312  1.1  christos 		data_string_forget(&ds, MDL);
   5313  1.1  christos 		return;
   5314  1.1  christos 	}
   5315  1.1  christos 	if (wanted_ia_pd &&
   5316  1.1  christos 	    ((dhc6_add_ia_pd(client, &ds, lease, client->refresh_type,
   5317  1.1  christos 			     wanted_ia_pd, &added) != ISC_R_SUCCESS) ||
   5318  1.1  christos 	     (dhc6_bare_ia_xx(client, &ds, wanted_ia_pd - added,
   5319  1.1  christos 			      D6O_IA_PD) != ISC_R_SUCCESS))) {
   5320  1.1  christos 		data_string_forget(&ds, MDL);
   5321  1.1  christos 		return;
   5322  1.1  christos 	}
   5323  1.1  christos 
   5324  1.1  christos 	log_info("XMT: %s on %s, interval %ld0ms.",
   5325  1.1  christos 		 dhcpv6_type_names[client->refresh_type],
   5326  1.1  christos 		 client->name ? client->name : client->interface->name,
   5327  1.1  christos 		 (long int)client->RT);
   5328  1.1  christos 
   5329  1.1  christos 	send_ret = send_packet6(client->interface, ds.data, ds.len, dest_addr);
   5330  1.1  christos 
   5331  1.1  christos 	if (send_ret != ds.len) {
   5332  1.1  christos 		log_error("dhc6: send_packet6() sent %d of %d bytes",
   5333  1.1  christos 			  send_ret, ds.len);
   5334  1.1  christos 	}
   5335  1.1  christos 
   5336  1.1  christos 	data_string_forget(&ds, MDL);
   5337  1.1  christos 
   5338  1.1  christos 	/* Wait RT */
   5339  1.1  christos 	tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
   5340  1.1  christos 	tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
   5341  1.1  christos 	if (tv.tv_usec >= 1000000) {
   5342  1.1  christos 		tv.tv_sec += 1;
   5343  1.1  christos 		tv.tv_usec -= 1000000;
   5344  1.1  christos 	}
   5345  1.1  christos 	add_timeout(&tv, do_refresh6, client, NULL, NULL);
   5346  1.1  christos 
   5347  1.1  christos 	dhc6_retrans_advance(client);
   5348  1.1  christos }
   5349  1.1  christos 
   5350  1.1  christos /* start_rebind6() gets us all set up to go and rebind a lease.  Note that
   5351  1.1  christos  * client->next_MRD must be set before entering this function.  In this case,
   5352  1.1  christos  * MRD must be set to the maximum time any address in the packet will
   5353  1.1  christos  * expire.
   5354  1.1  christos  */
   5355  1.1  christos void
   5356  1.1  christos start_rebind6(void *input)
   5357  1.1  christos {
   5358  1.1  christos 	struct client_state *client;
   5359  1.1  christos 
   5360  1.1  christos 	client = (struct client_state *)input;
   5361  1.1  christos 
   5362  1.1  christos 	log_info("PRC: Rebinding lease on %s.",
   5363  1.1  christos 		 client->name ? client->name : client->interface->name);
   5364  1.1  christos 	client->state = S_REBINDING;
   5365  1.1  christos 
   5366  1.1  christos 	client->v6_handler = reply_handler;
   5367  1.1  christos 
   5368  1.1  christos 	/* Times per RFC3315 section 18.1.4. */
   5369  1.1  christos 	client->IRT = REB_TIMEOUT * 100;
   5370  1.1  christos 	client->MRT = REB_MAX_RT * 100;
   5371  1.1  christos 	client->MRC = 0;
   5372  1.1  christos 	/* MRD is special in rebind - it's determined by the timer
   5373  1.1  christos 	 * state.
   5374  1.1  christos 	 */
   5375  1.1  christos 	client->MRD = client->next_MRD - cur_time;
   5376  1.1  christos 
   5377  1.1  christos 	dhc6_retrans_init(client);
   5378  1.1  christos 
   5379  1.1  christos 	client->refresh_type = DHCPV6_REBIND;
   5380  1.1  christos 	do_refresh6(client);
   5381  1.1  christos }
   5382  1.1  christos 
   5383  1.1  christos /* do_depref() runs through a given lease's addresses, for each that has
   5384  1.1  christos  * not yet been depreffed, shells out to the dhclient-script to inform it
   5385  1.1  christos  * of the status change.  The dhclient-script should then do...something...
   5386  1.1  christos  * to encourage applications to move off the address and onto one of the
   5387  1.1  christos  * remaining 'preferred' addresses.
   5388  1.1  christos  */
   5389  1.1  christos void
   5390  1.1  christos do_depref(void *input)
   5391  1.1  christos {
   5392  1.1  christos 	struct client_state *client;
   5393  1.1  christos 	struct dhc6_lease *lease;
   5394  1.1  christos 	struct dhc6_ia *ia;
   5395  1.1  christos 	struct dhc6_addr *addr;
   5396  1.1  christos 
   5397  1.1  christos 	client = (struct client_state *)input;
   5398  1.1  christos 
   5399  1.1  christos 	lease = client->active_lease;
   5400  1.1  christos 	if (lease == NULL)
   5401  1.1  christos 		return;
   5402  1.1  christos 
   5403  1.1  christos 	for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
   5404  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   5405  1.1  christos 			if (addr->flags & DHC6_ADDR_DEPREFFED)
   5406  1.1  christos 				continue;
   5407  1.1  christos 
   5408  1.1  christos 			if (addr->starts + addr->preferred_life <= cur_time) {
   5409  1.1  christos 				script_init(client, "DEPREF6", NULL);
   5410  1.1  christos 				dhc6_marshall_values("cur_", client, lease,
   5411  1.1  christos 						     ia, addr);
   5412  1.1  christos 				script_write_requested6(client);
   5413  1.1  christos 				script_go(client);
   5414  1.1  christos 
   5415  1.1  christos 				addr->flags |= DHC6_ADDR_DEPREFFED;
   5416  1.1  christos 
   5417  1.1  christos 				if (ia->ia_type != D6O_IA_PD)
   5418  1.1  christos 				    log_info("PRC: Address %s depreferred.",
   5419  1.1  christos 					     piaddr(addr->address));
   5420  1.1  christos 				else
   5421  1.1  christos 				    log_info("PRC: Prefix %s/%u depreferred.",
   5422  1.1  christos 					     piaddr(addr->address),
   5423  1.1  christos 					     (unsigned) addr->plen);
   5424  1.1  christos 
   5425  1.1  christos #if defined (NSUPDATE)
   5426  1.1  christos 				/* Remove DDNS bindings at depref time. */
   5427  1.1  christos 				if ((ia->ia_type == D6O_IA_NA) &&
   5428  1.1  christos 				    client->config->do_forward_update)
   5429  1.1  christos 					client_dns_remove(client,
   5430  1.1  christos 							  &addr->address);
   5431  1.1  christos #endif
   5432  1.1  christos 			}
   5433  1.1  christos 		}
   5434  1.1  christos 	}
   5435  1.1  christos 
   5436  1.1  christos 	dhc6_check_times(client);
   5437  1.1  christos }
   5438  1.1  christos 
   5439  1.1  christos /* do_expire() searches through all the addresses on a given lease, and
   5440  1.1  christos  * expires/removes any addresses that are no longer valid.
   5441  1.1  christos  */
   5442  1.1  christos void
   5443  1.1  christos do_expire(void *input)
   5444  1.1  christos {
   5445  1.1  christos 	struct client_state *client;
   5446  1.1  christos 	struct dhc6_lease *lease;
   5447  1.1  christos 	struct dhc6_ia *ia, **tia;
   5448  1.1  christos 	struct dhc6_addr *addr;
   5449  1.1  christos 	int has_addrs = ISC_FALSE;
   5450  1.1  christos 	int ia_has_addrs = ISC_FALSE;
   5451  1.1  christos 
   5452  1.1  christos 	client = (struct client_state *)input;
   5453  1.1  christos 
   5454  1.1  christos 	lease = client->active_lease;
   5455  1.1  christos 	if (lease == NULL)
   5456  1.1  christos 		return;
   5457  1.1  christos 
   5458  1.1  christos 	for (ia = lease->bindings, tia = &lease->bindings; ia != NULL ; ) {
   5459  1.1  christos 		ia_has_addrs = ISC_FALSE;
   5460  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   5461  1.1  christos 			if (addr->flags & DHC6_ADDR_EXPIRED)
   5462  1.1  christos 				continue;
   5463  1.1  christos 
   5464  1.1  christos 			if (addr->starts + addr->max_life <= cur_time) {
   5465  1.1  christos 				script_init(client, "EXPIRE6", NULL);
   5466  1.1  christos 				dhc6_marshall_values("old_", client, lease,
   5467  1.1  christos 						     ia, addr);
   5468  1.1  christos 				script_write_requested6(client);
   5469  1.1  christos 				script_go(client);
   5470  1.1  christos 
   5471  1.1  christos 				addr->flags |= DHC6_ADDR_EXPIRED;
   5472  1.1  christos 
   5473  1.1  christos 				if (ia->ia_type != D6O_IA_PD)
   5474  1.1  christos 				    log_info("PRC: Address %s expired.",
   5475  1.1  christos 					     piaddr(addr->address));
   5476  1.1  christos 				else
   5477  1.1  christos 				    log_info("PRC: Prefix %s/%u expired.",
   5478  1.1  christos 					     piaddr(addr->address),
   5479  1.1  christos 					     (unsigned) addr->plen);
   5480  1.1  christos 
   5481  1.1  christos #if defined (NSUPDATE)
   5482  1.1  christos 				/* We remove DNS records at depref time, but
   5483  1.1  christos 				 * it is possible that we might get here
   5484  1.1  christos 				 * without depreffing.
   5485  1.1  christos 				 */
   5486  1.1  christos 				if ((ia->ia_type == D6O_IA_NA) &&
   5487  1.1  christos 				    client->config->do_forward_update &&
   5488  1.1  christos 				    !(addr->flags & DHC6_ADDR_DEPREFFED))
   5489  1.1  christos 					client_dns_remove(client,
   5490  1.1  christos 							  &addr->address);
   5491  1.1  christos #endif
   5492  1.1  christos 
   5493  1.1  christos 				continue;
   5494  1.1  christos 			}
   5495  1.1  christos 
   5496  1.1  christos 			ia_has_addrs = ISC_TRUE;
   5497  1.1  christos 			has_addrs = ISC_TRUE;
   5498  1.1  christos 		}
   5499  1.1  christos 
   5500  1.1  christos 		/* Update to the next ia and git rid of this ia
   5501  1.1  christos 		 * if it doesn't have any leases.
   5502  1.1  christos 		 */
   5503  1.1  christos 		if (ia_has_addrs == ISC_TRUE) {
   5504  1.1  christos 			/* leases, just advance the list pointer */
   5505  1.1  christos 			tia = &(*tia)->next;
   5506  1.1  christos 		} else {
   5507  1.1  christos 			/* no leases, update the list pointer
   5508  1.1  christos 			 * and free the ia
   5509  1.1  christos 			 */
   5510  1.1  christos 			*tia = ia->next;
   5511  1.1  christos 			dhc6_ia_destroy(&ia, MDL);
   5512  1.1  christos 		}
   5513  1.1  christos 		/* lastly update the ia pointer to our new ia */
   5514  1.1  christos 		ia = *tia;
   5515  1.1  christos 	}
   5516  1.1  christos 
   5517  1.1  christos 	/* Clean up empty leases. */
   5518  1.1  christos 	if (has_addrs == ISC_FALSE) {
   5519  1.1  christos 		log_info("PRC: Bound lease is devoid of active addresses."
   5520  1.1  christos 			 "  Re-initializing.");
   5521  1.1  christos 
   5522  1.1  christos 		dhc6_lease_destroy(&lease, MDL);
   5523  1.1  christos 		client->active_lease = NULL;
   5524  1.1  christos 
   5525  1.1  christos 		start_init6(client);
   5526  1.1  christos 		return;
   5527  1.1  christos 	}
   5528  1.1  christos 
   5529  1.1  christos 	/* Schedule the next run through. */
   5530  1.1  christos 	dhc6_check_times(client);
   5531  1.1  christos }
   5532  1.1  christos 
   5533  1.1  christos /*
   5534  1.1  christos  * Run client script to unconfigure interface.
   5535  1.1  christos  * Called with reason STOP6 when dhclient -x is run, or with reason
   5536  1.1  christos  * RELEASE6 when server has replied to a Release message.
   5537  1.1  christos  * Stateless is a special case.
   5538  1.1  christos  */
   5539  1.1  christos void
   5540  1.1  christos unconfigure6(struct client_state *client, const char *reason)
   5541  1.1  christos {
   5542  1.1  christos 	struct dhc6_ia *ia;
   5543  1.1  christos 	struct dhc6_addr *addr;
   5544  1.1  christos 
   5545  1.1  christos 	if (stateless) {
   5546  1.1  christos 		script_init(client, reason, NULL);
   5547  1.1  christos 		if (client->active_lease != NULL)
   5548  1.1  christos 			script_write_params6(client, "old_",
   5549  1.1  christos 					     client->active_lease->options);
   5550  1.1  christos 		script_write_requested6(client);
   5551  1.1  christos 		script_go(client);
   5552  1.1  christos 		return;
   5553  1.1  christos 	}
   5554  1.1  christos 
   5555  1.1  christos 	if (client->active_lease == NULL)
   5556  1.1  christos 		return;
   5557  1.1  christos 
   5558  1.1  christos 	for (ia = client->active_lease->bindings ; ia != NULL ; ia = ia->next) {
   5559  1.1  christos 		if (ia->ia_type == D6O_IA_TA)
   5560  1.1  christos 			continue;
   5561  1.1  christos 
   5562  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   5563  1.1  christos 			script_init(client, reason, NULL);
   5564  1.1  christos 			dhc6_marshall_values("old_", client,
   5565  1.1  christos 					     client->active_lease, ia, addr);
   5566  1.1  christos 			script_write_requested6(client);
   5567  1.1  christos 			script_go(client);
   5568  1.1  christos 
   5569  1.1  christos #if defined (NSUPDATE)
   5570  1.1  christos 			if ((ia->ia_type == D6O_IA_NA) &&
   5571  1.1  christos 			    client->config->do_forward_update)
   5572  1.1  christos 				client_dns_remove(client, &addr->address);
   5573  1.1  christos #endif
   5574  1.1  christos 		}
   5575  1.1  christos 	}
   5576  1.1  christos }
   5577  1.1  christos 
   5578  1.2  christos static void
   5579  1.1  christos refresh_info_request6(void *input)
   5580  1.1  christos {
   5581  1.1  christos 	struct client_state *client;
   5582  1.1  christos 
   5583  1.1  christos 	client = (struct client_state *)input;
   5584  1.1  christos 	start_info_request6(client);
   5585  1.1  christos }
   5586  1.1  christos 
   5587  1.1  christos /* Timeout for Information-Request (using the IRT option).
   5588  1.1  christos  */
   5589  1.1  christos static void
   5590  1.1  christos dhc6_check_irt(struct client_state *client)
   5591  1.1  christos {
   5592  1.1  christos 	struct option **req;
   5593  1.1  christos 	struct option_cache *oc;
   5594  1.1  christos 	TIME expire = MAX_TIME;
   5595  1.1  christos 	struct timeval tv;
   5596  1.1  christos 	int i;
   5597  1.1  christos 	isc_boolean_t found = ISC_FALSE;
   5598  1.1  christos 
   5599  1.1  christos 	cancel_timeout(refresh_info_request6, client);
   5600  1.1  christos 
   5601  1.1  christos 	req = client->config->requested_options;
   5602  1.1  christos 	for (i = 0; req[i] != NULL; i++) {
   5603  1.1  christos 		if (req[i] == irt_option) {
   5604  1.1  christos 			found = ISC_TRUE;
   5605  1.1  christos 			break;
   5606  1.1  christos 		}
   5607  1.1  christos 	}
   5608  1.1  christos 	/* Simply return gives a endless loop waiting for nothing. */
   5609  1.1  christos 	if (!found) {
   5610  1.1  christos #ifdef DHCP4o6
   5611  1.1  christos 		if (!dhcpv4_over_dhcpv6)
   5612  1.1  christos #endif
   5613  1.1  christos 		finish(0);
   5614  1.1  christos 	}
   5615  1.1  christos 
   5616  1.1  christos 	oc = lookup_option(&dhcpv6_universe, client->active_lease->options,
   5617  1.1  christos 			   D6O_INFORMATION_REFRESH_TIME);
   5618  1.1  christos 	if (oc != NULL) {
   5619  1.1  christos 		struct data_string irt;
   5620  1.1  christos 
   5621  1.1  christos 		memset(&irt, 0, sizeof(irt));
   5622  1.1  christos 		if (!evaluate_option_cache(&irt, NULL, NULL, client,
   5623  1.1  christos 					   client->active_lease->options,
   5624  1.1  christos 					   NULL, &global_scope, oc, MDL) ||
   5625  1.1  christos 		    (irt.len < 4)) {
   5626  1.1  christos 			log_error("Can't evaluate IRT.");
   5627  1.1  christos 		} else {
   5628  1.1  christos 			expire = getULong(irt.data);
   5629  1.1  christos 			if (expire < IRT_MINIMUM)
   5630  1.1  christos 				expire = IRT_MINIMUM;
   5631  1.1  christos 			if (expire == 0xffffffff)
   5632  1.1  christos 				expire = MAX_TIME;
   5633  1.1  christos 		}
   5634  1.1  christos 		data_string_forget(&irt, MDL);
   5635  1.1  christos 	} else
   5636  1.1  christos 		expire = IRT_DEFAULT;
   5637  1.1  christos 
   5638  1.1  christos 	if (expire != MAX_TIME) {
   5639  1.1  christos 		log_debug("PRC: Refresh event scheduled in %u seconds.",
   5640  1.1  christos 			  (unsigned) expire);
   5641  1.1  christos 		tv.tv_sec = cur_time + expire;
   5642  1.1  christos 		tv.tv_usec = 0;
   5643  1.1  christos 		add_timeout(&tv, refresh_info_request6, client, NULL, NULL);
   5644  1.1  christos 	}
   5645  1.1  christos }
   5646  1.1  christos 
   5647  1.1  christos /* We got a Reply. Give dhclient-script a tickle to inform it about
   5648  1.1  christos  * the new values, and then lay in wait for the next event.
   5649  1.1  christos  */
   5650  1.1  christos static void
   5651  1.1  christos start_informed(struct client_state *client)
   5652  1.1  christos {
   5653  1.1  christos 	client->v6_handler = informed_handler;
   5654  1.1  christos 
   5655  1.1  christos 	log_debug("PRC: Done.");
   5656  1.1  christos 
   5657  1.1  christos 	client->state = S_BOUND;
   5658  1.1  christos 
   5659  1.1  christos 	script_init(client, "RENEW6", NULL);
   5660  1.1  christos 	if (client->old_lease != NULL)
   5661  1.1  christos 		script_write_params6(client, "old_",
   5662  1.1  christos 				     client->old_lease->options);
   5663  1.1  christos 	script_write_params6(client, "new_", client->active_lease->options);
   5664  1.1  christos 	script_write_requested6(client);
   5665  1.1  christos 	script_go(client);
   5666  1.1  christos 
   5667  1.1  christos #ifdef DHCP4o6
   5668  1.1  christos 	if (dhcpv4_over_dhcpv6)
   5669  1.1  christos 		dhcp4o6_start();
   5670  1.1  christos #endif
   5671  1.1  christos 
   5672  1.1  christos 	detach();
   5673  1.1  christos 
   5674  1.1  christos 	if (client->old_lease != NULL) {
   5675  1.1  christos 		dhc6_lease_destroy(&client->old_lease, MDL);
   5676  1.1  christos 		client->old_lease = NULL;
   5677  1.1  christos 	}
   5678  1.1  christos 
   5679  1.1  christos 	/* Schedule events. */
   5680  1.1  christos 	dhc6_check_irt(client);
   5681  1.1  christos }
   5682  1.1  christos 
   5683  1.1  christos /* While informed, ignore packets.
   5684  1.1  christos  */
   5685  1.1  christos void
   5686  1.1  christos informed_handler(struct packet *packet, struct client_state *client)
   5687  1.1  christos {
   5688  1.1  christos 	log_debug("RCV: Input packets are ignored once bound.");
   5689  1.1  christos }
   5690  1.1  christos 
   5691  1.1  christos /* make_client6_options() fetches option caches relevant to the client's
   5692  1.1  christos  * scope and places them into the sent_options cache.  This cache is later
   5693  1.1  christos  * used to populate DHCPv6 output packets with options.
   5694  1.1  christos  */
   5695  1.1  christos static void
   5696  1.1  christos make_client6_options(struct client_state *client, struct option_state **op,
   5697  1.1  christos 		     struct dhc6_lease *lease, u_int8_t message)
   5698  1.1  christos {
   5699  1.1  christos 	struct option_cache *oc;
   5700  1.1  christos 	struct option **req;
   5701  1.1  christos 	struct buffer *buffer;
   5702  1.1  christos 	int buflen, i, oro_len;
   5703  1.1  christos 
   5704  1.1  christos 	if ((op == NULL) || (client == NULL))
   5705  1.1  christos 		return;
   5706  1.1  christos 
   5707  1.1  christos 	if (*op)
   5708  1.1  christos 		option_state_dereference(op, MDL);
   5709  1.1  christos 
   5710  1.1  christos 	/* Create a cache to carry options to transmission. */
   5711  1.1  christos 	option_state_allocate(op, MDL);
   5712  1.1  christos 
   5713  1.1  christos 	/* Create and store an 'elapsed time' option in the cache. */
   5714  1.1  christos 	oc = NULL;
   5715  1.1  christos 	if (option_cache_allocate(&oc, MDL)) {
   5716  1.1  christos 		const unsigned char *cdata;
   5717  1.1  christos 
   5718  1.1  christos 		cdata = (unsigned char *)&client->elapsed;
   5719  1.1  christos 
   5720  1.1  christos 		if (make_const_data(&oc->expression, cdata, 2, 0, 0, MDL)) {
   5721  1.1  christos 			option_reference(&oc->option, elapsed_option, MDL);
   5722  1.1  christos 			save_option(&dhcpv6_universe, *op, oc);
   5723  1.1  christos 		}
   5724  1.1  christos 
   5725  1.1  christos 		option_cache_dereference(&oc, MDL);
   5726  1.1  christos 	}
   5727  1.1  christos 
   5728  1.1  christos 	/* Bring in any configured options to send. */
   5729  1.1  christos 	if (client->config->on_transmission)
   5730  1.1  christos 		execute_statements_in_scope(NULL, NULL, NULL, client,
   5731  1.1  christos 					    lease ? lease->options : NULL,
   5732  1.1  christos 					    *op, &global_scope,
   5733  1.1  christos 					    client->config->on_transmission,
   5734  1.1  christos 					    NULL, NULL);
   5735  1.1  christos 
   5736  1.1  christos 	/* Rapid-commit is only for SOLICITs. */
   5737  1.1  christos 	if (message != DHCPV6_SOLICIT)
   5738  1.1  christos 		delete_option(&dhcpv6_universe, *op, D6O_RAPID_COMMIT);
   5739  1.1  christos 
   5740  1.1  christos 	/* See if the user configured a DUID in a relevant scope.  If not,
   5741  1.1  christos 	 * introduce our default manufactured id.
   5742  1.1  christos 	 */
   5743  1.1  christos 	if ((oc = lookup_option(&dhcpv6_universe, *op,
   5744  1.1  christos 				D6O_CLIENTID)) == NULL) {
   5745  1.1  christos 		if (!option_cache(&oc, &default_duid, NULL, clientid_option,
   5746  1.1  christos 				  MDL))
   5747  1.1  christos 			log_fatal("Failure assembling a DUID.");
   5748  1.1  christos 
   5749  1.1  christos 		save_option(&dhcpv6_universe, *op, oc);
   5750  1.1  christos 		option_cache_dereference(&oc, MDL);
   5751  1.1  christos 	}
   5752  1.1  christos 
   5753  1.1  christos 	/* In cases where we're responding to a single server, put the
   5754  1.1  christos 	 * server's id in the response.
   5755  1.1  christos 	 *
   5756  1.1  christos 	 * Note that lease is NULL for SOLICIT or INFO request messages,
   5757  1.1  christos 	 * and otherwise MUST be present.
   5758  1.1  christos 	 */
   5759  1.1  christos 	if (lease == NULL) {
   5760  1.1  christos 		if ((message != DHCPV6_SOLICIT) &&
   5761  1.1  christos 		    (message != DHCPV6_INFORMATION_REQUEST))
   5762  1.1  christos 			log_fatal("Impossible condition at %s:%d.", MDL);
   5763  1.1  christos 	} else if ((message != DHCPV6_REBIND) &&
   5764  1.1  christos 		   (message != DHCPV6_CONFIRM)) {
   5765  1.1  christos 		oc = lookup_option(&dhcpv6_universe, lease->options,
   5766  1.1  christos 				   D6O_SERVERID);
   5767  1.1  christos 		if (oc != NULL)
   5768  1.1  christos 			save_option(&dhcpv6_universe, *op, oc);
   5769  1.1  christos 	}
   5770  1.1  christos 
   5771  1.1  christos 	/* 'send dhcp6.oro foo;' syntax we used in 4.0.0a1/a2 has been
   5772  1.1  christos 	 * deprecated by adjustments to the 'request' syntax also used for
   5773  1.1  christos 	 * DHCPv4.
   5774  1.1  christos 	 */
   5775  1.1  christos 	if (lookup_option(&dhcpv6_universe, *op, D6O_ORO) != NULL)
   5776  1.1  christos 		log_error("'send dhcp6.oro' syntax is deprecated, please "
   5777  1.1  christos 			  "use the 'request' syntax (\"man dhclient.conf\").");
   5778  1.1  christos 
   5779  1.1  christos 	/* Construct and store an ORO (Option Request Option).  It is a
   5780  1.1  christos 	 * fatal error to fail to send an ORO (of at least zero length).
   5781  1.1  christos 	 *
   5782  1.1  christos 	 * Discussion:  RFC3315 appears to be inconsistent in its statements
   5783  1.1  christos 	 * of whether or not the ORO is mandatory.  In section 18.1.1
   5784  1.1  christos 	 * ("Creation and Transmission of Request Messages"):
   5785  1.1  christos 	 *
   5786  1.1  christos 	 *    The client MUST include an Option Request option (see section
   5787  1.1  christos 	 *    22.7) to indicate the options the client is interested in
   5788  1.1  christos 	 *    receiving.  The client MAY include options with data values as
   5789  1.1  christos 	 *    hints to the server about parameter values the client would like
   5790  1.1  christos 	 *    to have returned.
   5791  1.1  christos 	 *
   5792  1.1  christos 	 * This MUST is missing from the creation/transmission of other
   5793  1.1  christos 	 * messages (such as Renew and Rebind), and the section 22.7 ("Option
   5794  1.1  christos 	 * Request Option" format and definition):
   5795  1.1  christos 	 *
   5796  1.1  christos 	 *    A client MAY include an Option Request option in a Solicit,
   5797  1.1  christos 	 *    Request, Renew, Rebind, Confirm or Information-request message to
   5798  1.1  christos 	 *    inform the server about options the client wants the server to
   5799  1.1  christos 	 *    send to the client.  A server MAY include an Option Request
   5800  1.1  christos 	 *    option in a Reconfigure option to indicate which options the
   5801  1.1  christos 	 *    client should request from the server.
   5802  1.1  christos 	 *
   5803  1.1  christos 	 * seems to relax the requirement from MUST to MAY (and still other
   5804  1.1  christos 	 * language in RFC3315 supports this).
   5805  1.1  christos 	 *
   5806  1.1  christos 	 * In lieu of a clarification of RFC3315, we will conform with the
   5807  1.1  christos 	 * MUST.  Instead of an absent ORO, we will if there are no options
   5808  1.1  christos 	 * to request supply an empty ORO.  Theoretically, an absent ORO is
   5809  1.1  christos 	 * difficult to interpret (does the client want all options or no
   5810  1.1  christos 	 * options?).  A zero-length ORO is intuitively clear: requesting
   5811  1.1  christos 	 * nothing.
   5812  1.1  christos 	 */
   5813  1.1  christos 	buffer = NULL;
   5814  1.1  christos 	oro_len = 0;
   5815  1.1  christos 	buflen = 32;
   5816  1.1  christos 	if (!buffer_allocate(&buffer, buflen, MDL))
   5817  1.1  christos 		log_fatal("Out of memory constructing DHCPv6 ORO.");
   5818  1.1  christos 	req = client->config->requested_options;
   5819  1.1  christos 	if (req != NULL) {
   5820  1.1  christos 		for (i = 0 ; req[i] != NULL ; i++) {
   5821  1.1  christos 			if (buflen == oro_len) {
   5822  1.1  christos 				struct buffer *tmpbuf = NULL;
   5823  1.1  christos 
   5824  1.1  christos 				buflen += 32;
   5825  1.1  christos 
   5826  1.1  christos 				/* Shell game. */
   5827  1.1  christos 				buffer_reference(&tmpbuf, buffer, MDL);
   5828  1.1  christos 				buffer_dereference(&buffer, MDL);
   5829  1.1  christos 
   5830  1.1  christos 				if (!buffer_allocate(&buffer, buflen, MDL))
   5831  1.1  christos 					log_fatal("Out of memory resizing "
   5832  1.1  christos 						  "DHCPv6 ORO buffer.");
   5833  1.1  christos 
   5834  1.1  christos 				memcpy(buffer->data, tmpbuf->data, oro_len);
   5835  1.1  christos 
   5836  1.1  christos 				buffer_dereference(&tmpbuf, MDL);
   5837  1.1  christos 			}
   5838  1.1  christos 
   5839  1.1  christos 			if (req[i]->universe == &dhcpv6_universe) {
   5840  1.1  christos 				/* Append the code to the ORO. */
   5841  1.1  christos 				putUShort(buffer->data + oro_len,
   5842  1.1  christos 					  req[i]->code);
   5843  1.1  christos 				oro_len += 2;
   5844  1.1  christos 			}
   5845  1.1  christos 		}
   5846  1.1  christos 	}
   5847  1.1  christos 
   5848  1.1  christos 	oc = NULL;
   5849  1.1  christos 	if (make_const_option_cache(&oc, &buffer, NULL, oro_len,
   5850  1.1  christos 				    oro_option, MDL)) {
   5851  1.1  christos 		save_option(&dhcpv6_universe, *op, oc);
   5852  1.1  christos 	} else {
   5853  1.1  christos 		log_fatal("Unable to create ORO option cache.");
   5854  1.1  christos 	}
   5855  1.1  christos 
   5856  1.1  christos 	/*
   5857  1.1  christos 	 * Note: make_const_option_cache() consumes the buffer, we do not
   5858  1.1  christos 	 * need to dereference it (XXX).
   5859  1.1  christos 	 */
   5860  1.1  christos 	option_cache_dereference(&oc, MDL);
   5861  1.1  christos }
   5862  1.1  christos 
   5863  1.1  christos /* A clone of the DHCPv4 script_write_params() minus the DHCPv4-specific
   5864  1.1  christos  * filename, server-name, etc specifics.
   5865  1.1  christos  *
   5866  1.1  christos  * Simply, store all values present in all universes of the option state
   5867  1.1  christos  * (probably derived from a DHCPv6 packet) into environment variables
   5868  1.1  christos  * named after the option names (and universe names) but with the 'prefix'
   5869  1.1  christos  * prepended.
   5870  1.1  christos  *
   5871  1.1  christos  * Later, dhclient-script may compare for example "new_time_servers" and
   5872  1.1  christos  * "old_time_servers" for differences, and only upon detecting a change
   5873  1.1  christos  * bother to rewrite ntp.conf and restart it.  Or something along those
   5874  1.1  christos  * generic lines.
   5875  1.1  christos  */
   5876  1.1  christos static void
   5877  1.1  christos script_write_params6(struct client_state *client, const char *prefix,
   5878  1.1  christos 		     struct option_state *options)
   5879  1.1  christos {
   5880  1.1  christos 	struct envadd_state es;
   5881  1.1  christos 	int i;
   5882  1.1  christos 
   5883  1.1  christos 	if (options == NULL)
   5884  1.1  christos 		return;
   5885  1.1  christos 
   5886  1.1  christos 	es.client = client;
   5887  1.1  christos 	es.prefix = prefix;
   5888  1.1  christos 
   5889  1.1  christos 	for (i = 0 ; i < options->universe_count ; i++) {
   5890  1.1  christos 		option_space_foreach(NULL, NULL, client, NULL, options,
   5891  1.1  christos 				     &global_scope, universes[i], &es,
   5892  1.1  christos 				     client_option_envadd);
   5893  1.1  christos 	}
   5894  1.1  christos }
   5895  1.1  christos 
   5896  1.1  christos /*
   5897  1.1  christos  * A clone of the DHCPv4 routine.
   5898  1.1  christos  * Write out the environment variables for the objects that the
   5899  1.1  christos  * client requested.  If the object was requested the variable will be:
   5900  1.1  christos  * requested_<option_name>=1
   5901  1.1  christos  * If it wasn't requested there won't be a variable.
   5902  1.1  christos  */
   5903  1.1  christos static void script_write_requested6(client)
   5904  1.1  christos 	struct client_state *client;
   5905  1.1  christos {
   5906  1.1  christos 	int i;
   5907  1.1  christos 	struct option **req;
   5908  1.1  christos 	char name[256];
   5909  1.1  christos 	req = client->config->requested_options;
   5910  1.1  christos 
   5911  1.1  christos 	if (req == NULL)
   5912  1.1  christos 		return;
   5913  1.1  christos 
   5914  1.1  christos 	for (i = 0 ; req[i] != NULL ; i++) {
   5915  1.1  christos 		if ((req[i]->universe == &dhcpv6_universe) &&
   5916  1.1  christos 		    dhcp_option_ev_name (name, sizeof(name), req[i])) {
   5917  1.1  christos 			client_envadd(client, "requested_", name, "%d", 1);
   5918  1.1  christos 		}
   5919  1.1  christos 	}
   5920  1.1  christos }
   5921  1.1  christos 
   5922  1.1  christos /*
   5923  1.1  christos  * Check if there is something not fully defined in the active lease.
   5924  1.1  christos  */
   5925  1.1  christos static isc_boolean_t
   5926  1.1  christos active_prefix(struct client_state *client)
   5927  1.1  christos {
   5928  1.1  christos 	struct dhc6_lease *lease;
   5929  1.1  christos 	struct dhc6_ia *ia;
   5930  1.1  christos 	struct dhc6_addr *pref;
   5931  1.1  christos 	char zeros[16];
   5932  1.1  christos 
   5933  1.1  christos 	lease = client->active_lease;
   5934  1.1  christos 	if (lease == NULL)
   5935  1.1  christos 		return ISC_FALSE;
   5936  1.1  christos 	memset(zeros, 0, 16);
   5937  1.1  christos 	for (ia = lease->bindings; ia != NULL; ia = ia->next) {
   5938  1.1  christos 		if (ia->ia_type != D6O_IA_PD)
   5939  1.1  christos 			continue;
   5940  1.1  christos 		for (pref = ia->addrs; pref != NULL; pref = pref->next) {
   5941  1.1  christos 			if (pref->plen == 0)
   5942  1.1  christos 				return ISC_FALSE;
   5943  1.1  christos 			if (pref->address.len != 16)
   5944  1.1  christos 				return ISC_FALSE;
   5945  1.1  christos 			if (memcmp(pref->address.iabuf, zeros, 16) == 0)
   5946  1.1  christos 				return ISC_FALSE;
   5947  1.1  christos 		}
   5948  1.1  christos 	}
   5949  1.1  christos 	return ISC_TRUE;
   5950  1.1  christos }
   5951  1.1  christos 
   5952  1.1  christos /* Adds a leases's declined addreses to the outbound packet
   5953  1.1  christos  *
   5954  1.1  christos  * For each IA_NA in the lease that contains one or more declined
   5955  1.1  christos  * addresses, an IA_NA option with an iasubopt for each declined
   5956  1.1  christos  * address is added to the outbound packet.
   5957  1.1  christos  *
   5958  1.1  christos  * We skip PDs and TAs as declines are undefined for them.
   5959  1.1  christos  */
   5960  1.1  christos static isc_result_t
   5961  1.1  christos dhc6_add_ia_na_decline(struct client_state *client, struct data_string *packet,
   5962  1.1  christos 		       struct dhc6_lease *lease) {
   5963  1.1  christos 	struct data_string iads;
   5964  1.1  christos 	struct data_string addrds;
   5965  1.1  christos 	struct dhc6_addr *addr;
   5966  1.1  christos 	struct dhc6_ia *ia;
   5967  1.1  christos 	isc_result_t rval = ISC_R_SUCCESS;
   5968  1.1  christos 
   5969  1.1  christos 	memset(&iads, 0, sizeof(iads));
   5970  1.1  christos 	memset(&addrds, 0, sizeof(addrds));
   5971  1.1  christos 	for (ia = lease->bindings; ia != NULL && rval == ISC_R_SUCCESS;
   5972  1.1  christos 	     ia = ia->next) {
   5973  1.1  christos 		if (ia->ia_type != D6O_IA_NA)
   5974  1.1  christos 			continue;
   5975  1.1  christos 
   5976  1.1  christos 		int start_new_ia = 1;
   5977  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   5978  1.1  christos 			/*
   5979  1.1  christos 			 * Do not confirm expired addresses, do not request
   5980  1.1  christos 			 * expired addresses (but we keep them around for
   5981  1.1  christos 			 * solicit).
   5982  1.1  christos 			 */
   5983  1.1  christos 			if (!(addr->flags & DHC6_ADDR_DECLINED)) {
   5984  1.1  christos 				continue;
   5985  1.1  christos 			}
   5986  1.1  christos 
   5987  1.1  christos 			if (start_new_ia) {
   5988  1.1  christos 				if (!buffer_allocate(&iads.buffer, 12, MDL)) {
   5989  1.1  christos 					log_error("Unable to allocate memory"
   5990  1.1  christos 						  " for IA_NA.");
   5991  1.1  christos 					rval = ISC_R_NOMEMORY;
   5992  1.1  christos 					break;
   5993  1.1  christos 				}
   5994  1.1  christos 
   5995  1.1  christos 				/* Copy the IAID into the packet buffer. */
   5996  1.1  christos 				memcpy(iads.buffer->data, ia->iaid, 4);
   5997  1.1  christos 				iads.data = iads.buffer->data;
   5998  1.1  christos 				iads.len = 12;
   5999  1.1  christos 
   6000  1.1  christos 				/* Set t1/t2 to zero; server will ignore them */
   6001  1.1  christos 				memset(iads.buffer->data + 4, 0, 8);
   6002  1.1  christos 				log_debug("XMT:  X-- IA_NA %s",
   6003  1.1  christos 				print_hex_1(4, iads.buffer->data, 55));
   6004  1.1  christos 				start_new_ia = 0;
   6005  1.1  christos 			}
   6006  1.1  christos 
   6007  1.1  christos 			if (addr->address.len != 16) {
   6008  1.1  christos 				log_error("Illegal IPv6 address length (%d), "
   6009  1.1  christos 					  "ignoring.  (%s:%d)",
   6010  1.1  christos 					  addr->address.len, MDL);
   6011  1.1  christos 				continue;
   6012  1.1  christos 			}
   6013  1.1  christos 
   6014  1.1  christos 			if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
   6015  1.1  christos 				log_error("Unable to allocate memory for "
   6016  1.1  christos 					  "IAADDR.");
   6017  1.1  christos 				rval = ISC_R_NOMEMORY;
   6018  1.1  christos 				break;
   6019  1.1  christos 			}
   6020  1.1  christos 
   6021  1.1  christos 			addrds.data = addrds.buffer->data;
   6022  1.1  christos 			addrds.len = 24;
   6023  1.1  christos 
   6024  1.1  christos 			/* Copy the address into the packet buffer. */
   6025  1.1  christos 			memcpy(addrds.buffer->data, addr->address.iabuf, 16);
   6026  1.1  christos 
   6027  1.1  christos 			/* Preferred and max life are irrelevant */
   6028  1.1  christos 			memset(addrds.buffer->data + 16, 0, 8);
   6029  1.1  christos 			log_debug("XMT:  | X-- Decline Address %s",
   6030  1.1  christos 				  piaddr(addr->address));
   6031  1.1  christos 
   6032  1.1  christos 			append_option(&iads, &dhcpv6_universe, iaaddr_option,
   6033  1.1  christos 				      &addrds);
   6034  1.1  christos 			data_string_forget(&addrds, MDL);
   6035  1.1  christos 		}
   6036  1.1  christos 
   6037  1.1  christos 		/*
   6038  1.1  christos 		 * It doesn't make sense to make a request without an
   6039  1.1  christos 		 * address.
   6040  1.1  christos 		 */
   6041  1.1  christos 		if (ia->addrs == NULL) {
   6042  1.1  christos 			log_debug("!!!:  V IA_NA has no IAADDRs - removed.");
   6043  1.1  christos 			rval = ISC_R_FAILURE;
   6044  1.1  christos 		} else if (rval == ISC_R_SUCCESS) {
   6045  1.1  christos 			log_debug("XMT:  V IA_NA appended.");
   6046  1.1  christos 			append_option(packet, &dhcpv6_universe, ia_na_option,
   6047  1.1  christos 				      &iads);
   6048  1.1  christos 		}
   6049  1.1  christos 
   6050  1.1  christos 		data_string_forget(&iads, MDL);
   6051  1.1  christos 	}
   6052  1.1  christos 
   6053  1.1  christos 	return (rval);
   6054  1.1  christos }
   6055  1.1  christos 
   6056  1.1  christos /*
   6057  1.1  christos  * Remove any declined NA addresses from the lease.
   6058  1.1  christos  *
   6059  1.1  christos  * Returns zero if the all of the bindings on the lease
   6060  1.1  christos  * were removed, non-zero if there are PD, TA, or usuable NA
   6061  1.1  christos  * bindings
   6062  1.1  christos  */
   6063  1.1  christos int drop_declined_addrs(struct dhc6_lease *lease) {
   6064  1.1  christos 	struct dhc6_ia *ia;
   6065  1.1  christos 	int live_cnt = 0;
   6066  1.1  christos 
   6067  1.1  christos 	for (ia = lease->bindings; ia != NULL; ia = ia->next) {
   6068  1.1  christos 		struct dhc6_addr* prev_addr;
   6069  1.1  christos 		struct dhc6_addr* addr;
   6070  1.1  christos 		struct dhc6_addr* next;
   6071  1.1  christos 
   6072  1.1  christos 		/* If it's a PD or TA, we assume it has at least
   6073  1.1  christos 		* one usuable binding */
   6074  1.1  christos 		if (ia->ia_type != D6O_IA_NA) {
   6075  1.1  christos 			live_cnt++;
   6076  1.1  christos 			continue;
   6077  1.1  christos 		}
   6078  1.1  christos 
   6079  1.1  christos 		prev_addr = NULL;
   6080  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; ) {
   6081  1.1  christos 			if (!(addr->flags & DHC6_ADDR_DECLINED))  {
   6082  1.1  christos 				live_cnt++;
   6083  1.1  christos 				addr = addr->next;
   6084  1.1  christos 				prev_addr = addr;
   6085  1.1  christos 				continue;
   6086  1.1  christos 			}
   6087  1.1  christos 
   6088  1.1  christos 			/* If we're deleting head, move it up one */
   6089  1.1  christos 			if (ia->addrs == addr) {
   6090  1.1  christos 				ia->addrs = addr->next;
   6091  1.1  christos 				prev_addr = addr->next;
   6092  1.1  christos 			} else {
   6093  1.1  christos 				prev_addr->next = addr->next;
   6094  1.1  christos 			}
   6095  1.1  christos 
   6096  1.1  christos 			if (addr->options != NULL) {
   6097  1.1  christos                         	option_state_dereference(&addr->options, MDL);
   6098  1.1  christos 			}
   6099  1.1  christos 
   6100  1.1  christos 			next = addr->next;
   6101  1.1  christos 			dfree(addr, MDL);
   6102  1.1  christos 			addr = next;
   6103  1.1  christos 		}
   6104  1.1  christos 	}
   6105  1.1  christos 
   6106  1.1  christos 	return (live_cnt);
   6107  1.1  christos }
   6108  1.1  christos 
   6109  1.1  christos /* Run through the addresses in lease and return true if there's any unexpired.
   6110  1.1  christos  * Return false otherwise.
   6111  1.1  christos  */
   6112  1.1  christos static isc_boolean_t
   6113  1.1  christos unexpired_address_in_lease(struct dhc6_lease *lease)
   6114  1.1  christos {
   6115  1.1  christos 	struct dhc6_ia *ia;
   6116  1.1  christos 	struct dhc6_addr *addr;
   6117  1.1  christos 
   6118  1.1  christos 	if (lease == NULL) {
   6119  1.1  christos 		return ISC_FALSE;
   6120  1.1  christos 	}
   6121  1.1  christos 
   6122  1.1  christos 	for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
   6123  1.1  christos 		for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
   6124  1.1  christos 			if (!(addr->flags & DHC6_ADDR_EXPIRED) &&
   6125  1.1  christos 			    (addr->starts + addr->max_life > cur_time)) {
   6126  1.1  christos 				return ISC_TRUE;
   6127  1.1  christos 			}
   6128  1.1  christos 		}
   6129  1.1  christos 	}
   6130  1.1  christos 
   6131  1.1  christos 	log_debug("PRC: Previous lease is devoid of active addresses.");
   6132  1.1  christos 	return ISC_FALSE;
   6133  1.1  christos }
   6134  1.1  christos #endif /* DHCPv6 */
   6135