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(©->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(©->options, lease->options, file, line); 494 1.1 christos 495 1.1 christos insert_ia = ©->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(©, 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 = ©->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(©, 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(©->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(©->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(©->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