Remove building with NOCRYPTO option
[minix.git] / external / bsd / dhcp / dist / client / dhc6.c
blob54d95486415b189b390b7a58b7615f030b0896b2
1 /* $NetBSD: dhc6.c,v 1.6 2014/07/12 12:09:37 spz Exp $ */
2 /* dhc6.c - DHCPv6 client routines. */
4 /*
5 * Copyright (c) 2012-2013 by Internet Systems Consortium, Inc. ("ISC")
6 * Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
18 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * Internet Systems Consortium, Inc.
21 * 950 Charter Street
22 * Redwood City, CA 94063
23 * <info@isc.org>
24 * https://www.isc.org/
27 #include <sys/cdefs.h>
28 __RCSID("$NetBSD: dhc6.c,v 1.6 2014/07/12 12:09:37 spz Exp $");
30 #include "dhcpd.h"
32 #ifdef DHCPv6
34 struct sockaddr_in6 DHCPv6DestAddr;
37 * Option definition structures that are used by the software - declared
38 * here once and assigned at startup to save lookups.
40 struct option *clientid_option = NULL;
41 struct option *elapsed_option = NULL;
42 struct option *ia_na_option = NULL;
43 struct option *ia_ta_option = NULL;
44 struct option *ia_pd_option = NULL;
45 struct option *iaaddr_option = NULL;
46 struct option *iaprefix_option = NULL;
47 struct option *oro_option = NULL;
48 struct option *irt_option = NULL;
50 static struct dhc6_lease *dhc6_dup_lease(struct dhc6_lease *lease,
51 const char *file, int line);
52 static struct dhc6_ia *dhc6_dup_ia(struct dhc6_ia *ia,
53 const char *file, int line);
54 static struct dhc6_addr *dhc6_dup_addr(struct dhc6_addr *addr,
55 const char *file, int line);
56 static void dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line);
57 static isc_result_t dhc6_parse_ia_na(struct dhc6_ia **pia,
58 struct packet *packet,
59 struct option_state *options);
60 static isc_result_t dhc6_parse_ia_ta(struct dhc6_ia **pia,
61 struct packet *packet,
62 struct option_state *options);
63 static isc_result_t dhc6_parse_ia_pd(struct dhc6_ia **pia,
64 struct packet *packet,
65 struct option_state *options);
66 static isc_result_t dhc6_parse_addrs(struct dhc6_addr **paddr,
67 struct packet *packet,
68 struct option_state *options);
69 static isc_result_t dhc6_parse_prefixes(struct dhc6_addr **ppref,
70 struct packet *packet,
71 struct option_state *options);
72 static struct dhc6_ia *find_ia(struct dhc6_ia *head,
73 u_int16_t type, const char *id);
74 static struct dhc6_addr *find_addr(struct dhc6_addr *head,
75 struct iaddr *address);
76 static struct dhc6_addr *find_pref(struct dhc6_addr *head,
77 struct iaddr *prefix, u_int8_t plen);
78 void init_handler(struct packet *packet, struct client_state *client);
79 void info_request_handler(struct packet *packet, struct client_state *client);
80 void rapid_commit_handler(struct packet *packet, struct client_state *client);
81 void do_init6(void *input);
82 void do_info_request6(void *input);
83 void do_confirm6(void *input);
84 void reply_handler(struct packet *packet, struct client_state *client);
85 static isc_result_t dhc6_add_ia_na(struct client_state *client,
86 struct data_string *packet,
87 struct dhc6_lease *lease,
88 u_int8_t message);
89 static isc_result_t dhc6_add_ia_ta(struct client_state *client,
90 struct data_string *packet,
91 struct dhc6_lease *lease,
92 u_int8_t message);
93 static isc_result_t dhc6_add_ia_pd(struct client_state *client,
94 struct data_string *packet,
95 struct dhc6_lease *lease,
96 u_int8_t message);
97 static isc_boolean_t stopping_finished(void);
98 static void dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst);
99 void do_select6(void *input);
100 void do_refresh6(void *input);
101 static void do_release6(void *input);
102 static void start_bound(struct client_state *client);
103 static void start_informed(struct client_state *client);
104 void informed_handler(struct packet *packet, struct client_state *client);
105 void bound_handler(struct packet *packet, struct client_state *client);
106 void start_renew6(void *input);
107 void start_rebind6(void *input);
108 void do_depref(void *input);
109 void do_expire(void *input);
110 static void make_client6_options(struct client_state *client,
111 struct option_state **op,
112 struct dhc6_lease *lease, u_int8_t message);
113 static void script_write_params6(struct client_state *client,
114 const char *prefix,
115 struct option_state *options);
116 static void script_write_requested6(struct client_state *client);
117 static isc_boolean_t active_prefix(struct client_state *client);
119 static int check_timing6(struct client_state *client, u_int8_t msg_type,
120 char *msg_str, struct dhc6_lease *lease,
121 struct data_string *ds);
123 extern int onetry;
124 extern int stateless;
127 * Assign DHCPv6 port numbers as a client.
129 void
130 dhcpv6_client_assignments(void)
132 struct servent *ent;
133 unsigned code;
135 if (path_dhclient_pid == NULL)
136 path_dhclient_pid = _PATH_DHCLIENT6_PID;
137 if (path_dhclient_db == NULL)
138 path_dhclient_db = _PATH_DHCLIENT6_DB;
140 if (local_port == 0) {
141 ent = getservbyname("dhcpv6-client", "udp");
142 if (ent == NULL)
143 local_port = htons(546);
144 else
145 local_port = ent->s_port;
148 if (remote_port == 0) {
149 ent = getservbyname("dhcpv6-server", "udp");
150 if (ent == NULL)
151 remote_port = htons(547);
152 else
153 remote_port = ent->s_port;
156 memset(&DHCPv6DestAddr, 0, sizeof(DHCPv6DestAddr));
157 DHCPv6DestAddr.sin6_family = AF_INET6;
158 DHCPv6DestAddr.sin6_port = remote_port;
159 if (inet_pton(AF_INET6, All_DHCP_Relay_Agents_and_Servers,
160 &DHCPv6DestAddr.sin6_addr) <= 0) {
161 log_fatal("Bad address %s", All_DHCP_Relay_Agents_and_Servers);
164 code = D6O_CLIENTID;
165 if (!option_code_hash_lookup(&clientid_option,
166 dhcpv6_universe.code_hash, &code, 0, MDL))
167 log_fatal("Unable to find the CLIENTID option definition.");
169 code = D6O_ELAPSED_TIME;
170 if (!option_code_hash_lookup(&elapsed_option,
171 dhcpv6_universe.code_hash, &code, 0, MDL))
172 log_fatal("Unable to find the ELAPSED_TIME option definition.");
174 code = D6O_IA_NA;
175 if (!option_code_hash_lookup(&ia_na_option, dhcpv6_universe.code_hash,
176 &code, 0, MDL))
177 log_fatal("Unable to find the IA_NA option definition.");
179 code = D6O_IA_TA;
180 if (!option_code_hash_lookup(&ia_ta_option, dhcpv6_universe.code_hash,
181 &code, 0, MDL))
182 log_fatal("Unable to find the IA_TA option definition.");
184 code = D6O_IA_PD;
185 if (!option_code_hash_lookup(&ia_pd_option, dhcpv6_universe.code_hash,
186 &code, 0, MDL))
187 log_fatal("Unable to find the IA_PD option definition.");
189 code = D6O_IAADDR;
190 if (!option_code_hash_lookup(&iaaddr_option, dhcpv6_universe.code_hash,
191 &code, 0, MDL))
192 log_fatal("Unable to find the IAADDR option definition.");
194 code = D6O_IAPREFIX;
195 if (!option_code_hash_lookup(&iaprefix_option,
196 dhcpv6_universe.code_hash,
197 &code, 0, MDL))
198 log_fatal("Unable to find the IAPREFIX option definition.");
200 code = D6O_ORO;
201 if (!option_code_hash_lookup(&oro_option, dhcpv6_universe.code_hash,
202 &code, 0, MDL))
203 log_fatal("Unable to find the ORO option definition.");
205 code = D6O_INFORMATION_REFRESH_TIME;
206 if (!option_code_hash_lookup(&irt_option, dhcpv6_universe.code_hash,
207 &code, 0, MDL))
208 log_fatal("Unable to find the IRT option definition.");
210 #ifndef __CYGWIN32__ /* XXX */
211 endservent();
212 #endif
216 * Instead of implementing RFC3315 RAND (section 14) as a float "between"
217 * -0.1 and 0.1 non-inclusive, we implement it as an integer.
219 * The result is expected to follow this table:
221 * split range answer
222 * - ERROR - base <= 0
223 * 0 1 0..0 1 <= base <= 10
224 * 1 3 -1..1 11 <= base <= 20
225 * 2 5 -2..2 21 <= base <= 30
226 * 3 7 -3..3 31 <= base <= 40
227 * ...
229 * XXX: For this to make sense, we really need to do timing on a
230 * XXX: usec scale...we currently can assume zero for any value less than
231 * XXX: 11, which are very common in early stages of transmission for most
232 * XXX: messages.
234 static TIME
235 dhc6_rand(TIME base)
237 TIME rval;
238 TIME range;
239 TIME split;
242 * A zero or less timeout is a bad thing...we don't want to
243 * DHCP-flood anyone.
245 if (base <= 0)
246 log_fatal("Impossible condition at %s:%d.", MDL);
249 * The first thing we do is count how many random integers we want
250 * in either direction (best thought of as the maximum negative
251 * integer, as we will subtract this potentially from a random 0).
253 split = (base - 1) / 10;
255 /* Don't bother with the rest of the math if we know we'll get 0. */
256 if (split == 0)
257 return 0;
260 * Then we count the total number of integers in this set. This
261 * is twice the number of integers in positive and negative
262 * directions, plus zero (-1, 0, 1 is 3, -2..2 adds 2 to 5, so forth).
264 range = (split * 2) + 1;
266 /* Take a random number from [0..(range-1)]. */
267 rval = random();
268 rval %= range;
270 /* Offset it to uncover potential negative values. */
271 rval -= split;
273 return rval;
276 /* Initialize message exchange timers (set RT from Initial-RT). */
277 static void
278 dhc6_retrans_init(struct client_state *client)
280 int xid;
282 /* Initialize timers. */
283 client->txcount = 0;
284 client->RT = client->IRT + dhc6_rand(client->IRT);
286 /* Generate a new random 24-bit transaction ID for this exchange. */
288 #if (RAND_MAX >= 0x00ffffff)
289 xid = random();
290 #elif (RAND_MAX >= 0x0000ffff)
291 xid = (random() << 16) ^ random();
292 #elif (RAND_MAX >= 0x000000ff)
293 xid = (random() << 16) ^ (random() << 8) ^ random();
294 #else
295 # error "Random number generator of less than 8 bits not supported."
296 #endif
298 client->dhcpv6_transaction_id[0] = (xid >> 16) & 0xff;
299 client->dhcpv6_transaction_id[1] = (xid >> 8) & 0xff;
300 client->dhcpv6_transaction_id[2] = xid & 0xff;
303 /* Advance the DHCPv6 retransmission state once. */
304 static void
305 dhc6_retrans_advance(struct client_state *client)
307 struct timeval elapsed;
309 /* elapsed = cur - start */
310 elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
311 elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
312 if (elapsed.tv_usec < 0) {
313 elapsed.tv_sec -= 1;
314 elapsed.tv_usec += 1000000;
316 /* retrans_advance is called after consuming client->RT. */
317 /* elapsed += RT */
318 elapsed.tv_sec += client->RT / 100;
319 elapsed.tv_usec += (client->RT % 100) * 10000;
320 if (elapsed.tv_usec >= 1000000) {
321 elapsed.tv_sec += 1;
322 elapsed.tv_usec -= 1000000;
326 * RT for each subsequent message transmission is based on the previous
327 * value of RT:
329 * RT = 2*RTprev + RAND*RTprev
331 client->RT += client->RT + dhc6_rand(client->RT);
334 * MRT specifies an upper bound on the value of RT (disregarding the
335 * randomization added by the use of RAND). If MRT has a value of 0,
336 * there is no upper limit on the value of RT. Otherwise:
338 * if (RT > MRT)
339 * RT = MRT + RAND*MRT
341 if ((client->MRT != 0) && (client->RT > client->MRT))
342 client->RT = client->MRT + dhc6_rand(client->MRT);
345 * Further, if there's an MRD, we should wake up upon reaching
346 * the MRD rather than at some point after it.
348 if (client->MRD == 0) {
349 /* Done. */
350 client->txcount++;
351 return;
353 /* elapsed += client->RT */
354 elapsed.tv_sec += client->RT / 100;
355 elapsed.tv_usec += (client->RT % 100) * 10000;
356 if (elapsed.tv_usec >= 1000000) {
357 elapsed.tv_sec += 1;
358 elapsed.tv_usec -= 1000000;
360 if (elapsed.tv_sec >= client->MRD) {
362 * wake at RT + cur = start + MRD
364 client->RT = client->MRD +
365 (client->start_time.tv_sec - cur_tv.tv_sec);
366 client->RT = client->RT * 100 +
367 (client->start_time.tv_usec - cur_tv.tv_usec) / 10000;
369 client->txcount++;
372 /* Quick validation of DHCPv6 ADVERTISE packet contents. */
373 static int
374 valid_reply(struct packet *packet, struct client_state *client)
376 struct data_string sid, cid;
377 struct option_cache *oc;
378 int rval = ISC_TRUE;
380 memset(&sid, 0, sizeof(sid));
381 memset(&cid, 0, sizeof(cid));
383 if (!lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID)) {
384 log_error("Response without a server identifier received.");
385 rval = ISC_FALSE;
388 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
389 if (!oc ||
390 !evaluate_option_cache(&sid, packet, NULL, client, packet->options,
391 client->sent_options, &global_scope, oc,
392 MDL)) {
393 log_error("Response without a client identifier.");
394 rval = ISC_FALSE;
397 oc = lookup_option(&dhcpv6_universe, client->sent_options,
398 D6O_CLIENTID);
399 if (!oc ||
400 !evaluate_option_cache(&cid, packet, NULL, client,
401 client->sent_options, NULL, &global_scope,
402 oc, MDL)) {
403 log_error("Local client identifier is missing!");
404 rval = ISC_FALSE;
407 if (sid.len == 0 ||
408 sid.len != cid.len ||
409 memcmp(sid.data, cid.data, sid.len)) {
410 log_error("Advertise with matching transaction ID, but "
411 "mismatching client id.");
412 rval = ISC_FALSE;
415 return rval;
419 * Create a complete copy of a DHCPv6 lease structure.
421 static struct dhc6_lease *
422 dhc6_dup_lease(struct dhc6_lease *lease, const char *file, int line)
424 struct dhc6_lease *copy;
425 struct dhc6_ia **insert_ia, *ia;
427 copy = dmalloc(sizeof(*copy), file, line);
428 if (copy == NULL) {
429 log_error("Out of memory for v6 lease structure.");
430 return NULL;
433 data_string_copy(&copy->server_id, &lease->server_id, file, line);
434 copy->pref = lease->pref;
436 memcpy(copy->dhcpv6_transaction_id, lease->dhcpv6_transaction_id,
437 sizeof(copy->dhcpv6_transaction_id));
439 option_state_reference(&copy->options, lease->options, file, line);
441 insert_ia = &copy->bindings;
442 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
443 *insert_ia = dhc6_dup_ia(ia, file, line);
445 if (*insert_ia == NULL) {
446 dhc6_lease_destroy(&copy, file, line);
447 return NULL;
450 insert_ia = &(*insert_ia)->next;
453 return copy;
457 * Duplicate an IA structure.
459 static struct dhc6_ia *
460 dhc6_dup_ia(struct dhc6_ia *ia, const char *file, int line)
462 struct dhc6_ia *copy;
463 struct dhc6_addr **insert_addr, *addr;
465 copy = dmalloc(sizeof(*ia), file, line);
467 memcpy(copy->iaid, ia->iaid, sizeof(copy->iaid));
469 copy->ia_type = ia->ia_type;
470 copy->starts = ia->starts;
471 copy->renew = ia->renew;
472 copy->rebind = ia->rebind;
474 insert_addr = &copy->addrs;
475 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
476 *insert_addr = dhc6_dup_addr(addr, file, line);
478 if (*insert_addr == NULL) {
479 dhc6_ia_destroy(&copy, file, line);
480 return NULL;
483 insert_addr = &(*insert_addr)->next;
486 if (ia->options != NULL)
487 option_state_reference(&copy->options, ia->options,
488 file, line);
490 return copy;
494 * Duplicate an IAADDR or IAPREFIX structure.
496 static struct dhc6_addr *
497 dhc6_dup_addr(struct dhc6_addr *addr, const char *file, int line)
499 struct dhc6_addr *copy;
501 copy = dmalloc(sizeof(*addr), file, line);
503 if (copy == NULL)
504 return NULL;
506 memcpy(&copy->address, &addr->address, sizeof(copy->address));
508 copy->plen = addr->plen;
509 copy->flags = addr->flags;
510 copy->starts = addr->starts;
511 copy->preferred_life = addr->preferred_life;
512 copy->max_life = addr->max_life;
514 if (addr->options != NULL)
515 option_state_reference(&copy->options, addr->options,
516 file, line);
518 return copy;
522 * Form a DHCPv6 lease structure based upon packet contents. Creates and
523 * populates IA's and any IAADDR/IAPREFIX's they contain.
524 * Parsed options are deleted in order to not save them in the lease file.
526 static struct dhc6_lease *
527 dhc6_leaseify(struct packet *packet)
529 struct data_string ds;
530 struct dhc6_lease *lease;
531 struct option_cache *oc;
533 lease = dmalloc(sizeof(*lease), MDL);
534 if (lease == NULL) {
535 log_error("Out of memory for v6 lease structure.");
536 return NULL;
539 memcpy(lease->dhcpv6_transaction_id, packet->dhcpv6_transaction_id, 3);
540 option_state_reference(&lease->options, packet->options, MDL);
542 memset(&ds, 0, sizeof(ds));
544 /* Determine preference (default zero). */
545 oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
546 if (oc &&
547 evaluate_option_cache(&ds, packet, NULL, NULL, lease->options,
548 NULL, &global_scope, oc, MDL)) {
549 if (ds.len != 1) {
550 log_error("Invalid length of DHCPv6 Preference option "
551 "(%d != 1)", ds.len);
552 data_string_forget(&ds, MDL);
553 dhc6_lease_destroy(&lease, MDL);
554 return NULL;
555 } else {
556 lease->pref = ds.data[0];
557 log_debug("RCV: X-- Preference %u.",
558 (unsigned)lease->pref);
561 data_string_forget(&ds, MDL);
563 delete_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
566 * Dig into recursive DHCPv6 pockets for IA_NA and contained IAADDR
567 * options.
569 if (dhc6_parse_ia_na(&lease->bindings, packet,
570 lease->options) != ISC_R_SUCCESS) {
571 /* Error conditions are logged by the caller. */
572 dhc6_lease_destroy(&lease, MDL);
573 return NULL;
576 * Dig into recursive DHCPv6 pockets for IA_TA and contained IAADDR
577 * options.
579 if (dhc6_parse_ia_ta(&lease->bindings, packet,
580 lease->options) != ISC_R_SUCCESS) {
581 /* Error conditions are logged by the caller. */
582 dhc6_lease_destroy(&lease, MDL);
583 return NULL;
586 * Dig into recursive DHCPv6 pockets for IA_PD and contained IAPREFIX
587 * options.
589 if (dhc6_parse_ia_pd(&lease->bindings, packet,
590 lease->options) != ISC_R_SUCCESS) {
591 /* Error conditions are logged by the caller. */
592 dhc6_lease_destroy(&lease, MDL);
593 return NULL;
597 * This is last because in the future we may want to make a different
598 * key based upon additional information from the packet (we may need
599 * to allow multiple leases in one client state per server, but we're
600 * not sure based on what additional keys now).
602 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
603 if ((oc == NULL) ||
604 !evaluate_option_cache(&lease->server_id, packet, NULL, NULL,
605 lease->options, NULL, &global_scope,
606 oc, MDL) ||
607 lease->server_id.len == 0) {
608 /* This should be impossible due to validation checks earlier.
610 log_error("Invalid SERVERID option cache.");
611 dhc6_lease_destroy(&lease, MDL);
612 return NULL;
613 } else {
614 log_debug("RCV: X-- Server ID: %s",
615 print_hex_1(lease->server_id.len,
616 lease->server_id.data, 52));
619 return lease;
622 static isc_result_t
623 dhc6_parse_ia_na(struct dhc6_ia **pia, struct packet *packet,
624 struct option_state *options)
626 struct data_string ds;
627 struct dhc6_ia *ia;
628 struct option_cache *oc;
629 isc_result_t result;
631 memset(&ds, 0, sizeof(ds));
633 oc = lookup_option(&dhcpv6_universe, options, D6O_IA_NA);
634 for ( ; oc != NULL ; oc = oc->next) {
635 ia = dmalloc(sizeof(*ia), MDL);
636 if (ia == NULL) {
637 log_error("Out of memory allocating IA_NA structure.");
638 return ISC_R_NOMEMORY;
639 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
640 options, NULL,
641 &global_scope, oc, MDL) &&
642 ds.len >= 12) {
643 memcpy(ia->iaid, ds.data, 4);
644 ia->ia_type = D6O_IA_NA;
645 ia->starts = cur_time;
646 ia->renew = getULong(ds.data + 4);
647 ia->rebind = getULong(ds.data + 8);
649 log_debug("RCV: X-- IA_NA %s",
650 print_hex_1(4, ia->iaid, 59));
651 /* XXX: This should be the printed time I think. */
652 log_debug("RCV: | X-- starts %u",
653 (unsigned)ia->starts);
654 log_debug("RCV: | X-- t1 - renew +%u", ia->renew);
655 log_debug("RCV: | X-- t2 - rebind +%u", ia->rebind);
658 * RFC3315 section 22.4, discard IA_NA's that
659 * have t1 greater than t2, and both not zero.
660 * Since RFC3315 defines this behaviour, it is not
661 * an error - just normal operation.
663 * Note that RFC3315 says we MUST honor these values
664 * if they are not zero. So insane values are
665 * totally OK.
667 if ((ia->renew > 0) && (ia->rebind > 0) &&
668 (ia->renew > ia->rebind)) {
669 log_debug("RCV: | !-- INVALID renew/rebind "
670 "times, IA_NA discarded.");
671 dfree(ia, MDL);
672 data_string_forget(&ds, MDL);
673 continue;
676 if (ds.len > 12) {
677 log_debug("RCV: | X-- [Options]");
679 if (!option_state_allocate(&ia->options,
680 MDL)) {
681 log_error("Out of memory allocating "
682 "IA_NA option state.");
683 dfree(ia, MDL);
684 data_string_forget(&ds, MDL);
685 return ISC_R_NOMEMORY;
688 if (!parse_option_buffer(ia->options,
689 ds.data + 12,
690 ds.len - 12,
691 &dhcpv6_universe)) {
692 log_error("Corrupt IA_NA options.");
693 option_state_dereference(&ia->options,
694 MDL);
695 dfree(ia, MDL);
696 data_string_forget(&ds, MDL);
697 return DHCP_R_BADPARSE;
700 data_string_forget(&ds, MDL);
702 if (ia->options != NULL) {
703 result = dhc6_parse_addrs(&ia->addrs, packet,
704 ia->options);
705 if (result != ISC_R_SUCCESS) {
706 option_state_dereference(&ia->options,
707 MDL);
708 dfree(ia, MDL);
709 return result;
713 while (*pia != NULL)
714 pia = &(*pia)->next;
715 *pia = ia;
716 pia = &ia->next;
717 } else {
718 log_error("Invalid IA_NA option cache.");
719 dfree(ia, MDL);
720 if (ds.len != 0)
721 data_string_forget(&ds, MDL);
722 return ISC_R_UNEXPECTED;
725 delete_option(&dhcpv6_universe, options, D6O_IA_NA);
727 return ISC_R_SUCCESS;
730 static isc_result_t
731 dhc6_parse_ia_ta(struct dhc6_ia **pia, struct packet *packet,
732 struct option_state *options)
734 struct data_string ds;
735 struct dhc6_ia *ia;
736 struct option_cache *oc;
737 isc_result_t result;
739 memset(&ds, 0, sizeof(ds));
741 oc = lookup_option(&dhcpv6_universe, options, D6O_IA_TA);
742 for ( ; oc != NULL ; oc = oc->next) {
743 ia = dmalloc(sizeof(*ia), MDL);
744 if (ia == NULL) {
745 log_error("Out of memory allocating IA_TA structure.");
746 return ISC_R_NOMEMORY;
747 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
748 options, NULL,
749 &global_scope, oc, MDL) &&
750 ds.len >= 4) {
751 memcpy(ia->iaid, ds.data, 4);
752 ia->ia_type = D6O_IA_TA;
753 ia->starts = cur_time;
755 log_debug("RCV: X-- IA_TA %s",
756 print_hex_1(4, ia->iaid, 59));
757 /* XXX: This should be the printed time I think. */
758 log_debug("RCV: | X-- starts %u",
759 (unsigned)ia->starts);
761 if (ds.len > 4) {
762 log_debug("RCV: | X-- [Options]");
764 if (!option_state_allocate(&ia->options,
765 MDL)) {
766 log_error("Out of memory allocating "
767 "IA_TA option state.");
768 dfree(ia, MDL);
769 data_string_forget(&ds, MDL);
770 return ISC_R_NOMEMORY;
773 if (!parse_option_buffer(ia->options,
774 ds.data + 4,
775 ds.len - 4,
776 &dhcpv6_universe)) {
777 log_error("Corrupt IA_TA options.");
778 option_state_dereference(&ia->options,
779 MDL);
780 dfree(ia, MDL);
781 data_string_forget(&ds, MDL);
782 return DHCP_R_BADPARSE;
785 data_string_forget(&ds, MDL);
787 if (ia->options != NULL) {
788 result = dhc6_parse_addrs(&ia->addrs, packet,
789 ia->options);
790 if (result != ISC_R_SUCCESS) {
791 option_state_dereference(&ia->options,
792 MDL);
793 dfree(ia, MDL);
794 return result;
798 while (*pia != NULL)
799 pia = &(*pia)->next;
800 *pia = ia;
801 pia = &ia->next;
802 } else {
803 log_error("Invalid IA_TA option cache.");
804 dfree(ia, MDL);
805 if (ds.len != 0)
806 data_string_forget(&ds, MDL);
807 return ISC_R_UNEXPECTED;
810 delete_option(&dhcpv6_universe, options, D6O_IA_TA);
812 return ISC_R_SUCCESS;
815 static isc_result_t
816 dhc6_parse_ia_pd(struct dhc6_ia **pia, struct packet *packet,
817 struct option_state *options)
819 struct data_string ds;
820 struct dhc6_ia *ia;
821 struct option_cache *oc;
822 isc_result_t result;
824 memset(&ds, 0, sizeof(ds));
826 oc = lookup_option(&dhcpv6_universe, options, D6O_IA_PD);
827 for ( ; oc != NULL ; oc = oc->next) {
828 ia = dmalloc(sizeof(*ia), MDL);
829 if (ia == NULL) {
830 log_error("Out of memory allocating IA_PD structure.");
831 return ISC_R_NOMEMORY;
832 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
833 options, NULL,
834 &global_scope, oc, MDL) &&
835 ds.len >= 12) {
836 memcpy(ia->iaid, ds.data, 4);
837 ia->ia_type = D6O_IA_PD;
838 ia->starts = cur_time;
839 ia->renew = getULong(ds.data + 4);
840 ia->rebind = getULong(ds.data + 8);
842 log_debug("RCV: X-- IA_PD %s",
843 print_hex_1(4, ia->iaid, 59));
844 /* XXX: This should be the printed time I think. */
845 log_debug("RCV: | X-- starts %u",
846 (unsigned)ia->starts);
847 log_debug("RCV: | X-- t1 - renew +%u", ia->renew);
848 log_debug("RCV: | X-- t2 - rebind +%u", ia->rebind);
851 * RFC3633 section 9, discard IA_PD's that
852 * have t1 greater than t2, and both not zero.
853 * Since RFC3633 defines this behaviour, it is not
854 * an error - just normal operation.
856 if ((ia->renew > 0) && (ia->rebind > 0) &&
857 (ia->renew > ia->rebind)) {
858 log_debug("RCV: | !-- INVALID renew/rebind "
859 "times, IA_PD discarded.");
860 dfree(ia, MDL);
861 data_string_forget(&ds, MDL);
862 continue;
865 if (ds.len > 12) {
866 log_debug("RCV: | X-- [Options]");
868 if (!option_state_allocate(&ia->options,
869 MDL)) {
870 log_error("Out of memory allocating "
871 "IA_PD option state.");
872 dfree(ia, MDL);
873 data_string_forget(&ds, MDL);
874 return ISC_R_NOMEMORY;
877 if (!parse_option_buffer(ia->options,
878 ds.data + 12,
879 ds.len - 12,
880 &dhcpv6_universe)) {
881 log_error("Corrupt IA_PD options.");
882 option_state_dereference(&ia->options,
883 MDL);
884 dfree(ia, MDL);
885 data_string_forget(&ds, MDL);
886 return DHCP_R_BADPARSE;
889 data_string_forget(&ds, MDL);
891 if (ia->options != NULL) {
892 result = dhc6_parse_prefixes(&ia->addrs,
893 packet,
894 ia->options);
895 if (result != ISC_R_SUCCESS) {
896 option_state_dereference(&ia->options,
897 MDL);
898 dfree(ia, MDL);
899 return result;
903 while (*pia != NULL)
904 pia = &(*pia)->next;
905 *pia = ia;
906 pia = &ia->next;
907 } else {
908 log_error("Invalid IA_PD option cache.");
909 dfree(ia, MDL);
910 if (ds.len != 0)
911 data_string_forget(&ds, MDL);
912 return ISC_R_UNEXPECTED;
915 delete_option(&dhcpv6_universe, options, D6O_IA_PD);
917 return ISC_R_SUCCESS;
921 static isc_result_t
922 dhc6_parse_addrs(struct dhc6_addr **paddr, struct packet *packet,
923 struct option_state *options)
925 struct data_string ds;
926 struct option_cache *oc;
927 struct dhc6_addr *addr;
929 memset(&ds, 0, sizeof(ds));
931 oc = lookup_option(&dhcpv6_universe, options, D6O_IAADDR);
932 for ( ; oc != NULL ; oc = oc->next) {
933 addr = dmalloc(sizeof(*addr), MDL);
934 if (addr == NULL) {
935 log_error("Out of memory allocating "
936 "address structure.");
937 return ISC_R_NOMEMORY;
938 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
939 options, NULL, &global_scope,
940 oc, MDL) &&
941 (ds.len >= 24)) {
943 addr->address.len = 16;
944 memcpy(addr->address.iabuf, ds.data, 16);
945 addr->starts = cur_time;
946 addr->preferred_life = getULong(ds.data + 16);
947 addr->max_life = getULong(ds.data + 20);
949 log_debug("RCV: | | X-- IAADDR %s",
950 piaddr(addr->address));
951 log_debug("RCV: | | | X-- Preferred lifetime %u.",
952 addr->preferred_life);
953 log_debug("RCV: | | | X-- Max lifetime %u.",
954 addr->max_life);
957 * RFC 3315 section 22.6 says we must discard
958 * addresses whose pref is later than valid.
960 if ((addr->preferred_life > addr->max_life)) {
961 log_debug("RCV: | | | !-- INVALID lifetimes, "
962 "IAADDR discarded. Check your "
963 "server configuration.");
964 dfree(addr, MDL);
965 data_string_forget(&ds, MDL);
966 continue;
970 * Fortunately this is the last recursion in the
971 * protocol.
973 if (ds.len > 24) {
974 if (!option_state_allocate(&addr->options,
975 MDL)) {
976 log_error("Out of memory allocating "
977 "IAADDR option state.");
978 dfree(addr, MDL);
979 data_string_forget(&ds, MDL);
980 return ISC_R_NOMEMORY;
983 if (!parse_option_buffer(addr->options,
984 ds.data + 24,
985 ds.len - 24,
986 &dhcpv6_universe)) {
987 log_error("Corrupt IAADDR options.");
988 option_state_dereference(&addr->options,
989 MDL);
990 dfree(addr, MDL);
991 data_string_forget(&ds, MDL);
992 return DHCP_R_BADPARSE;
996 if (addr->options != NULL)
997 log_debug("RCV: | | | X-- "
998 "[Options]");
1000 data_string_forget(&ds, MDL);
1002 *paddr = addr;
1003 paddr = &addr->next;
1004 } else {
1005 log_error("Invalid IAADDR option cache.");
1006 dfree(addr, MDL);
1007 if (ds.len != 0)
1008 data_string_forget(&ds, MDL);
1009 return ISC_R_UNEXPECTED;
1012 delete_option(&dhcpv6_universe, options, D6O_IAADDR);
1014 return ISC_R_SUCCESS;
1017 static isc_result_t
1018 dhc6_parse_prefixes(struct dhc6_addr **ppfx, struct packet *packet,
1019 struct option_state *options)
1021 struct data_string ds;
1022 struct option_cache *oc;
1023 struct dhc6_addr *pfx;
1025 memset(&ds, 0, sizeof(ds));
1027 oc = lookup_option(&dhcpv6_universe, options, D6O_IAPREFIX);
1028 for ( ; oc != NULL ; oc = oc->next) {
1029 pfx = dmalloc(sizeof(*pfx), MDL);
1030 if (pfx == NULL) {
1031 log_error("Out of memory allocating "
1032 "prefix structure.");
1033 return ISC_R_NOMEMORY;
1034 } else if (evaluate_option_cache(&ds, packet, NULL, NULL,
1035 options, NULL, &global_scope,
1036 oc, MDL) &&
1037 (ds.len >= 25)) {
1039 pfx->preferred_life = getULong(ds.data);
1040 pfx->max_life = getULong(ds.data + 4);
1041 pfx->plen = getUChar(ds.data + 8);
1042 pfx->address.len = 16;
1043 memcpy(pfx->address.iabuf, ds.data + 9, 16);
1044 pfx->starts = cur_time;
1046 log_debug("RCV: | | X-- IAPREFIX %s/%d",
1047 piaddr(pfx->address), (int)pfx->plen);
1048 log_debug("RCV: | | | X-- Preferred lifetime %u.",
1049 pfx->preferred_life);
1050 log_debug("RCV: | | | X-- Max lifetime %u.",
1051 pfx->max_life);
1053 /* Sanity check over the prefix length */
1054 if ((pfx->plen < 4) || (pfx->plen > 128)) {
1055 log_debug("RCV: | | | !-- INVALID prefix "
1056 "length, IAPREFIX discarded. "
1057 "Check your server configuration.");
1058 dfree(pfx, MDL);
1059 data_string_forget(&ds, MDL);
1060 continue;
1063 * RFC 3633 section 10 says we must discard
1064 * prefixes whose pref is later than valid.
1066 if ((pfx->preferred_life > pfx->max_life)) {
1067 log_debug("RCV: | | | !-- INVALID lifetimes, "
1068 "IAPREFIX discarded. Check your "
1069 "server configuration.");
1070 dfree(pfx, MDL);
1071 data_string_forget(&ds, MDL);
1072 continue;
1076 * Fortunately this is the last recursion in the
1077 * protocol.
1079 if (ds.len > 25) {
1080 if (!option_state_allocate(&pfx->options,
1081 MDL)) {
1082 log_error("Out of memory allocating "
1083 "IAPREFIX option state.");
1084 dfree(pfx, MDL);
1085 data_string_forget(&ds, MDL);
1086 return ISC_R_NOMEMORY;
1089 if (!parse_option_buffer(pfx->options,
1090 ds.data + 25,
1091 ds.len - 25,
1092 &dhcpv6_universe)) {
1093 log_error("Corrupt IAPREFIX options.");
1094 option_state_dereference(&pfx->options,
1095 MDL);
1096 dfree(pfx, MDL);
1097 data_string_forget(&ds, MDL);
1098 return DHCP_R_BADPARSE;
1102 if (pfx->options != NULL)
1103 log_debug("RCV: | | | X-- "
1104 "[Options]");
1106 data_string_forget(&ds, MDL);
1108 *ppfx = pfx;
1109 ppfx = &pfx->next;
1110 } else {
1111 log_error("Invalid IAPREFIX option cache.");
1112 dfree(pfx, MDL);
1113 if (ds.len != 0)
1114 data_string_forget(&ds, MDL);
1115 return ISC_R_UNEXPECTED;
1118 delete_option(&dhcpv6_universe, options, D6O_IAPREFIX);
1120 return ISC_R_SUCCESS;
1123 /* Clean up a lease object, deallocate all its parts, and set it to NULL. */
1124 void
1125 dhc6_lease_destroy(struct dhc6_lease **src, const char *file, int line)
1127 struct dhc6_ia *ia, *nia;
1128 struct dhc6_lease *lease;
1130 if (src == NULL || *src == NULL) {
1131 log_error("Attempt to destroy null lease.");
1132 return;
1134 lease = *src;
1136 if (lease->server_id.len != 0)
1137 data_string_forget(&lease->server_id, file, line);
1139 for (ia = lease->bindings ; ia != NULL ; ia = nia) {
1140 nia = ia->next;
1142 dhc6_ia_destroy(&ia, file, line);
1145 if (lease->options != NULL)
1146 option_state_dereference(&lease->options, file, line);
1148 dfree(lease, file, line);
1149 *src = NULL;
1153 * Traverse the addresses list, and destroy their contents, and NULL the
1154 * list pointer.
1156 static void
1157 dhc6_ia_destroy(struct dhc6_ia **src, const char *file, int line)
1159 struct dhc6_addr *addr, *naddr;
1160 struct dhc6_ia *ia;
1162 if (src == NULL || *src == NULL) {
1163 log_error("Attempt to destroy null IA.");
1164 return;
1166 ia = *src;
1168 for (addr = ia->addrs ; addr != NULL ; addr = naddr) {
1169 naddr = addr->next;
1171 if (addr->options != NULL)
1172 option_state_dereference(&addr->options, file, line);
1174 dfree(addr, file, line);
1177 if (ia->options != NULL)
1178 option_state_dereference(&ia->options, file, line);
1180 dfree(ia, file, line);
1181 *src = NULL;
1185 * For a given lease, insert it into the tail of the lease list. Upon
1186 * finding a duplicate by server id, remove it and take over its position.
1188 static void
1189 insert_lease(struct dhc6_lease **head, struct dhc6_lease *new)
1191 while (*head != NULL) {
1192 if ((*head)->server_id.len == new->server_id.len &&
1193 memcmp((*head)->server_id.data, new->server_id.data,
1194 new->server_id.len) == 0) {
1195 new->next = (*head)->next;
1196 dhc6_lease_destroy(head, MDL);
1197 break;
1200 head= &(*head)->next;
1203 *head = new;
1204 return;
1208 * Not really clear what to do here yet.
1210 static int
1211 dhc6_score_lease(struct client_state *client, struct dhc6_lease *lease)
1213 struct dhc6_ia *ia;
1214 struct dhc6_addr *addr;
1215 struct option **req;
1216 int i;
1218 if (lease->score)
1219 return lease->score;
1221 lease->score = 1;
1223 /* If this lease lacks a required option, dump it. */
1224 /* XXX: we should be able to cache the failure... */
1225 req = client->config->required_options;
1226 if (req != NULL) {
1227 for (i = 0 ; req[i] != NULL ; i++) {
1228 if (lookup_option(&dhcpv6_universe, lease->options,
1229 req[i]->code) == NULL) {
1230 lease->score = 0;
1231 return lease->score;
1236 /* If this lease contains a requested option, improve its score. */
1237 req = client->config->requested_options;
1238 if (req != NULL) {
1239 for (i = 0 ; req[i] != NULL ; i++) {
1240 if (lookup_option(&dhcpv6_universe, lease->options,
1241 req[i]->code) != NULL)
1242 lease->score++;
1246 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
1247 lease->score += 50;
1249 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
1250 lease->score += 100;
1254 return lease->score;
1258 * start_init6() kicks off the process, transmitting a packet and
1259 * scheduling a retransmission event.
1261 void
1262 start_init6(struct client_state *client)
1264 struct timeval tv;
1266 log_debug("PRC: Soliciting for leases (INIT).");
1267 client->state = S_INIT;
1269 /* Initialize timers, RFC3315 section 17.1.2. */
1270 client->IRT = SOL_TIMEOUT * 100;
1271 client->MRT = SOL_MAX_RT * 100;
1272 client->MRC = 0;
1273 /* Default is 0 (no max) but -1 changes this. */
1274 if (!onetry)
1275 client->MRD = 0;
1276 else
1277 client->MRD = client->config->timeout;
1279 dhc6_retrans_init(client);
1282 * RFC3315 section 17.1.2 goes out of its way:
1283 * Also, the first RT MUST be selected to be strictly greater than IRT
1284 * by choosing RAND to be strictly greater than 0.
1286 /* if RAND < 0 then RAND = -RAND */
1287 if (client->RT <= client->IRT)
1288 client->RT = client->IRT + (client->IRT - client->RT);
1289 /* if RAND == 0 then RAND = 1 */
1290 if (client->RT <= client->IRT)
1291 client->RT = client->IRT + 1;
1293 client->v6_handler = init_handler;
1296 * RFC3315 section 17.1.2 says we MUST start the first packet
1297 * between 0 and SOL_MAX_DELAY seconds. The good news is
1298 * SOL_MAX_DELAY is 1.
1300 tv.tv_sec = cur_tv.tv_sec;
1301 tv.tv_usec = cur_tv.tv_usec;
1302 tv.tv_usec += (random() % (SOL_MAX_DELAY * 100)) * 10000;
1303 if (tv.tv_usec >= 1000000) {
1304 tv.tv_sec += 1;
1305 tv.tv_usec -= 1000000;
1307 add_timeout(&tv, do_init6, client, NULL, NULL);
1309 if (nowait)
1310 finish_daemon();
1314 * start_info_request6() kicks off the process, transmitting an info
1315 * request packet and scheduling a retransmission event.
1317 void
1318 start_info_request6(struct client_state *client)
1320 struct timeval tv;
1322 log_debug("PRC: Requesting information (INIT).");
1323 client->state = S_INIT;
1325 /* Initialize timers, RFC3315 section 18.1.5. */
1326 client->IRT = INF_TIMEOUT * 100;
1327 client->MRT = INF_MAX_RT * 100;
1328 client->MRC = 0;
1329 /* Default is 0 (no max) but -1 changes this. */
1330 if (!onetry)
1331 client->MRD = 0;
1332 else
1333 client->MRD = client->config->timeout;
1335 dhc6_retrans_init(client);
1337 client->v6_handler = info_request_handler;
1340 * RFC3315 section 18.1.5 says we MUST start the first packet
1341 * between 0 and INF_MAX_DELAY seconds. The good news is
1342 * INF_MAX_DELAY is 1.
1344 tv.tv_sec = cur_tv.tv_sec;
1345 tv.tv_usec = cur_tv.tv_usec;
1346 tv.tv_usec += (random() % (INF_MAX_DELAY * 100)) * 10000;
1347 if (tv.tv_usec >= 1000000) {
1348 tv.tv_sec += 1;
1349 tv.tv_usec -= 1000000;
1351 add_timeout(&tv, do_info_request6, client, NULL, NULL);
1353 if (nowait)
1354 go_daemon();
1358 * start_confirm6() kicks off an "init-reboot" version of the process, at
1359 * startup to find out if old bindings are 'fair' and at runtime whenever
1360 * a link cycles state we'll eventually want to do this.
1362 void
1363 start_confirm6(struct client_state *client)
1365 struct timeval tv;
1367 /* If there is no active lease, there is nothing to check. */
1368 if ((client->active_lease == NULL) ||
1369 !active_prefix(client) ||
1370 client->active_lease->released) {
1371 start_init6(client);
1372 return;
1375 log_debug("PRC: Confirming active lease (INIT-REBOOT).");
1376 client->state = S_REBOOTING;
1378 /* Initialize timers, RFC3315 section 17.1.3. */
1379 client->IRT = CNF_TIMEOUT * 100;
1380 client->MRT = CNF_MAX_RT * 100;
1381 client->MRC = 0;
1382 client->MRD = CNF_MAX_RD;
1384 dhc6_retrans_init(client);
1386 client->v6_handler = reply_handler;
1389 * RFC3315 section 18.1.2 says we MUST start the first packet
1390 * between 0 and CNF_MAX_DELAY seconds. The good news is
1391 * CNF_MAX_DELAY is 1.
1393 tv.tv_sec = cur_tv.tv_sec;
1394 tv.tv_usec = cur_tv.tv_usec;
1395 tv.tv_usec += (random() % (CNF_MAX_DELAY * 100)) * 10000;
1396 if (tv.tv_usec >= 1000000) {
1397 tv.tv_sec += 1;
1398 tv.tv_usec -= 1000000;
1400 if (wanted_ia_pd != 0) {
1401 client->state = S_REBINDING;
1402 client->refresh_type = DHCPV6_REBIND;
1403 add_timeout(&tv, do_refresh6, client, NULL, NULL);
1404 } else
1405 add_timeout(&tv, do_confirm6, client, NULL, NULL);
1409 * check_timing6() check on the timing for sending a v6 message
1410 * and then do the basic initialization for a v6 message.
1412 #define CHK_TIM_SUCCESS 0
1413 #define CHK_TIM_MRC_EXCEEDED 1
1414 #define CHK_TIM_MRD_EXCEEDED 2
1415 #define CHK_TIM_ALLOC_FAILURE 3
1418 check_timing6 (struct client_state *client, u_int8_t msg_type,
1419 char *msg_str, struct dhc6_lease *lease,
1420 struct data_string *ds)
1422 struct timeval elapsed;
1425 * Start_time starts at the first transmission.
1427 if (client->txcount == 0) {
1428 client->start_time.tv_sec = cur_tv.tv_sec;
1429 client->start_time.tv_usec = cur_tv.tv_usec;
1430 } else if ((client->MRC != 0) && (client->txcount > client->MRC)) {
1431 log_info("Max retransmission count exceeded.");
1432 return(CHK_TIM_MRC_EXCEEDED);
1435 /* elapsed = cur - start */
1436 elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
1437 elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
1438 if (elapsed.tv_usec < 0) {
1439 elapsed.tv_sec -= 1;
1440 elapsed.tv_usec += 1000000;
1443 /* Check if finished (-1 argument). */
1444 if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) {
1445 log_info("Max retransmission duration exceeded.");
1446 return(CHK_TIM_MRD_EXCEEDED);
1449 memset(ds, 0, sizeof(*ds));
1450 if (!buffer_allocate(&(ds->buffer), 4, MDL)) {
1451 log_error("Unable to allocate memory for %s.", msg_str);
1452 return(CHK_TIM_ALLOC_FAILURE);
1454 ds->data = ds->buffer->data;
1455 ds->len = 4;
1457 ds->buffer->data[0] = msg_type;
1458 memcpy(ds->buffer->data + 1, client->dhcpv6_transaction_id, 3);
1460 /* Form an elapsed option. */
1461 /* Maximum value is 65535 1/100s coded as 0xffff. */
1462 if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
1463 ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
1464 client->elapsed = 0xffff;
1465 } else {
1466 client->elapsed = elapsed.tv_sec * 100;
1467 client->elapsed += elapsed.tv_usec / 10000;
1470 if (client->elapsed == 0)
1471 log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str);
1472 else
1473 log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str,
1474 (unsigned)client->elapsed);
1476 client->elapsed = htons(client->elapsed);
1478 make_client6_options(client, &client->sent_options, lease, msg_type);
1480 return(CHK_TIM_SUCCESS);
1484 * do_init6() marshals and transmits a solicit.
1486 void
1487 do_init6(void *input)
1489 struct client_state *client;
1490 struct dhc6_ia *old_ia;
1491 struct dhc6_addr *old_addr;
1492 struct data_string ds;
1493 struct data_string ia;
1494 struct data_string addr;
1495 struct timeval tv;
1496 u_int32_t t1, t2;
1497 int i, idx, len, send_ret;
1499 client = input;
1502 * In RFC3315 section 17.1.2, the retransmission timer is
1503 * used as the selecting timer.
1505 if (client->advertised_leases != NULL) {
1506 start_selecting6(client);
1507 return;
1510 switch(check_timing6(client, DHCPV6_SOLICIT, "Solicit", NULL, &ds)) {
1511 case CHK_TIM_MRC_EXCEEDED:
1512 case CHK_TIM_ALLOC_FAILURE:
1513 return;
1514 case CHK_TIM_MRD_EXCEEDED:
1515 client->state = S_STOPPED;
1516 if (client->active_lease != NULL) {
1517 dhc6_lease_destroy(&client->active_lease, MDL);
1518 client->active_lease = NULL;
1520 /* Stop if and only if this is the last client. */
1521 if (stopping_finished())
1522 exit(2);
1523 return;
1527 * Fetch any configured 'sent' options (includes DUID) in wire format.
1529 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
1530 NULL, client->sent_options, &global_scope,
1531 &dhcpv6_universe);
1533 /* Use a specific handler with rapid-commit. */
1534 if (lookup_option(&dhcpv6_universe, client->sent_options,
1535 D6O_RAPID_COMMIT) != NULL) {
1536 client->v6_handler = rapid_commit_handler;
1539 /* Append IA_NA. */
1540 for (i = 0; i < wanted_ia_na; i++) {
1542 * XXX: maybe the IA_NA('s) should be put into the sent_options
1543 * cache. They'd have to be pulled down as they also contain
1544 * different option caches in the same universe...
1546 memset(&ia, 0, sizeof(ia));
1547 if (!buffer_allocate(&ia.buffer, 12, MDL)) {
1548 log_error("Unable to allocate memory for IA_NA.");
1549 data_string_forget(&ds, MDL);
1550 return;
1552 ia.data = ia.buffer->data;
1553 ia.len = 12;
1556 * A simple IAID is the last 4 bytes
1557 * of the hardware address.
1559 if (client->interface->hw_address.hlen > 4) {
1560 idx = client->interface->hw_address.hlen - 4;
1561 len = 4;
1562 } else {
1563 idx = 0;
1564 len = client->interface->hw_address.hlen;
1566 memcpy(ia.buffer->data,
1567 client->interface->hw_address.hbuf + idx,
1568 len);
1569 if (i)
1570 ia.buffer->data[3] += i;
1572 t1 = client->config->requested_lease / 2;
1573 t2 = t1 + (t1 / 2);
1574 putULong(ia.buffer->data + 4, t1);
1575 putULong(ia.buffer->data + 8, t2);
1577 log_debug("XMT: X-- IA_NA %s",
1578 print_hex_1(4, ia.buffer->data, 55));
1579 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1);
1580 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2);
1582 if ((client->active_lease != NULL) &&
1583 ((old_ia = find_ia(client->active_lease->bindings,
1584 D6O_IA_NA,
1585 (char *)ia.buffer->data)) != NULL)) {
1587 * For each address in the old IA_NA,
1588 * request a binding.
1590 memset(&addr, 0, sizeof(addr));
1591 for (old_addr = old_ia->addrs ; old_addr != NULL ;
1592 old_addr = old_addr->next) {
1593 if (old_addr->address.len != 16) {
1594 log_error("Invalid IPv6 address "
1595 "length %d. "
1596 "Ignoring. (%s:%d)",
1597 old_addr->address.len,
1598 MDL);
1599 continue;
1602 if (!buffer_allocate(&addr.buffer, 24, MDL)) {
1603 log_error("Unable to allocate memory "
1604 "for IAADDR.");
1605 data_string_forget(&ia, MDL);
1606 data_string_forget(&ds, MDL);
1607 return;
1609 addr.data = addr.buffer->data;
1610 addr.len = 24;
1612 memcpy(addr.buffer->data,
1613 old_addr->address.iabuf,
1614 16);
1616 t1 = client->config->requested_lease;
1617 t2 = t1 + (t1 / 2);
1618 putULong(addr.buffer->data + 16, t1);
1619 putULong(addr.buffer->data + 20, t2);
1621 log_debug("XMT: | X-- Request address %s.",
1622 piaddr(old_addr->address));
1623 log_debug("XMT: | | X-- Request "
1624 "preferred in +%u",
1625 (unsigned)t1);
1626 log_debug("XMT: | | X-- Request valid "
1627 "in +%u",
1628 (unsigned)t2);
1630 append_option(&ia, &dhcpv6_universe,
1631 iaaddr_option,
1632 &addr);
1634 data_string_forget(&addr, MDL);
1638 append_option(&ds, &dhcpv6_universe, ia_na_option, &ia);
1639 data_string_forget(&ia, MDL);
1642 /* Append IA_TA. */
1643 for (i = 0; i < wanted_ia_ta; i++) {
1645 * XXX: maybe the IA_TA('s) should be put into the sent_options
1646 * cache. They'd have to be pulled down as they also contain
1647 * different option caches in the same universe...
1649 memset(&ia, 0, sizeof(ia));
1650 if (!buffer_allocate(&ia.buffer, 4, MDL)) {
1651 log_error("Unable to allocate memory for IA_TA.");
1652 data_string_forget(&ds, MDL);
1653 return;
1655 ia.data = ia.buffer->data;
1656 ia.len = 4;
1659 * A simple IAID is the last 4 bytes
1660 * of the hardware address.
1662 if (client->interface->hw_address.hlen > 4) {
1663 idx = client->interface->hw_address.hlen - 4;
1664 len = 4;
1665 } else {
1666 idx = 0;
1667 len = client->interface->hw_address.hlen;
1669 memcpy(ia.buffer->data,
1670 client->interface->hw_address.hbuf + idx,
1671 len);
1672 if (i)
1673 ia.buffer->data[3] += i;
1675 log_debug("XMT: X-- IA_TA %s",
1676 print_hex_1(4, ia.buffer->data, 55));
1678 if ((client->active_lease != NULL) &&
1679 ((old_ia = find_ia(client->active_lease->bindings,
1680 D6O_IA_TA,
1681 (char *)ia.buffer->data)) != NULL)) {
1683 * For each address in the old IA_TA,
1684 * request a binding.
1686 memset(&addr, 0, sizeof(addr));
1687 for (old_addr = old_ia->addrs ; old_addr != NULL ;
1688 old_addr = old_addr->next) {
1689 if (old_addr->address.len != 16) {
1690 log_error("Invalid IPv6 address "
1691 "length %d. "
1692 "Ignoring. (%s:%d)",
1693 old_addr->address.len,
1694 MDL);
1695 continue;
1698 if (!buffer_allocate(&addr.buffer, 24, MDL)) {
1699 log_error("Unable to allocate memory "
1700 "for IAADDR.");
1701 data_string_forget(&ia, MDL);
1702 data_string_forget(&ds, MDL);
1703 return;
1705 addr.data = addr.buffer->data;
1706 addr.len = 24;
1708 memcpy(addr.buffer->data,
1709 old_addr->address.iabuf,
1710 16);
1712 t1 = client->config->requested_lease;
1713 t2 = t1 + (t1 / 2);
1714 putULong(addr.buffer->data + 16, t1);
1715 putULong(addr.buffer->data + 20, t2);
1717 log_debug("XMT: | X-- Request address %s.",
1718 piaddr(old_addr->address));
1719 log_debug("XMT: | | X-- Request "
1720 "preferred in +%u",
1721 (unsigned)t1);
1722 log_debug("XMT: | | X-- Request valid "
1723 "in +%u",
1724 (unsigned)t2);
1726 append_option(&ia, &dhcpv6_universe,
1727 iaaddr_option,
1728 &addr);
1730 data_string_forget(&addr, MDL);
1734 append_option(&ds, &dhcpv6_universe, ia_ta_option, &ia);
1735 data_string_forget(&ia, MDL);
1738 /* Append IA_PD. */
1739 for (i = 0; i < wanted_ia_pd; i++) {
1741 * XXX: maybe the IA_PD('s) should be put into the sent_options
1742 * cache. They'd have to be pulled down as they also contain
1743 * different option caches in the same universe...
1745 memset(&ia, 0, sizeof(ia));
1746 if (!buffer_allocate(&ia.buffer, 12, MDL)) {
1747 log_error("Unable to allocate memory for IA_PD.");
1748 data_string_forget(&ds, MDL);
1749 return;
1751 ia.data = ia.buffer->data;
1752 ia.len = 12;
1755 * A simple IAID is the last 4 bytes
1756 * of the hardware address.
1758 if (client->interface->hw_address.hlen > 4) {
1759 idx = client->interface->hw_address.hlen - 4;
1760 len = 4;
1761 } else {
1762 idx = 0;
1763 len = client->interface->hw_address.hlen;
1765 memcpy(ia.buffer->data,
1766 client->interface->hw_address.hbuf + idx,
1767 len);
1768 if (i)
1769 ia.buffer->data[3] += i;
1771 t1 = client->config->requested_lease / 2;
1772 t2 = t1 + (t1 / 2);
1773 putULong(ia.buffer->data + 4, t1);
1774 putULong(ia.buffer->data + 8, t2);
1776 log_debug("XMT: X-- IA_PD %s",
1777 print_hex_1(4, ia.buffer->data, 55));
1778 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1);
1779 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2);
1781 if ((client->active_lease != NULL) &&
1782 ((old_ia = find_ia(client->active_lease->bindings,
1783 D6O_IA_PD,
1784 (char *)ia.buffer->data)) != NULL)) {
1786 * For each prefix in the old IA_PD,
1787 * request a binding.
1789 memset(&addr, 0, sizeof(addr));
1790 for (old_addr = old_ia->addrs ; old_addr != NULL ;
1791 old_addr = old_addr->next) {
1792 if (old_addr->address.len != 16) {
1793 log_error("Invalid IPv6 prefix, "
1794 "Ignoring. (%s:%d)",
1795 MDL);
1796 continue;
1799 if (!buffer_allocate(&addr.buffer, 25, MDL)) {
1800 log_error("Unable to allocate memory "
1801 "for IAPREFIX.");
1802 data_string_forget(&ia, MDL);
1803 data_string_forget(&ds, MDL);
1804 return;
1806 addr.data = addr.buffer->data;
1807 addr.len = 25;
1809 t1 = client->config->requested_lease;
1810 t2 = t1 + (t1 / 2);
1811 putULong(addr.buffer->data, t1);
1812 putULong(addr.buffer->data + 4, t2);
1814 putUChar(addr.buffer->data + 8,
1815 old_addr->plen);
1816 memcpy(addr.buffer->data + 9,
1817 old_addr->address.iabuf,
1818 16);
1820 log_debug("XMT: | X-- Request prefix %s/%u.",
1821 piaddr(old_addr->address),
1822 (unsigned) old_addr->plen);
1823 log_debug("XMT: | | X-- Request "
1824 "preferred in +%u",
1825 (unsigned)t1);
1826 log_debug("XMT: | | X-- Request valid "
1827 "in +%u",
1828 (unsigned)t2);
1830 append_option(&ia, &dhcpv6_universe,
1831 iaprefix_option,
1832 &addr);
1834 data_string_forget(&addr, MDL);
1838 append_option(&ds, &dhcpv6_universe, ia_pd_option, &ia);
1839 data_string_forget(&ia, MDL);
1842 /* Transmit and wait. */
1844 log_info("XMT: Solicit on %s, interval %ld0ms.",
1845 client->name ? client->name : client->interface->name,
1846 (long int)client->RT);
1848 send_ret = send_packet6(client->interface,
1849 ds.data, ds.len, &DHCPv6DestAddr);
1850 if (send_ret != ds.len) {
1851 log_error("dhc6: send_packet6() sent %d of %d bytes",
1852 send_ret, ds.len);
1855 data_string_forget(&ds, MDL);
1857 /* Wait RT */
1858 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
1859 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
1860 if (tv.tv_usec >= 1000000) {
1861 tv.tv_sec += 1;
1862 tv.tv_usec -= 1000000;
1864 add_timeout(&tv, do_init6, client, NULL, NULL);
1866 dhc6_retrans_advance(client);
1869 /* do_info_request6() marshals and transmits an information-request. */
1870 void
1871 do_info_request6(void *input)
1873 struct client_state *client;
1874 struct data_string ds;
1875 struct timeval tv;
1876 int send_ret;
1878 client = input;
1880 switch(check_timing6(client, DHCPV6_INFORMATION_REQUEST,
1881 "Info-Request", NULL, &ds)) {
1882 case CHK_TIM_MRC_EXCEEDED:
1883 case CHK_TIM_ALLOC_FAILURE:
1884 return;
1885 case CHK_TIM_MRD_EXCEEDED:
1886 exit(2);
1887 case CHK_TIM_SUCCESS:
1888 break;
1891 /* Fetch any configured 'sent' options (includes DUID) in wire format.
1893 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
1894 NULL, client->sent_options, &global_scope,
1895 &dhcpv6_universe);
1897 /* Transmit and wait. */
1899 log_info("XMT: Info-Request on %s, interval %ld0ms.",
1900 client->name ? client->name : client->interface->name,
1901 (long int)client->RT);
1903 send_ret = send_packet6(client->interface,
1904 ds.data, ds.len, &DHCPv6DestAddr);
1905 if (send_ret != ds.len) {
1906 log_error("dhc6: send_packet6() sent %d of %d bytes",
1907 send_ret, ds.len);
1910 data_string_forget(&ds, MDL);
1912 /* Wait RT */
1913 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
1914 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
1915 if (tv.tv_usec >= 1000000) {
1916 tv.tv_sec += 1;
1917 tv.tv_usec -= 1000000;
1919 add_timeout(&tv, do_info_request6, client, NULL, NULL);
1921 dhc6_retrans_advance(client);
1924 /* do_confirm6() creates a Confirm packet and transmits it. This function
1925 * is called on every timeout to (re)transmit.
1927 void
1928 do_confirm6(void *input)
1930 struct client_state *client;
1931 struct data_string ds;
1932 int send_ret;
1933 struct timeval tv;
1935 client = input;
1937 if (client->active_lease == NULL)
1938 log_fatal("Impossible condition at %s:%d.", MDL);
1940 /* In section 17.1.3, it is said:
1942 * If the client receives no responses before the message
1943 * transmission process terminates, as described in section 14,
1944 * the client SHOULD continue to use any IP addresses, using the
1945 * last known lifetimes for those addresses, and SHOULD continue
1946 * to use any other previously obtained configuration parameters.
1948 * So if confirm times out, we go active.
1950 * XXX: Should we reduce all IA's t1 to 0, so that we renew and
1951 * stick there until we get a reply?
1954 switch(check_timing6(client, DHCPV6_CONFIRM, "Confirm",
1955 client->active_lease, &ds)) {
1956 case CHK_TIM_MRC_EXCEEDED:
1957 case CHK_TIM_MRD_EXCEEDED:
1958 start_bound(client);
1959 return;
1960 case CHK_TIM_ALLOC_FAILURE:
1961 return;
1962 case CHK_TIM_SUCCESS:
1963 break;
1966 /* Fetch any configured 'sent' options (includes DUID') in wire format.
1968 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
1969 client->sent_options, &global_scope,
1970 &dhcpv6_universe);
1972 /* Append IA's. */
1973 if (wanted_ia_na &&
1974 dhc6_add_ia_na(client, &ds, client->active_lease,
1975 DHCPV6_CONFIRM) != ISC_R_SUCCESS) {
1976 data_string_forget(&ds, MDL);
1977 return;
1979 if (wanted_ia_ta &&
1980 dhc6_add_ia_ta(client, &ds, client->active_lease,
1981 DHCPV6_CONFIRM) != ISC_R_SUCCESS) {
1982 data_string_forget(&ds, MDL);
1983 return;
1986 /* Transmit and wait. */
1988 log_info("XMT: Confirm on %s, interval %ld0ms.",
1989 client->name ? client->name : client->interface->name,
1990 (long int)client->RT);
1992 send_ret = send_packet6(client->interface, ds.data, ds.len,
1993 &DHCPv6DestAddr);
1994 if (send_ret != ds.len) {
1995 log_error("dhc6: sendpacket6() sent %d of %d bytes",
1996 send_ret, ds.len);
1999 data_string_forget(&ds, MDL);
2001 /* Wait RT */
2002 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
2003 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
2004 if (tv.tv_usec >= 1000000) {
2005 tv.tv_sec += 1;
2006 tv.tv_usec -= 1000000;
2008 add_timeout(&tv, do_confirm6, client, NULL, NULL);
2010 dhc6_retrans_advance(client);
2014 * Release addresses.
2016 void
2017 start_release6(struct client_state *client)
2019 /* Cancel any pending transmissions */
2020 cancel_timeout(do_confirm6, client);
2021 cancel_timeout(do_select6, client);
2022 cancel_timeout(do_refresh6, client);
2023 cancel_timeout(do_release6, client);
2024 client->state = S_STOPPED;
2027 * It is written: "The client MUST NOT use any of the addresses it
2028 * is releasing as the source address in the Release message or in
2029 * any subsequently transmitted message." So unconfigure now.
2031 unconfigure6(client, "RELEASE6");
2033 /* Note this in the lease file. */
2034 if (client->active_lease == NULL)
2035 return;
2036 client->active_lease->released = ISC_TRUE;
2037 write_client6_lease(client, client->active_lease, 0, 1);
2039 /* Set timers per RFC3315 section 18.1.6. */
2040 client->IRT = REL_TIMEOUT * 100;
2041 client->MRT = 0;
2042 client->MRC = REL_MAX_RC;
2043 client->MRD = 0;
2045 dhc6_retrans_init(client);
2046 client->v6_handler = reply_handler;
2048 do_release6(client);
2051 * do_release6() creates a Release packet and transmits it.
2053 static void
2054 do_release6(void *input)
2056 struct client_state *client;
2057 struct data_string ds;
2058 int send_ret;
2059 struct timeval tv;
2061 client = input;
2063 if ((client->active_lease == NULL) || !active_prefix(client))
2064 return;
2066 switch(check_timing6(client, DHCPV6_RELEASE, "Release",
2067 client->active_lease, &ds)) {
2068 case CHK_TIM_MRC_EXCEEDED:
2069 case CHK_TIM_ALLOC_FAILURE:
2070 case CHK_TIM_MRD_EXCEEDED:
2071 goto release_done;
2072 case CHK_TIM_SUCCESS:
2073 break;
2077 * Don't use unicast as we don't know if we still have an
2078 * available address with enough scope.
2081 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
2082 client->sent_options, &global_scope,
2083 &dhcpv6_universe);
2085 /* Append IA's (but don't release temporary addresses). */
2086 if (wanted_ia_na &&
2087 dhc6_add_ia_na(client, &ds, client->active_lease,
2088 DHCPV6_RELEASE) != ISC_R_SUCCESS) {
2089 data_string_forget(&ds, MDL);
2090 goto release_done;
2092 if (wanted_ia_pd &&
2093 dhc6_add_ia_pd(client, &ds, client->active_lease,
2094 DHCPV6_RELEASE) != ISC_R_SUCCESS) {
2095 data_string_forget(&ds, MDL);
2096 goto release_done;
2099 /* Transmit and wait. */
2100 log_info("XMT: Release on %s, interval %ld0ms.",
2101 client->name ? client->name : client->interface->name,
2102 (long int)client->RT);
2104 send_ret = send_packet6(client->interface, ds.data, ds.len,
2105 &DHCPv6DestAddr);
2106 if (send_ret != ds.len) {
2107 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2108 send_ret, ds.len);
2111 data_string_forget(&ds, MDL);
2113 /* Wait RT */
2114 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
2115 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
2116 if (tv.tv_usec >= 1000000) {
2117 tv.tv_sec += 1;
2118 tv.tv_usec -= 1000000;
2120 add_timeout(&tv, do_release6, client, NULL, NULL);
2121 dhc6_retrans_advance(client);
2122 return;
2124 release_done:
2125 dhc6_lease_destroy(&client->active_lease, MDL);
2126 client->active_lease = NULL;
2127 if (stopping_finished())
2128 exit(0);
2131 /* status_log() just puts a status code into displayable form and logs it
2132 * to info level.
2134 static void
2135 status_log(int code, const char *scope, const char *additional, int len)
2137 const char *msg = NULL;
2139 switch(code) {
2140 case STATUS_Success:
2141 msg = "Success";
2142 break;
2144 case STATUS_UnspecFail:
2145 msg = "UnspecFail";
2146 break;
2148 case STATUS_NoAddrsAvail:
2149 msg = "NoAddrsAvail";
2150 break;
2152 case STATUS_NoBinding:
2153 msg = "NoBinding";
2154 break;
2156 case STATUS_NotOnLink:
2157 msg = "NotOnLink";
2158 break;
2160 case STATUS_UseMulticast:
2161 msg = "UseMulticast";
2162 break;
2164 case STATUS_NoPrefixAvail:
2165 msg = "NoPrefixAvail";
2166 break;
2168 default:
2169 msg = "UNKNOWN";
2170 break;
2173 if (len > 0)
2174 log_info("%s status code %s: %s", scope, msg,
2175 print_hex_1(len,
2176 (const unsigned char *)additional, 50));
2177 else
2178 log_info("%s status code %s.", scope, msg);
2181 /* Acquire a status code.
2183 static isc_result_t
2184 dhc6_get_status_code(struct option_state *options, unsigned *code,
2185 struct data_string *msg)
2187 struct option_cache *oc;
2188 struct data_string ds;
2189 isc_result_t rval = ISC_R_SUCCESS;
2191 if ((options == NULL) || (code == NULL))
2192 return DHCP_R_INVALIDARG;
2194 if ((msg != NULL) && (msg->len != 0))
2195 return DHCP_R_INVALIDARG;
2197 memset(&ds, 0, sizeof(ds));
2199 /* Assume success if there is no option. */
2200 *code = STATUS_Success;
2202 oc = lookup_option(&dhcpv6_universe, options, D6O_STATUS_CODE);
2203 if ((oc != NULL) &&
2204 evaluate_option_cache(&ds, NULL, NULL, NULL, options,
2205 NULL, &global_scope, oc, MDL)) {
2206 if (ds.len < 2) {
2207 log_error("Invalid status code length %d.", ds.len);
2208 rval = DHCP_R_FORMERR;
2209 } else
2210 *code = getUShort(ds.data);
2212 if ((msg != NULL) && (ds.len > 2)) {
2213 data_string_copy(msg, &ds, MDL);
2214 msg->data += 2;
2215 msg->len -= 2;
2218 data_string_forget(&ds, MDL);
2219 return rval;
2222 return ISC_R_NOTFOUND;
2225 /* Look at status codes in an advertise, and reform the return value.
2227 static isc_result_t
2228 dhc6_check_status(isc_result_t rval, struct option_state *options,
2229 const char *scope, unsigned *code)
2231 struct data_string msg;
2232 isc_result_t status;
2234 if ((scope == NULL) || (code == NULL))
2235 return DHCP_R_INVALIDARG;
2237 /* If we don't find a code, we assume success. */
2238 *code = STATUS_Success;
2240 /* If there is no options cache, then there is no code. */
2241 if (options != NULL) {
2242 memset(&msg, 0, sizeof(msg));
2243 status = dhc6_get_status_code(options, code, &msg);
2245 if (status == ISC_R_SUCCESS) {
2246 status_log(*code, scope, (char *)msg.data, msg.len);
2247 data_string_forget(&msg, MDL);
2249 if (*code != STATUS_Success)
2250 rval = ISC_R_FAILURE;
2252 } else if (status != ISC_R_NOTFOUND)
2253 rval = status;
2256 return rval;
2259 /* Look in the packet, any IA's, and any IAADDR's within those IA's to find
2260 * status code options that are not SUCCESS.
2262 static isc_result_t
2263 dhc6_check_advertise(struct dhc6_lease *lease)
2265 struct dhc6_ia *ia;
2266 struct dhc6_addr *addr;
2267 isc_result_t rval = ISC_R_SUCCESS;
2268 int have_addrs = ISC_FALSE;
2269 unsigned code;
2270 const char *scope;
2272 rval = dhc6_check_status(rval, lease->options, "message", &code);
2274 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
2275 switch (ia->ia_type) {
2276 case D6O_IA_NA:
2277 scope = "IA_NA";
2278 break;
2279 case D6O_IA_TA:
2280 scope = "IA_TA";
2281 break;
2282 case D6O_IA_PD:
2283 scope = "IA_PD";
2284 break;
2285 default:
2286 log_error("dhc6_check_advertise: no type.");
2287 return ISC_R_FAILURE;
2289 rval = dhc6_check_status(rval, ia->options, scope, &code);
2291 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
2292 if (ia->ia_type != D6O_IA_PD)
2293 scope = "IAADDR";
2294 else
2295 scope = "IAPREFIX";
2296 rval = dhc6_check_status(rval, addr->options,
2297 scope, &code);
2298 have_addrs = ISC_TRUE;
2302 if (have_addrs != ISC_TRUE)
2303 rval = ISC_R_ADDRNOTAVAIL;
2305 return rval;
2308 /* status code <-> action matrix for the client in INIT state
2309 * (rapid/commit). Returns always false as no action is defined.
2311 static isc_boolean_t
2312 dhc6_init_action(struct client_state *client, isc_result_t *rvalp,
2313 unsigned code)
2315 if (rvalp == NULL)
2316 log_fatal("Impossible condition at %s:%d.", MDL);
2318 if (client == NULL) {
2319 *rvalp = DHCP_R_INVALIDARG;
2320 return ISC_FALSE;
2323 if (*rvalp == ISC_R_SUCCESS)
2324 return ISC_FALSE;
2326 /* No possible action in any case... */
2327 return ISC_FALSE;
2330 /* status code <-> action matrix for the client in SELECT state
2331 * (request/reply). Returns true if action was taken (and the
2332 * packet should be ignored), or false if no action was taken.
2334 static isc_boolean_t
2335 dhc6_select_action(struct client_state *client, isc_result_t *rvalp,
2336 unsigned code)
2338 struct dhc6_lease *lease;
2339 isc_result_t rval;
2341 if (rvalp == NULL)
2342 log_fatal("Impossible condition at %s:%d.", MDL);
2344 if (client == NULL) {
2345 *rvalp = DHCP_R_INVALIDARG;
2346 return ISC_FALSE;
2348 rval = *rvalp;
2350 if (rval == ISC_R_SUCCESS)
2351 return ISC_FALSE;
2353 switch (code) {
2354 /* We may have an earlier failure status code (so no
2355 * success rval), and a success code now. This
2356 * doesn't upgrade the rval to success, but it does
2357 * mean we take no action here.
2359 case STATUS_Success:
2360 /* Gimpy server, or possibly an attacker. */
2361 case STATUS_NoBinding:
2362 case STATUS_UseMulticast:
2363 /* Take no action. */
2364 return ISC_FALSE;
2366 /* If the server can't deal with us, either try the
2367 * next advertised server, or continue retrying if there
2368 * weren't any.
2370 default:
2371 case STATUS_UnspecFail:
2372 if (client->advertised_leases != NULL) {
2373 dhc6_lease_destroy(&client->selected_lease, MDL);
2374 client->selected_lease = NULL;
2376 start_selecting6(client);
2378 break;
2379 } else /* Take no action - continue to retry. */
2380 return ISC_FALSE;
2382 /* If the server has no addresses, try other servers if
2383 * we got some, otherwise go to INIT to hope for more
2384 * servers.
2386 case STATUS_NoAddrsAvail:
2387 case STATUS_NoPrefixAvail:
2388 if (client->state == S_REBOOTING)
2389 return ISC_FALSE;
2391 if (client->selected_lease == NULL)
2392 log_fatal("Impossible case at %s:%d.", MDL);
2394 dhc6_lease_destroy(&client->selected_lease, MDL);
2395 client->selected_lease = NULL;
2397 if (client->advertised_leases != NULL)
2398 start_selecting6(client);
2399 else
2400 start_init6(client);
2402 break;
2404 /* If we got a NotOnLink from a Confirm, then we're not
2405 * on link. Kill the old-active binding and start over.
2407 * If we got a NotOnLink from our Request, something weird
2408 * happened. Start over from scratch anyway.
2410 case STATUS_NotOnLink:
2411 if (client->state == S_REBOOTING) {
2412 if (client->active_lease == NULL)
2413 log_fatal("Impossible case at %s:%d.", MDL);
2415 dhc6_lease_destroy(&client->active_lease, MDL);
2416 } else {
2417 if (client->selected_lease == NULL)
2418 log_fatal("Impossible case at %s:%d.", MDL);
2420 dhc6_lease_destroy(&client->selected_lease, MDL);
2421 client->selected_lease = NULL;
2423 while (client->advertised_leases != NULL) {
2424 lease = client->advertised_leases;
2425 client->advertised_leases = lease->next;
2427 dhc6_lease_destroy(&lease, MDL);
2431 start_init6(client);
2432 break;
2435 return ISC_TRUE;
2438 static void
2439 dhc6_withdraw_lease(struct client_state *client)
2441 struct dhc6_ia *ia;
2442 struct dhc6_addr *addr;
2444 if ((client == NULL) || (client->active_lease == NULL))
2445 return;
2447 for (ia = client->active_lease->bindings ; ia != NULL ;
2448 ia = ia->next) {
2449 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
2450 addr->max_life = addr->preferred_life = 0;
2454 /* Perform expiry. */
2455 do_expire(client);
2458 /* status code <-> action matrix for the client in BOUND state
2459 * (request/reply). Returns true if action was taken (and the
2460 * packet should be ignored), or false if no action was taken.
2462 static isc_boolean_t
2463 dhc6_reply_action(struct client_state *client, isc_result_t *rvalp,
2464 unsigned code)
2466 isc_result_t rval;
2468 if (rvalp == NULL)
2469 log_fatal("Impossible condition at %s:%d.", MDL);
2471 if (client == NULL) {
2472 *rvalp = DHCP_R_INVALIDARG;
2473 return ISC_FALSE;
2475 rval = *rvalp;
2477 if (rval == ISC_R_SUCCESS)
2478 return ISC_FALSE;
2480 switch (code) {
2481 /* It's possible an earlier status code set rval to a failure
2482 * code, and we've encountered a later success.
2484 case STATUS_Success:
2485 /* In "refreshes" (where we get replies), we probably
2486 * still have a valid lease. So "take no action" and
2487 * the upper levels will keep retrying until the lease
2488 * expires (or we rebind).
2490 case STATUS_UnspecFail:
2491 /* For unknown codes...it's a soft (retryable) error. */
2492 default:
2493 return ISC_FALSE;
2495 /* The server is telling us to use a multicast address, so
2496 * we have to delete the unicast option from the active
2497 * lease, then allow retransmission to occur normally.
2498 * (XXX: It might be preferable in this case to retransmit
2499 * sooner than the current interval, but for now we don't.)
2501 case STATUS_UseMulticast:
2502 if (client->active_lease != NULL)
2503 delete_option(&dhcp_universe,
2504 client->active_lease->options,
2505 D6O_UNICAST);
2506 return ISC_FALSE;
2508 /* "When the client receives a NotOnLink status from the
2509 * server in response to a Request, the client can either
2510 * re-issue the Request without specifying any addresses
2511 * or restart the DHCP server discovery process."
2513 * This is strange. If competing server evaluation is
2514 * useful (and therefore in the protocol), then why would
2515 * a client's first reaction be to request from the same
2516 * server on a different link? Surely you'd want to
2517 * re-evaluate your server selection.
2519 * Well, I guess that's the answer.
2521 case STATUS_NotOnLink:
2522 /* In this case, we need to rescind all current active
2523 * bindings (just 'expire' them all normally, if early).
2524 * They're no use to us on the wrong link. Then head back
2525 * to init, redo server selection and get new addresses.
2527 dhc6_withdraw_lease(client);
2528 break;
2530 /* "If the status code is NoAddrsAvail, the client has
2531 * received no usable addresses in the IA and may choose
2532 * to try obtaining addresses for the IA from another
2533 * server."
2535 case STATUS_NoAddrsAvail:
2536 case STATUS_NoPrefixAvail:
2537 /* Head back to init, keeping any active bindings (!). */
2538 start_init6(client);
2539 break;
2541 /* - sends a Request message if the IA contained a Status
2542 * Code option with the NoBinding status (and does not
2543 * send any additional Renew/Rebind messages)
2545 case STATUS_NoBinding:
2546 if (client->advertised_leases != NULL)
2547 log_fatal("Impossible condition at %s:%d.", MDL);
2549 client->advertised_leases =
2550 dhc6_dup_lease(client->active_lease, MDL);
2551 start_selecting6(client);
2552 break;
2555 return ISC_TRUE;
2558 /* status code <-> action matrix for the client in STOPPED state
2559 * (release/decline). Returns true if action was taken (and the
2560 * packet should be ignored), or false if no action was taken.
2561 * NoBinding is translated into Success.
2563 static isc_boolean_t
2564 dhc6_stop_action(struct client_state *client, isc_result_t *rvalp,
2565 unsigned code)
2567 isc_result_t rval;
2569 if (rvalp == NULL)
2570 log_fatal("Impossible condition at %s:%d.", MDL);
2572 if (client == NULL) {
2573 *rvalp = DHCP_R_INVALIDARG;
2574 return ISC_FALSE;
2576 rval = *rvalp;
2578 if (rval == ISC_R_SUCCESS)
2579 return ISC_FALSE;
2581 switch (code) {
2582 /* It's possible an earlier status code set rval to a failure
2583 * code, and we've encountered a later success.
2585 case STATUS_Success:
2586 /* For unknown codes...it's a soft (retryable) error. */
2587 case STATUS_UnspecFail:
2588 default:
2589 return ISC_FALSE;
2591 /* NoBinding is not an error */
2592 case STATUS_NoBinding:
2593 if (rval == ISC_R_FAILURE)
2594 *rvalp = ISC_R_SUCCESS;
2595 return ISC_FALSE;
2597 /* Should not happen */
2598 case STATUS_NoAddrsAvail:
2599 case STATUS_NoPrefixAvail:
2600 break;
2602 /* Give up on it */
2603 case STATUS_NotOnLink:
2604 break;
2606 /* The server is telling us to use a multicast address, so
2607 * we have to delete the unicast option from the active
2608 * lease, then allow retransmission to occur normally.
2609 * (XXX: It might be preferable in this case to retransmit
2610 * sooner than the current interval, but for now we don't.)
2612 case STATUS_UseMulticast:
2613 if (client->active_lease != NULL)
2614 delete_option(&dhcp_universe,
2615 client->active_lease->options,
2616 D6O_UNICAST);
2617 return ISC_FALSE;
2620 return ISC_TRUE;
2623 /* Look at a new and old lease, and make sure the new information is not
2624 * losing us any state.
2626 static isc_result_t
2627 dhc6_check_reply(struct client_state *client, struct dhc6_lease *new)
2629 isc_boolean_t (*action)(struct client_state *,
2630 isc_result_t *, unsigned);
2631 struct dhc6_ia *ia;
2632 struct dhc6_addr *addr;
2633 isc_result_t rval = ISC_R_SUCCESS;
2634 unsigned code;
2635 const char *scope;
2636 int nscore, sscore;
2638 if ((client == NULL) || (new == NULL))
2639 return DHCP_R_INVALIDARG;
2641 switch (client->state) {
2642 case S_INIT:
2643 action = dhc6_init_action;
2644 break;
2646 case S_SELECTING:
2647 case S_REBOOTING:
2648 action = dhc6_select_action;
2649 break;
2651 case S_RENEWING:
2652 case S_REBINDING:
2653 action = dhc6_reply_action;
2654 break;
2656 case S_STOPPED:
2657 action = dhc6_stop_action;
2658 break;
2660 default:
2661 log_fatal("Impossible condition at %s:%d.", MDL);
2662 return ISC_R_CANCELED;
2665 /* If there is a code to extract, and if there is some
2666 * action to take based on that code, then take the action
2667 * and do not continue.
2669 rval = dhc6_check_status(rval, new->options, "message", &code);
2670 if (action(client, &rval, code))
2671 return ISC_R_CANCELED;
2673 for (ia = new->bindings ; ia != NULL ; ia = ia->next) {
2674 switch (ia->ia_type) {
2675 case D6O_IA_NA:
2676 scope = "IA_NA";
2677 break;
2678 case D6O_IA_TA:
2679 scope = "IA_TA";
2680 break;
2681 case D6O_IA_PD:
2682 scope = "IA_PD";
2683 break;
2684 default:
2685 log_error("dhc6_check_reply: no type.");
2686 return DHCP_R_INVALIDARG;
2688 rval = dhc6_check_status(rval, ia->options,
2689 scope, &code);
2690 if (action(client, &rval, code))
2691 return ISC_R_CANCELED;
2693 for (addr = ia->addrs ; addr != NULL ;
2694 addr = addr->next) {
2695 if (ia->ia_type != D6O_IA_PD)
2696 scope = "IAADDR";
2697 else
2698 scope = "IAPREFIX";
2699 rval = dhc6_check_status(rval, addr->options,
2700 scope, &code);
2701 if (action(client, &rval, code))
2702 return ISC_R_CANCELED;
2706 /* A Confirm->Reply is unsuitable for comparison to the old lease. */
2707 if (client->state == S_REBOOTING)
2708 return rval;
2710 /* No old lease in rapid-commit. */
2711 if (client->state == S_INIT)
2712 return rval;
2714 switch (client->state) {
2715 case S_SELECTING:
2716 /* Compare the new lease with the selected lease to make
2717 * sure there is no risky business.
2719 nscore = dhc6_score_lease(client, new);
2720 sscore = dhc6_score_lease(client, client->selected_lease);
2721 if ((client->advertised_leases != NULL) &&
2722 (nscore < (sscore / 2))) {
2723 /* XXX: An attacker might reply this way to make
2724 * XXX: sure we latch onto their configuration.
2725 * XXX: We might want to ignore the packet and
2726 * XXX: schedule re-selection at the next timeout?
2728 log_error("PRC: BAIT AND SWITCH detected. Score of "
2729 "supplied lease (%d) is substantially "
2730 "smaller than the advertised score (%d). "
2731 "Trying other servers.",
2732 nscore, sscore);
2734 dhc6_lease_destroy(&client->selected_lease, MDL);
2735 client->selected_lease = NULL;
2737 start_selecting6(client);
2739 return ISC_R_CANCELED;
2741 break;
2743 case S_RENEWING:
2744 case S_REBINDING:
2745 /* This leaves one RFC3315 status check unimplemented:
2747 * - sends a Renew/Rebind if the IA is not in the Reply
2748 * message
2750 * We rely on the scheduling system to note that the IA has
2751 * not left Renewal/Rebinding/whatever since it still carries
2752 * old times from the last successful binding. So this is
2753 * implemented actually, just not explicitly.
2755 break;
2757 case S_STOPPED:
2758 /* Nothing critical to do at this stage. */
2759 break;
2761 default:
2762 log_fatal("REALLY impossible condition at %s:%d.", MDL);
2763 return ISC_R_CANCELED;
2766 return rval;
2769 /* While in init state, we only collect advertisements. If there happens
2770 * to be an advertisement with a preference option of 255, that's an
2771 * automatic exit. Otherwise, we collect advertisements until our timeout
2772 * expires (client->RT).
2774 void
2775 init_handler(struct packet *packet, struct client_state *client)
2777 struct dhc6_lease *lease;
2779 /* In INIT state, we send solicits, we only expect to get
2780 * advertises (rapid commit has its own handler).
2782 if (packet->dhcpv6_msg_type != DHCPV6_ADVERTISE)
2783 return;
2785 /* RFC3315 section 15.3 validation (same as 15.10 since we
2786 * always include a client id).
2788 if (!valid_reply(packet, client)) {
2789 log_error("Invalid Advertise - rejecting.");
2790 return;
2793 lease = dhc6_leaseify(packet);
2795 if (dhc6_check_advertise(lease) != ISC_R_SUCCESS) {
2796 log_debug("PRC: Lease failed to satisfy.");
2797 dhc6_lease_destroy(&lease, MDL);
2798 return;
2801 insert_lease(&client->advertised_leases, lease);
2803 /* According to RFC3315 section 17.1.2, the client MUST wait for
2804 * the first RT before selecting a lease. But on the 400th RT,
2805 * we dont' want to wait the full timeout if we finally get an
2806 * advertise. We could probably wait a second, but ohwell,
2807 * RFC3315 doesn't say so.
2809 * If the lease is highest possible preference, 255, RFC3315 claims
2810 * we should continue immediately even on the first RT. We probably
2811 * should not if the advertise contains less than one IA and address.
2813 if ((client->txcount > 1) ||
2814 ((lease->pref == 255) &&
2815 (dhc6_score_lease(client, lease) > 150))) {
2816 log_debug("RCV: Advertisement immediately selected.");
2817 cancel_timeout(do_init6, client);
2818 start_selecting6(client);
2819 } else
2820 log_debug("RCV: Advertisement recorded.");
2823 /* info_request_handler() accepts a Reply to an Info-request.
2825 void
2826 info_request_handler(struct packet *packet, struct client_state *client)
2828 isc_result_t check_status;
2829 unsigned code;
2831 if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
2832 return;
2834 /* RFC3315 section 15.10 validation (same as 15.3 since we
2835 * always include a client id).
2837 if (!valid_reply(packet, client)) {
2838 log_error("Invalid Reply - rejecting.");
2839 return;
2842 check_status = dhc6_check_status(ISC_R_SUCCESS, packet->options,
2843 "message", &code);
2844 if (check_status != ISC_R_SUCCESS) {
2845 /* If no action was taken, but there is an error, then
2846 * we wait for a retransmission.
2848 if (check_status != ISC_R_CANCELED)
2849 return;
2852 /* We're done retransmitting at this point. */
2853 cancel_timeout(do_info_request6, client);
2855 /* Action was taken, so now that we've torn down our scheduled
2856 * retransmissions, return.
2858 if (check_status == ISC_R_CANCELED)
2859 return;
2861 /* Cleanup if a previous attempt to go bound failed. */
2862 if (client->old_lease != NULL) {
2863 dhc6_lease_destroy(&client->old_lease, MDL);
2864 client->old_lease = NULL;
2867 /* Cache options in the active_lease. */
2868 if (client->active_lease != NULL)
2869 client->old_lease = client->active_lease;
2870 client->active_lease = dmalloc(sizeof(struct dhc6_lease), MDL);
2871 if (client->active_lease == NULL)
2872 log_fatal("Out of memory for v6 lease structure.");
2873 option_state_reference(&client->active_lease->options,
2874 packet->options, MDL);
2876 start_informed(client);
2879 /* Specific version of init_handler() for rapid-commit.
2881 void
2882 rapid_commit_handler(struct packet *packet, struct client_state *client)
2884 struct dhc6_lease *lease;
2885 isc_result_t check_status;
2887 /* On ADVERTISE just fall back to the init_handler().
2889 if (packet->dhcpv6_msg_type == DHCPV6_ADVERTISE) {
2890 init_handler(packet, client);
2891 return;
2892 } else if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
2893 return;
2895 /* RFC3315 section 15.10 validation (same as 15.3 since we
2896 * always include a client id).
2898 if (!valid_reply(packet, client)) {
2899 log_error("Invalid Reply - rejecting.");
2900 return;
2903 /* A rapid-commit option MUST be here. */
2904 if (lookup_option(&dhcpv6_universe, packet->options,
2905 D6O_RAPID_COMMIT) == 0) {
2906 log_error("Reply without Rapid-Commit - rejecting.");
2907 return;
2910 lease = dhc6_leaseify(packet);
2912 /* This is an out of memory condition...hopefully a temporary
2913 * problem. Returning now makes us try to retransmit later.
2915 if (lease == NULL)
2916 return;
2918 check_status = dhc6_check_reply(client, lease);
2919 if (check_status != ISC_R_SUCCESS) {
2920 dhc6_lease_destroy(&lease, MDL);
2921 return;
2924 /* Jump to the selecting state. */
2925 cancel_timeout(do_init6, client);
2926 client->state = S_SELECTING;
2928 /* Merge any bindings in the active lease (if there is one) into
2929 * the new active lease.
2931 dhc6_merge_lease(client->active_lease, lease);
2933 /* Cleanup if a previous attempt to go bound failed. */
2934 if (client->old_lease != NULL) {
2935 dhc6_lease_destroy(&client->old_lease, MDL);
2936 client->old_lease = NULL;
2939 /* Make this lease active and BIND to it. */
2940 if (client->active_lease != NULL)
2941 client->old_lease = client->active_lease;
2942 client->active_lease = lease;
2944 /* We're done with the ADVERTISEd leases, if any. */
2945 while(client->advertised_leases != NULL) {
2946 lease = client->advertised_leases;
2947 client->advertised_leases = lease->next;
2949 dhc6_lease_destroy(&lease, MDL);
2952 start_bound(client);
2955 /* Find the 'best' lease in the cache of advertised leases (usually). From
2956 * RFC3315 Section 17.1.3:
2958 * Upon receipt of one or more valid Advertise messages, the client
2959 * selects one or more Advertise messages based upon the following
2960 * criteria.
2962 * - Those Advertise messages with the highest server preference value
2963 * are preferred over all other Advertise messages.
2965 * - Within a group of Advertise messages with the same server
2966 * preference value, a client MAY select those servers whose
2967 * Advertise messages advertise information of interest to the
2968 * client. For example, the client may choose a server that returned
2969 * an advertisement with configuration options of interest to the
2970 * client.
2972 * - The client MAY choose a less-preferred server if that server has a
2973 * better set of advertised parameters, such as the available
2974 * addresses advertised in IAs.
2976 * Note that the first and third contradict each other. The third should
2977 * probably be taken to mean that the client should prefer answers that
2978 * offer bindings, even if that violates the preference rule.
2980 * The above also isn't deterministic where there are ties. So the final
2981 * tiebreaker we add, if all other values are equal, is to compare the
2982 * server identifiers and to select the numerically lower one.
2984 static struct dhc6_lease *
2985 dhc6_best_lease(struct client_state *client, struct dhc6_lease **head)
2987 struct dhc6_lease **rpos, *rval, **candp, *cand;
2988 int cscore, rscore;
2990 if (head == NULL || *head == NULL)
2991 return NULL;
2993 rpos = head;
2994 rval = *rpos;
2995 rscore = dhc6_score_lease(client, rval);
2996 candp = &rval->next;
2997 cand = *candp;
2999 log_debug("PRC: Considering best lease.");
3000 log_debug("PRC: X-- Initial candidate %s (s: %d, p: %u).",
3001 print_hex_1(rval->server_id.len,
3002 rval->server_id.data, 48),
3003 rscore, (unsigned)rval->pref);
3005 for (; cand != NULL ; candp = &cand->next, cand = *candp) {
3006 cscore = dhc6_score_lease(client, cand);
3008 log_debug("PRC: X-- Candidate %s (s: %d, p: %u).",
3009 print_hex_1(cand->server_id.len,
3010 cand->server_id.data, 48),
3011 cscore, (unsigned)cand->pref);
3013 /* Above you'll find quoted RFC3315 Section 17.1.3.
3015 * The third clause tells us to give up on leases that
3016 * have no bindings even if their preference is better.
3017 * So where our 'selected' lease's score is less than 150
3018 * (1 ia + 1 addr), choose any candidate >= 150.
3020 * The first clause tells us to make preference the primary
3021 * deciding factor. So if it's lower, reject, if it's
3022 * higher, select.
3024 * The second clause tells us where the preference is
3025 * equal, we should use 'our judgement' of what we like
3026 * to see in an advertisement primarily.
3028 * But there can still be a tie. To make this deterministic,
3029 * we compare the server identifiers and select the binary
3030 * lowest.
3032 * Since server id's are unique in this list, there is
3033 * no further tie to break.
3035 if ((rscore < 150) && (cscore >= 150)) {
3036 log_debug("PRC: | X-- Selected, has bindings.");
3037 } else if (cand->pref < rval->pref) {
3038 log_debug("PRC: | X-- Rejected, lower preference.");
3039 continue;
3040 } else if (cand->pref > rval->pref) {
3041 log_debug("PRC: | X-- Selected, higher preference.");
3042 } else if (cscore > rscore) {
3043 log_debug("PRC: | X-- Selected, equal preference, "
3044 "higher score.");
3045 } else if (cscore < rscore) {
3046 log_debug("PRC: | X-- Rejected, equal preference, "
3047 "lower score.");
3048 continue;
3049 } else if ((cand->server_id.len < rval->server_id.len) ||
3050 ((cand->server_id.len == rval->server_id.len) &&
3051 (memcmp(cand->server_id.data,
3052 rval->server_id.data,
3053 cand->server_id.len) < 0))) {
3054 log_debug("PRC: | X-- Selected, equal preference, "
3055 "equal score, binary lesser server ID.");
3056 } else {
3057 log_debug("PRC: | X-- Rejected, equal preference, "
3058 "equal score, binary greater server ID.");
3059 continue;
3062 rpos = candp;
3063 rval = cand;
3064 rscore = cscore;
3067 /* Remove the selected lease from the chain. */
3068 *rpos = rval->next;
3070 return rval;
3073 /* Select a lease out of the advertised leases and setup state to try and
3074 * acquire that lease.
3076 void
3077 start_selecting6(struct client_state *client)
3079 struct dhc6_lease *lease;
3081 if (client->advertised_leases == NULL) {
3082 log_error("Can not enter DHCPv6 SELECTING state with no "
3083 "leases to select from!");
3084 return;
3087 log_debug("PRC: Selecting best advertised lease.");
3088 client->state = S_SELECTING;
3090 lease = dhc6_best_lease(client, &client->advertised_leases);
3092 if (lease == NULL)
3093 log_fatal("Impossible error at %s:%d.", MDL);
3095 client->selected_lease = lease;
3097 /* Set timers per RFC3315 section 18.1.1. */
3098 client->IRT = REQ_TIMEOUT * 100;
3099 client->MRT = REQ_MAX_RT * 100;
3100 client->MRC = REQ_MAX_RC;
3101 client->MRD = 0;
3103 dhc6_retrans_init(client);
3105 client->v6_handler = reply_handler;
3107 /* ("re")transmit the first packet. */
3108 do_select6(client);
3111 /* Transmit a Request to select a lease offered in Advertisements. In
3112 * the event of failure, either move on to the next-best advertised lease,
3113 * or head back to INIT state if there are none.
3115 void
3116 do_select6(void *input)
3118 struct client_state *client;
3119 struct dhc6_lease *lease;
3120 struct data_string ds;
3121 struct timeval tv;
3122 int send_ret;
3124 client = input;
3126 /* 'lease' is fewer characters to type. */
3127 lease = client->selected_lease;
3128 if (lease == NULL || lease->bindings == NULL) {
3129 log_error("Illegal to attempt selection without selecting "
3130 "a lease.");
3131 return;
3134 switch(check_timing6(client, DHCPV6_REQUEST, "Request", lease, &ds)) {
3135 case CHK_TIM_MRC_EXCEEDED:
3136 case CHK_TIM_MRD_EXCEEDED:
3137 log_debug("PRC: Lease %s failed.",
3138 print_hex_1(lease->server_id.len,
3139 lease->server_id.data, 56));
3141 /* Get rid of the lease that timed/counted out. */
3142 dhc6_lease_destroy(&lease, MDL);
3143 client->selected_lease = NULL;
3145 /* If there are more leases great. If not, get more. */
3146 if (client->advertised_leases != NULL)
3147 start_selecting6(client);
3148 else
3149 start_init6(client);
3150 return;
3151 case CHK_TIM_ALLOC_FAILURE:
3152 return;
3153 case CHK_TIM_SUCCESS:
3154 break;
3157 /* Now make a packet that looks suspiciously like the one we
3158 * got from the server. But different.
3160 * XXX: I guess IAID is supposed to be something the client
3161 * indicates and uses as a key to its internal state. It is
3162 * kind of odd to ask the server for IA's whose IAID the client
3163 * did not manufacture. We first need a formal dhclient.conf
3164 * construct for the iaid, then we can delve into this matter
3165 * more properly. In the time being, this will work.
3168 /* Fetch any configured 'sent' options (includes DUID) in wire format.
3170 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client,
3171 NULL, client->sent_options, &global_scope,
3172 &dhcpv6_universe);
3174 /* Now append any IA's, and within them any IAADDR/IAPREFIXs. */
3175 if (wanted_ia_na &&
3176 dhc6_add_ia_na(client, &ds, lease,
3177 DHCPV6_REQUEST) != ISC_R_SUCCESS) {
3178 data_string_forget(&ds, MDL);
3179 return;
3181 if (wanted_ia_ta &&
3182 dhc6_add_ia_ta(client, &ds, lease,
3183 DHCPV6_REQUEST) != ISC_R_SUCCESS) {
3184 data_string_forget(&ds, MDL);
3185 return;
3187 if (wanted_ia_pd &&
3188 dhc6_add_ia_pd(client, &ds, lease,
3189 DHCPV6_REQUEST) != ISC_R_SUCCESS) {
3190 data_string_forget(&ds, MDL);
3191 return;
3194 log_info("XMT: Request on %s, interval %ld0ms.",
3195 client->name ? client->name : client->interface->name,
3196 (long int)client->RT);
3198 send_ret = send_packet6(client->interface,
3199 ds.data, ds.len, &DHCPv6DestAddr);
3200 if (send_ret != ds.len) {
3201 log_error("dhc6: send_packet6() sent %d of %d bytes",
3202 send_ret, ds.len);
3205 data_string_forget(&ds, MDL);
3207 /* Wait RT */
3208 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
3209 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
3210 if (tv.tv_usec >= 1000000) {
3211 tv.tv_sec += 1;
3212 tv.tv_usec -= 1000000;
3214 add_timeout(&tv, do_select6, client, NULL, NULL);
3216 dhc6_retrans_advance(client);
3219 /* For each IA_NA in the lease, for each address in the IA_NA,
3220 * append that information onto the packet-so-far.
3222 static isc_result_t
3223 dhc6_add_ia_na(struct client_state *client, struct data_string *packet,
3224 struct dhc6_lease *lease, u_int8_t message)
3226 struct data_string iads;
3227 struct data_string addrds;
3228 struct dhc6_addr *addr;
3229 struct dhc6_ia *ia;
3230 isc_result_t rval = ISC_R_SUCCESS;
3231 TIME t1, t2;
3233 memset(&iads, 0, sizeof(iads));
3234 memset(&addrds, 0, sizeof(addrds));
3235 for (ia = lease->bindings;
3236 ia != NULL && rval == ISC_R_SUCCESS;
3237 ia = ia->next) {
3238 if (ia->ia_type != D6O_IA_NA)
3239 continue;
3241 if (!buffer_allocate(&iads.buffer, 12, MDL)) {
3242 log_error("Unable to allocate memory for IA_NA.");
3243 rval = ISC_R_NOMEMORY;
3244 break;
3247 /* Copy the IAID into the packet buffer. */
3248 memcpy(iads.buffer->data, ia->iaid, 4);
3249 iads.data = iads.buffer->data;
3250 iads.len = 12;
3252 switch (message) {
3253 case DHCPV6_REQUEST:
3254 case DHCPV6_RENEW:
3255 case DHCPV6_REBIND:
3257 t1 = client->config->requested_lease / 2;
3258 t2 = t1 + (t1 / 2);
3259 #if MAX_TIME > 0xffffffff
3260 if (t1 > 0xffffffff)
3261 t1 = 0xffffffff;
3262 if (t2 > 0xffffffff)
3263 t2 = 0xffffffff;
3264 #endif
3265 putULong(iads.buffer->data + 4, t1);
3266 putULong(iads.buffer->data + 8, t2);
3268 log_debug("XMT: X-- IA_NA %s",
3269 print_hex_1(4, iads.data, 59));
3270 log_debug("XMT: | X-- Requested renew +%u",
3271 (unsigned) t1);
3272 log_debug("XMT: | X-- Requested rebind +%u",
3273 (unsigned) t2);
3274 break;
3276 case DHCPV6_CONFIRM:
3277 case DHCPV6_RELEASE:
3278 case DHCPV6_DECLINE:
3279 /* Set t1 and t2 to zero; server will ignore them */
3280 memset(iads.buffer->data + 4, 0, 8);
3281 log_debug("XMT: X-- IA_NA %s",
3282 print_hex_1(4, iads.buffer->data, 55));
3284 break;
3286 default:
3287 log_fatal("Impossible condition at %s:%d.", MDL);
3290 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
3292 * Do not confirm expired addresses, do not request
3293 * expired addresses (but we keep them around for
3294 * solicit).
3296 if (addr->flags & DHC6_ADDR_EXPIRED)
3297 continue;
3299 if (addr->address.len != 16) {
3300 log_error("Illegal IPv6 address length (%d), "
3301 "ignoring. (%s:%d)",
3302 addr->address.len, MDL);
3303 continue;
3306 if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
3307 log_error("Unable to allocate memory for "
3308 "IAADDR.");
3309 rval = ISC_R_NOMEMORY;
3310 break;
3313 addrds.data = addrds.buffer->data;
3314 addrds.len = 24;
3316 /* Copy the address into the packet buffer. */
3317 memcpy(addrds.buffer->data, addr->address.iabuf, 16);
3319 /* Copy in additional information as appropriate */
3320 switch (message) {
3321 case DHCPV6_REQUEST:
3322 case DHCPV6_RENEW:
3323 case DHCPV6_REBIND:
3324 t1 = client->config->requested_lease;
3325 t2 = t1 + 300;
3326 putULong(addrds.buffer->data + 16, t1);
3327 putULong(addrds.buffer->data + 20, t2);
3329 log_debug("XMT: | | X-- IAADDR %s",
3330 piaddr(addr->address));
3331 log_debug("XMT: | | | X-- Preferred "
3332 "lifetime +%u", (unsigned)t1);
3333 log_debug("XMT: | | | X-- Max lifetime +%u",
3334 (unsigned)t2);
3336 break;
3338 case DHCPV6_CONFIRM:
3340 * Set preferred and max life to zero,
3341 * per 17.1.3.
3343 memset(addrds.buffer->data + 16, 0, 8);
3344 log_debug("XMT: | X-- Confirm Address %s",
3345 piaddr(addr->address));
3346 break;
3348 case DHCPV6_RELEASE:
3349 /* Preferred and max life are irrelevant */
3350 memset(addrds.buffer->data + 16, 0, 8);
3351 log_debug("XMT: | X-- Release Address %s",
3352 piaddr(addr->address));
3353 break;
3355 case DHCPV6_DECLINE:
3356 /* Preferred and max life are irrelevant */
3357 memset(addrds.buffer->data + 16, 0, 8);
3358 log_debug("XMT: | X-- Decline Address %s",
3359 piaddr(addr->address));
3360 break;
3362 default:
3363 log_fatal("Impossible condition at %s:%d.",
3364 MDL);
3367 append_option(&iads, &dhcpv6_universe, iaaddr_option,
3368 &addrds);
3369 data_string_forget(&addrds, MDL);
3373 * It doesn't make sense to make a request without an
3374 * address.
3376 if (ia->addrs == NULL) {
3377 log_debug("!!!: V IA_NA has no IAADDRs - removed.");
3378 rval = ISC_R_FAILURE;
3379 } else if (rval == ISC_R_SUCCESS) {
3380 log_debug("XMT: V IA_NA appended.");
3381 append_option(packet, &dhcpv6_universe, ia_na_option,
3382 &iads);
3385 data_string_forget(&iads, MDL);
3388 return rval;
3391 /* For each IA_TA in the lease, for each address in the IA_TA,
3392 * append that information onto the packet-so-far.
3394 static isc_result_t
3395 dhc6_add_ia_ta(struct client_state *client, struct data_string *packet,
3396 struct dhc6_lease *lease, u_int8_t message)
3398 struct data_string iads;
3399 struct data_string addrds;
3400 struct dhc6_addr *addr;
3401 struct dhc6_ia *ia;
3402 isc_result_t rval = ISC_R_SUCCESS;
3403 TIME t1, t2;
3405 memset(&iads, 0, sizeof(iads));
3406 memset(&addrds, 0, sizeof(addrds));
3407 for (ia = lease->bindings;
3408 ia != NULL && rval == ISC_R_SUCCESS;
3409 ia = ia->next) {
3410 if (ia->ia_type != D6O_IA_TA)
3411 continue;
3413 if (!buffer_allocate(&iads.buffer, 4, MDL)) {
3414 log_error("Unable to allocate memory for IA_TA.");
3415 rval = ISC_R_NOMEMORY;
3416 break;
3419 /* Copy the IAID into the packet buffer. */
3420 memcpy(iads.buffer->data, ia->iaid, 4);
3421 iads.data = iads.buffer->data;
3422 iads.len = 4;
3424 log_debug("XMT: X-- IA_TA %s",
3425 print_hex_1(4, iads.buffer->data, 55));
3427 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
3429 * Do not confirm expired addresses, do not request
3430 * expired addresses (but we keep them around for
3431 * solicit).
3433 if (addr->flags & DHC6_ADDR_EXPIRED)
3434 continue;
3436 if (addr->address.len != 16) {
3437 log_error("Illegal IPv6 address length (%d), "
3438 "ignoring. (%s:%d)",
3439 addr->address.len, MDL);
3440 continue;
3443 if (!buffer_allocate(&addrds.buffer, 24, MDL)) {
3444 log_error("Unable to allocate memory for "
3445 "IAADDR.");
3446 rval = ISC_R_NOMEMORY;
3447 break;
3450 addrds.data = addrds.buffer->data;
3451 addrds.len = 24;
3453 /* Copy the address into the packet buffer. */
3454 memcpy(addrds.buffer->data, addr->address.iabuf, 16);
3456 /* Copy in additional information as appropriate */
3457 switch (message) {
3458 case DHCPV6_REQUEST:
3459 case DHCPV6_RENEW:
3460 case DHCPV6_REBIND:
3461 t1 = client->config->requested_lease;
3462 t2 = t1 + 300;
3463 putULong(addrds.buffer->data + 16, t1);
3464 putULong(addrds.buffer->data + 20, t2);
3466 log_debug("XMT: | | X-- IAADDR %s",
3467 piaddr(addr->address));
3468 log_debug("XMT: | | | X-- Preferred "
3469 "lifetime +%u", (unsigned)t1);
3470 log_debug("XMT: | | | X-- Max lifetime +%u",
3471 (unsigned)t2);
3473 break;
3475 case DHCPV6_CONFIRM:
3477 * Set preferred and max life to zero,
3478 * per 17.1.3.
3480 memset(addrds.buffer->data + 16, 0, 8);
3481 log_debug("XMT: | X-- Confirm Address %s",
3482 piaddr(addr->address));
3483 break;
3485 case DHCPV6_RELEASE:
3486 /* Preferred and max life are irrelevant */
3487 memset(addrds.buffer->data + 16, 0, 8);
3488 log_debug("XMT: | X-- Release Address %s",
3489 piaddr(addr->address));
3490 break;
3492 default:
3493 log_fatal("Impossible condition at %s:%d.",
3494 MDL);
3497 append_option(&iads, &dhcpv6_universe, iaaddr_option,
3498 &addrds);
3499 data_string_forget(&addrds, MDL);
3503 * It doesn't make sense to make a request without an
3504 * address.
3506 if (ia->addrs == NULL) {
3507 log_debug("!!!: V IA_TA has no IAADDRs - removed.");
3508 rval = ISC_R_FAILURE;
3509 } else if (rval == ISC_R_SUCCESS) {
3510 log_debug("XMT: V IA_TA appended.");
3511 append_option(packet, &dhcpv6_universe, ia_ta_option,
3512 &iads);
3515 data_string_forget(&iads, MDL);
3518 return rval;
3521 /* For each IA_PD in the lease, for each prefix in the IA_PD,
3522 * append that information onto the packet-so-far.
3524 static isc_result_t
3525 dhc6_add_ia_pd(struct client_state *client, struct data_string *packet,
3526 struct dhc6_lease *lease, u_int8_t message)
3528 struct data_string iads;
3529 struct data_string prefds;
3530 struct dhc6_addr *pref;
3531 struct dhc6_ia *ia;
3532 isc_result_t rval = ISC_R_SUCCESS;
3533 TIME t1, t2;
3535 memset(&iads, 0, sizeof(iads));
3536 memset(&prefds, 0, sizeof(prefds));
3537 for (ia = lease->bindings;
3538 ia != NULL && rval == ISC_R_SUCCESS;
3539 ia = ia->next) {
3540 if (ia->ia_type != D6O_IA_PD)
3541 continue;
3543 if (!buffer_allocate(&iads.buffer, 12, MDL)) {
3544 log_error("Unable to allocate memory for IA_PD.");
3545 rval = ISC_R_NOMEMORY;
3546 break;
3549 /* Copy the IAID into the packet buffer. */
3550 memcpy(iads.buffer->data, ia->iaid, 4);
3551 iads.data = iads.buffer->data;
3552 iads.len = 12;
3554 switch (message) {
3555 case DHCPV6_REQUEST:
3556 case DHCPV6_RENEW:
3557 case DHCPV6_REBIND:
3559 t1 = client->config->requested_lease / 2;
3560 t2 = t1 + (t1 / 2);
3561 #if MAX_TIME > 0xffffffff
3562 if (t1 > 0xffffffff)
3563 t1 = 0xffffffff;
3564 if (t2 > 0xffffffff)
3565 t2 = 0xffffffff;
3566 #endif
3567 putULong(iads.buffer->data + 4, t1);
3568 putULong(iads.buffer->data + 8, t2);
3570 log_debug("XMT: X-- IA_PD %s",
3571 print_hex_1(4, iads.data, 59));
3572 log_debug("XMT: | X-- Requested renew +%u",
3573 (unsigned) t1);
3574 log_debug("XMT: | X-- Requested rebind +%u",
3575 (unsigned) t2);
3576 break;
3578 case DHCPV6_RELEASE:
3579 /* Set t1 and t2 to zero; server will ignore them */
3580 memset(iads.buffer->data + 4, 0, 8);
3581 log_debug("XMT: X-- IA_PD %s",
3582 print_hex_1(4, iads.buffer->data, 55));
3584 break;
3586 default:
3587 log_fatal("Impossible condition at %s:%d.", MDL);
3590 for (pref = ia->addrs ; pref != NULL ; pref = pref->next) {
3592 * Do not confirm expired prefixes, do not request
3593 * expired prefixes (but we keep them around for
3594 * solicit).
3596 if (pref->flags & DHC6_ADDR_EXPIRED)
3597 continue;
3599 if (pref->address.len != 16) {
3600 log_error("Illegal IPv6 prefix "
3601 "ignoring. (%s:%d)",
3602 MDL);
3603 continue;
3606 if (pref->plen == 0) {
3607 log_info("Null IPv6 prefix, "
3608 "ignoring. (%s:%d)",
3609 MDL);
3612 if (!buffer_allocate(&prefds.buffer, 25, MDL)) {
3613 log_error("Unable to allocate memory for "
3614 "IAPREFIX.");
3615 rval = ISC_R_NOMEMORY;
3616 break;
3619 prefds.data = prefds.buffer->data;
3620 prefds.len = 25;
3622 /* Copy the prefix into the packet buffer. */
3623 putUChar(prefds.buffer->data + 8, pref->plen);
3624 memcpy(prefds.buffer->data + 9,
3625 pref->address.iabuf,
3626 16);
3628 /* Copy in additional information as appropriate */
3629 switch (message) {
3630 case DHCPV6_REQUEST:
3631 case DHCPV6_RENEW:
3632 case DHCPV6_REBIND:
3633 t1 = client->config->requested_lease;
3634 t2 = t1 + 300;
3635 putULong(prefds.buffer->data, t1);
3636 putULong(prefds.buffer->data + 4, t2);
3638 log_debug("XMT: | | X-- IAPREFIX %s/%u",
3639 piaddr(pref->address),
3640 (unsigned) pref->plen);
3641 log_debug("XMT: | | | X-- Preferred "
3642 "lifetime +%u", (unsigned)t1);
3643 log_debug("XMT: | | | X-- Max lifetime +%u",
3644 (unsigned)t2);
3646 break;
3648 case DHCPV6_RELEASE:
3649 /* Preferred and max life are irrelevant */
3650 memset(prefds.buffer->data, 0, 8);
3651 log_debug("XMT: | X-- Release Prefix %s/%u",
3652 piaddr(pref->address),
3653 (unsigned) pref->plen);
3654 break;
3656 default:
3657 log_fatal("Impossible condition at %s:%d.",
3658 MDL);
3661 append_option(&iads, &dhcpv6_universe,
3662 iaprefix_option, &prefds);
3663 data_string_forget(&prefds, MDL);
3667 * It doesn't make sense to make a request without an
3668 * address.
3670 if (ia->addrs == NULL) {
3671 log_debug("!!!: V IA_PD has no IAPREFIXs - removed.");
3672 rval = ISC_R_FAILURE;
3673 } else if (rval == ISC_R_SUCCESS) {
3674 log_debug("XMT: V IA_PD appended.");
3675 append_option(packet, &dhcpv6_universe,
3676 ia_pd_option, &iads);
3679 data_string_forget(&iads, MDL);
3682 return rval;
3685 /* stopping_finished() checks if there is a remaining work to do.
3687 static isc_boolean_t
3688 stopping_finished(void)
3690 struct interface_info *ip;
3691 struct client_state *client;
3693 for (ip = interfaces; ip; ip = ip -> next) {
3694 for (client = ip -> client; client; client = client -> next) {
3695 if (client->state != S_STOPPED)
3696 return ISC_FALSE;
3697 if (client->active_lease != NULL)
3698 return ISC_FALSE;
3701 return ISC_TRUE;
3704 /* reply_handler() accepts a Reply while we're attempting Select or Renew or
3705 * Rebind. Basically any Reply packet.
3707 void
3708 reply_handler(struct packet *packet, struct client_state *client)
3710 struct dhc6_lease *lease;
3711 isc_result_t check_status;
3713 if (packet->dhcpv6_msg_type != DHCPV6_REPLY)
3714 return;
3716 /* RFC3315 section 15.10 validation (same as 15.3 since we
3717 * always include a client id).
3719 if (!valid_reply(packet, client)) {
3720 log_error("Invalid Reply - rejecting.");
3721 return;
3724 lease = dhc6_leaseify(packet);
3726 /* This is an out of memory condition...hopefully a temporary
3727 * problem. Returning now makes us try to retransmit later.
3729 if (lease == NULL)
3730 return;
3732 check_status = dhc6_check_reply(client, lease);
3733 if (check_status != ISC_R_SUCCESS) {
3734 dhc6_lease_destroy(&lease, MDL);
3736 /* If no action was taken, but there is an error, then
3737 * we wait for a retransmission.
3739 if (check_status != ISC_R_CANCELED)
3740 return;
3743 /* We're done retransmitting at this point. */
3744 cancel_timeout(do_confirm6, client);
3745 cancel_timeout(do_select6, client);
3746 cancel_timeout(do_refresh6, client);
3747 cancel_timeout(do_release6, client);
3749 /* If this is in response to a Release/Decline, clean up and return. */
3750 if (client->state == S_STOPPED) {
3751 if (client->active_lease == NULL)
3752 return;
3754 dhc6_lease_destroy(&client->active_lease, MDL);
3755 client->active_lease = NULL;
3756 /* We should never wait for nothing!? */
3757 if (stopping_finished())
3758 exit(0);
3759 return;
3762 /* Action was taken, so now that we've torn down our scheduled
3763 * retransmissions, return.
3765 if (check_status == ISC_R_CANCELED)
3766 return;
3768 if (client->selected_lease != NULL) {
3769 dhc6_lease_destroy(&client->selected_lease, MDL);
3770 client->selected_lease = NULL;
3773 /* If this is in response to a confirm, we use the lease we've
3774 * already got, not the reply we were sent.
3776 if (client->state == S_REBOOTING) {
3777 if (client->active_lease == NULL)
3778 log_fatal("Impossible condition at %s:%d.", MDL);
3780 dhc6_lease_destroy(&lease, MDL);
3781 start_bound(client);
3782 return;
3785 /* Merge any bindings in the active lease (if there is one) into
3786 * the new active lease.
3788 dhc6_merge_lease(client->active_lease, lease);
3790 /* Cleanup if a previous attempt to go bound failed. */
3791 if (client->old_lease != NULL) {
3792 dhc6_lease_destroy(&client->old_lease, MDL);
3793 client->old_lease = NULL;
3796 /* Make this lease active and BIND to it. */
3797 if (client->active_lease != NULL)
3798 client->old_lease = client->active_lease;
3799 client->active_lease = lease;
3801 /* We're done with the ADVERTISEd leases, if any. */
3802 while(client->advertised_leases != NULL) {
3803 lease = client->advertised_leases;
3804 client->advertised_leases = lease->next;
3806 dhc6_lease_destroy(&lease, MDL);
3809 start_bound(client);
3812 /* DHCPv6 packets are a little sillier than they needed to be - the root
3813 * packet contains options, then IA's which contain options, then within
3814 * that IAADDR's which contain options.
3816 * To sort this out at dhclient-script time (which fetches config parameters
3817 * in environment variables), start_bound() iterates over each IAADDR, and
3818 * calls this function to marshall an environment variable set that includes
3819 * the most-specific option values related to that IAADDR in particular.
3821 * To achieve this, we load environment variables for the root options space,
3822 * then the IA, then the IAADDR. Any duplicate option names will be
3823 * over-written by the later versions.
3825 static void
3826 dhc6_marshall_values(const char *prefix, struct client_state *client,
3827 struct dhc6_lease *lease, struct dhc6_ia *ia,
3828 struct dhc6_addr *addr)
3830 /* Option cache contents, in descending order of
3831 * scope.
3833 if ((lease != NULL) && (lease->options != NULL))
3834 script_write_params6(client, prefix, lease->options);
3835 if ((ia != NULL) && (ia->options != NULL))
3836 script_write_params6(client, prefix, ia->options);
3837 if ((addr != NULL) && (addr->options != NULL))
3838 script_write_params6(client, prefix, addr->options);
3840 /* addr fields. */
3841 if (addr != NULL) {
3842 if ((ia != NULL) && (ia->ia_type == D6O_IA_PD)) {
3843 client_envadd(client, prefix,
3844 "ip6_prefix", "%s/%u",
3845 piaddr(addr->address),
3846 (unsigned) addr->plen);
3847 } else {
3848 /* Current practice is that all subnets are /64's, but
3849 * some suspect this may not be permanent.
3851 client_envadd(client, prefix, "ip6_prefixlen",
3852 "%d", 64);
3853 client_envadd(client, prefix, "ip6_address",
3854 "%s", piaddr(addr->address));
3856 if ((ia != NULL) && (ia->ia_type == D6O_IA_TA)) {
3857 client_envadd(client, prefix,
3858 "ip6_type", "temporary");
3860 client_envadd(client, prefix, "life_starts", "%d",
3861 (int)(addr->starts));
3862 client_envadd(client, prefix, "preferred_life", "%d",
3863 (int)(addr->preferred_life));
3864 client_envadd(client, prefix, "max_life", "%d",
3865 (int)(addr->max_life));
3868 /* ia fields. */
3869 if (ia != NULL) {
3870 client_envadd(client, prefix, "iaid", "%s",
3871 print_hex_1(4, ia->iaid, 12));
3872 client_envadd(client, prefix, "starts", "%d",
3873 (int)(ia->starts));
3874 client_envadd(client, prefix, "renew", "%u", ia->renew);
3875 client_envadd(client, prefix, "rebind", "%u", ia->rebind);
3879 /* Look at where the client's active lease is sitting. If it's looking to
3880 * time out on renew, rebind, depref, or expiration, do those things.
3882 static void
3883 dhc6_check_times(struct client_state *client)
3885 struct dhc6_lease *lease;
3886 struct dhc6_ia *ia;
3887 struct dhc6_addr *addr;
3888 TIME renew=MAX_TIME, rebind=MAX_TIME, depref=MAX_TIME,
3889 lo_expire=MAX_TIME, hi_expire=0, tmp;
3890 int has_addrs = ISC_FALSE;
3891 struct timeval tv;
3893 lease = client->active_lease;
3895 /* Bit spammy. We should probably keep record of scheduled
3896 * events instead.
3898 cancel_timeout(start_renew6, client);
3899 cancel_timeout(start_rebind6, client);
3900 cancel_timeout(do_depref, client);
3901 cancel_timeout(do_expire, client);
3903 for(ia = lease->bindings ; ia != NULL ; ia = ia->next) {
3904 TIME this_ia_lo_expire, this_ia_hi_expire, use_expire;
3906 this_ia_lo_expire = MAX_TIME;
3907 this_ia_hi_expire = 0;
3909 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
3910 if(!(addr->flags & DHC6_ADDR_DEPREFFED)) {
3911 if (addr->preferred_life == 0xffffffff)
3912 tmp = MAX_TIME;
3913 else
3914 tmp = addr->starts +
3915 addr->preferred_life;
3917 if (tmp < depref)
3918 depref = tmp;
3921 if (!(addr->flags & DHC6_ADDR_EXPIRED)) {
3922 /* Find EPOCH-relative expiration. */
3923 if (addr->max_life == 0xffffffff)
3924 tmp = MAX_TIME;
3925 else
3926 tmp = addr->starts + addr->max_life;
3928 /* Make the times ia->starts relative. */
3929 tmp -= ia->starts;
3931 if (tmp > this_ia_hi_expire)
3932 this_ia_hi_expire = tmp;
3933 if (tmp < this_ia_lo_expire)
3934 this_ia_lo_expire = tmp;
3936 has_addrs = ISC_TRUE;
3940 /* These times are ia->starts relative. */
3941 if (this_ia_lo_expire <= (this_ia_hi_expire / 2))
3942 use_expire = this_ia_hi_expire;
3943 else
3944 use_expire = this_ia_lo_expire;
3947 * If the auto-selected expiration time is "infinite", or
3948 * zero, assert a reasonable default.
3950 if ((use_expire == MAX_TIME) || (use_expire <= 1))
3951 use_expire = client->config->requested_lease / 2;
3952 else
3953 use_expire /= 2;
3955 /* Don't renew/rebind temporary addresses. */
3956 if (ia->ia_type != D6O_IA_TA) {
3958 if (ia->renew == 0) {
3959 tmp = ia->starts + use_expire;
3960 } else if (ia->renew == 0xffffffff)
3961 tmp = MAX_TIME;
3962 else
3963 tmp = ia->starts + ia->renew;
3965 if (tmp < renew)
3966 renew = tmp;
3968 if (ia->rebind == 0) {
3969 /* Set rebind to 3/4 expiration interval. */
3970 tmp = ia->starts;
3971 tmp += use_expire + (use_expire / 2);
3972 } else if (ia->rebind == 0xffffffff)
3973 tmp = MAX_TIME;
3974 else
3975 tmp = ia->starts + ia->rebind;
3977 if (tmp < rebind)
3978 rebind = tmp;
3982 * Return expiration ranges to EPOCH relative for event
3983 * scheduling (add_timeout()).
3985 this_ia_hi_expire += ia->starts;
3986 this_ia_lo_expire += ia->starts;
3988 if (this_ia_hi_expire > hi_expire)
3989 hi_expire = this_ia_hi_expire;
3990 if (this_ia_lo_expire < lo_expire)
3991 lo_expire = this_ia_lo_expire;
3994 /* If there are no addresses, give up, go to INIT.
3995 * Note that if an address is unexpired with a date in the past,
3996 * we're scheduling an expiration event to ocurr in the past. We
3997 * could probably optimize this to expire now (but then there's
3998 * recursion).
4000 * In the future, we may decide that we're done here, or to
4001 * schedule a future request (using 4-pkt info-request model).
4003 if (has_addrs == ISC_FALSE) {
4004 dhc6_lease_destroy(&client->active_lease, MDL);
4005 client->active_lease = NULL;
4007 /* Go back to the beginning. */
4008 start_init6(client);
4009 return;
4012 switch(client->state) {
4013 case S_BOUND:
4014 /* We'd like to hit renewing, but if rebinding has already
4015 * passed (time warp), head straight there.
4017 if ((rebind > cur_time) && (renew < rebind)) {
4018 log_debug("PRC: Renewal event scheduled in %d seconds, "
4019 "to run for %u seconds.",
4020 (int)(renew - cur_time),
4021 (unsigned)(rebind - renew));
4022 client->next_MRD = rebind;
4023 tv.tv_sec = renew;
4024 tv.tv_usec = 0;
4025 add_timeout(&tv, start_renew6, client, NULL, NULL);
4027 break;
4029 /* FALL THROUGH */
4030 case S_RENEWING:
4031 /* While actively renewing, MRD is bounded by the time
4032 * we stop renewing and start rebinding. This helps us
4033 * process the state change on time.
4035 client->MRD = rebind - cur_time;
4036 if (rebind != MAX_TIME) {
4037 log_debug("PRC: Rebind event scheduled in %d seconds, "
4038 "to run for %d seconds.",
4039 (int)(rebind - cur_time),
4040 (int)(hi_expire - rebind));
4041 client->next_MRD = hi_expire;
4042 tv.tv_sec = rebind;
4043 tv.tv_usec = 0;
4044 add_timeout(&tv, start_rebind6, client, NULL, NULL);
4046 break;
4048 case S_REBINDING:
4049 /* For now, we rebind up until the last lease expires. In
4050 * the future, we might want to start SOLICITing when we've
4051 * depreffed an address.
4053 client->MRD = hi_expire - cur_time;
4054 break;
4056 default:
4057 log_fatal("Impossible condition at %s:%d.", MDL);
4060 /* Separately, set a time at which we will depref and expire
4061 * leases. This might happen with multiple addresses while we
4062 * keep trying to refresh.
4064 if (depref != MAX_TIME) {
4065 log_debug("PRC: Depreference scheduled in %d seconds.",
4066 (int)(depref - cur_time));
4067 tv.tv_sec = depref;
4068 tv.tv_usec = 0;
4069 add_timeout(&tv, do_depref, client, NULL, NULL);
4071 if (lo_expire != MAX_TIME) {
4072 log_debug("PRC: Expiration scheduled in %d seconds.",
4073 (int)(lo_expire - cur_time));
4074 tv.tv_sec = lo_expire;
4075 tv.tv_usec = 0;
4076 add_timeout(&tv, do_expire, client, NULL, NULL);
4080 /* In a given IA chain, find the IA with the same type and 'iaid'. */
4081 static struct dhc6_ia *
4082 find_ia(struct dhc6_ia *head, u_int16_t type, const char *id)
4084 struct dhc6_ia *ia;
4086 for (ia = head ; ia != NULL ; ia = ia->next) {
4087 if (ia->ia_type != type)
4088 continue;
4089 if (memcmp(ia->iaid, id, 4) == 0)
4090 return ia;
4093 return NULL;
4096 /* In a given address chain, find a matching address. */
4097 static struct dhc6_addr *
4098 find_addr(struct dhc6_addr *head, struct iaddr *address)
4100 struct dhc6_addr *addr;
4102 for (addr = head ; addr != NULL ; addr = addr->next) {
4103 if ((addr->address.len == address->len) &&
4104 (memcmp(addr->address.iabuf, address->iabuf,
4105 address->len) == 0))
4106 return addr;
4109 return NULL;
4112 /* In a given prefix chain, find a matching prefix. */
4113 static struct dhc6_addr *
4114 find_pref(struct dhc6_addr *head, struct iaddr *prefix, u_int8_t plen)
4116 struct dhc6_addr *pref;
4118 for (pref = head ; pref != NULL ; pref = pref->next) {
4119 if ((pref->address.len == prefix->len) &&
4120 (pref->plen == plen) &&
4121 (memcmp(pref->address.iabuf, prefix->iabuf,
4122 prefix->len) == 0))
4123 return pref;
4126 return NULL;
4129 /* Merge the bindings from the source lease into the destination lease
4130 * structure, where they are missing. We have to copy the stateful
4131 * objects rather than move them over, because later code needs to be
4132 * able to compare new versus old if they contain any bindings.
4134 static void
4135 dhc6_merge_lease(struct dhc6_lease *src, struct dhc6_lease *dst)
4137 struct dhc6_ia *sia, *dia, *tia;
4138 struct dhc6_addr *saddr, *daddr, *taddr;
4139 int changes = 0;
4141 if ((dst == NULL) || (src == NULL))
4142 return;
4144 for (sia = src->bindings ; sia != NULL ; sia = sia->next) {
4145 dia = find_ia(dst->bindings, sia->ia_type, (char *)sia->iaid);
4147 if (dia == NULL) {
4148 tia = dhc6_dup_ia(sia, MDL);
4150 if (tia == NULL)
4151 log_fatal("Out of memory merging lease - "
4152 "Unable to continue without losing "
4153 "state! (%s:%d)", MDL);
4155 /* XXX: consider sorting? */
4156 tia->next = dst->bindings;
4157 dst->bindings = tia;
4158 changes = 1;
4159 } else {
4160 for (saddr = sia->addrs ; saddr != NULL ;
4161 saddr = saddr->next) {
4162 if (sia->ia_type != D6O_IA_PD)
4163 daddr = find_addr(dia->addrs,
4164 &saddr->address);
4165 else
4166 daddr = find_pref(dia->addrs,
4167 &saddr->address,
4168 saddr->plen);
4170 if (daddr == NULL) {
4171 taddr = dhc6_dup_addr(saddr, MDL);
4173 if (taddr == NULL)
4174 log_fatal("Out of memory "
4175 "merging lease - "
4176 "Unable to continue "
4177 "without losing "
4178 "state! (%s:%d)",
4179 MDL);
4181 /* XXX: consider sorting? */
4182 taddr->next = dia->addrs;
4183 dia->addrs = taddr;
4184 changes = 1;
4190 /* If we made changes, reset the score to 0 so it is recalculated. */
4191 if (changes)
4192 dst->score = 0;
4195 /* We've either finished selecting or succeeded in Renew or Rebinding our
4196 * lease. In all cases we got a Reply. Give dhclient-script a tickle
4197 * to inform it about the new values, and then lay in wait for the next
4198 * event.
4200 static void
4201 start_bound(struct client_state *client)
4203 struct dhc6_ia *ia, *oldia;
4204 struct dhc6_addr *addr, *oldaddr;
4205 struct dhc6_lease *lease, *old;
4206 const char *reason;
4207 #if defined (NSUPDATE)
4208 TIME dns_update_offset = 1;
4209 #endif
4211 lease = client->active_lease;
4212 if (lease == NULL) {
4213 log_error("Cannot enter bound state unless an active lease "
4214 "is selected.");
4215 return;
4217 lease->released = ISC_FALSE;
4218 old = client->old_lease;
4220 client->v6_handler = bound_handler;
4222 switch (client->state) {
4223 case S_SELECTING:
4224 case S_REBOOTING: /* Pretend we got bound. */
4225 reason = "BOUND6";
4226 break;
4228 case S_RENEWING:
4229 reason = "RENEW6";
4230 break;
4232 case S_REBINDING:
4233 reason = "REBIND6";
4234 break;
4236 default:
4237 log_fatal("Impossible condition at %s:%d.", MDL);
4238 /* Silence compiler warnings. */
4239 return;
4242 log_debug("PRC: Bound to lease %s.",
4243 print_hex_1(client->active_lease->server_id.len,
4244 client->active_lease->server_id.data, 55));
4245 client->state = S_BOUND;
4247 write_client6_lease(client, lease, 0, 1);
4249 oldia = NULL;
4250 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
4251 if (old != NULL)
4252 oldia = find_ia(old->bindings,
4253 ia->ia_type,
4254 (char *)ia->iaid);
4255 else
4256 oldia = NULL;
4258 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
4259 if (oldia != NULL) {
4260 if (ia->ia_type != D6O_IA_PD)
4261 oldaddr = find_addr(oldia->addrs,
4262 &addr->address);
4263 else
4264 oldaddr = find_pref(oldia->addrs,
4265 &addr->address,
4266 addr->plen);
4267 } else
4268 oldaddr = NULL;
4270 #if defined (NSUPDATE)
4271 if ((oldaddr == NULL) && (ia->ia_type == D6O_IA_NA))
4272 dhclient_schedule_updates(client,
4273 &addr->address,
4274 dns_update_offset++);
4275 #endif
4277 /* Shell out to setup the new binding. */
4278 script_init(client, reason, NULL);
4280 if (old != NULL)
4281 dhc6_marshall_values("old_", client, old,
4282 oldia, oldaddr);
4283 dhc6_marshall_values("new_", client, lease, ia, addr);
4284 script_write_requested6(client);
4286 script_go(client);
4289 /* XXX: maybe we should loop on the old values instead? */
4290 if (ia->addrs == NULL) {
4291 script_init(client, reason, NULL);
4293 if (old != NULL)
4294 dhc6_marshall_values("old_", client, old,
4295 oldia,
4296 oldia != NULL ?
4297 oldia->addrs : NULL);
4299 dhc6_marshall_values("new_", client, lease, ia,
4300 NULL);
4301 script_write_requested6(client);
4303 script_go(client);
4307 /* XXX: maybe we should loop on the old values instead? */
4308 if (lease->bindings == NULL) {
4309 script_init(client, reason, NULL);
4311 if (old != NULL)
4312 dhc6_marshall_values("old_", client, old,
4313 old->bindings,
4314 (old->bindings != NULL) ?
4315 old->bindings->addrs : NULL);
4317 dhc6_marshall_values("new_", client, lease, NULL, NULL);
4318 script_write_requested6(client);
4320 script_go(client);
4323 go_daemon();
4325 if (client->old_lease != NULL) {
4326 dhc6_lease_destroy(&client->old_lease, MDL);
4327 client->old_lease = NULL;
4330 /* Schedule events. */
4331 dhc6_check_times(client);
4334 /* While bound, ignore packets. In the future we'll want to answer
4335 * Reconfigure-Request messages and the like.
4337 void
4338 bound_handler(struct packet *packet, struct client_state *client)
4340 log_debug("RCV: Input packets are ignored once bound.");
4343 /* start_renew6() gets us all ready to go to start transmitting Renew packets.
4344 * Note that client->next_MRD must be set before entering this function -
4345 * it must be set to the time at which the client should start Rebinding.
4347 void
4348 start_renew6(void *input)
4350 struct client_state *client;
4352 client = (struct client_state *)input;
4354 log_info("PRC: Renewing lease on %s.",
4355 client->name ? client->name : client->interface->name);
4356 client->state = S_RENEWING;
4358 client->v6_handler = reply_handler;
4360 /* Times per RFC3315 section 18.1.3. */
4361 client->IRT = REN_TIMEOUT * 100;
4362 client->MRT = REN_MAX_RT * 100;
4363 client->MRC = 0;
4364 /* MRD is special in renew - we need to set it by checking timer
4365 * state.
4367 client->MRD = client->next_MRD - cur_time;
4369 dhc6_retrans_init(client);
4371 client->refresh_type = DHCPV6_RENEW;
4372 do_refresh6(client);
4375 /* do_refresh6() transmits one DHCPv6 packet, be it a Renew or Rebind, and
4376 * gives the retransmission state a bump for the next time. Note that
4377 * client->refresh_type must be set before entering this function.
4379 void
4380 do_refresh6(void *input)
4382 struct option_cache *oc;
4383 struct sockaddr_in6 unicast, *dest_addr = &DHCPv6DestAddr;
4384 struct data_string ds;
4385 struct client_state *client;
4386 struct dhc6_lease *lease;
4387 struct timeval elapsed, tv;
4388 int send_ret;
4390 client = (struct client_state *)input;
4391 memset(&ds, 0, sizeof(ds));
4393 lease = client->active_lease;
4394 if (lease == NULL) {
4395 log_error("Cannot renew without an active binding.");
4396 return;
4399 /* Ensure we're emitting a valid message type. */
4400 switch (client->refresh_type) {
4401 case DHCPV6_RENEW:
4402 case DHCPV6_REBIND:
4403 break;
4405 default:
4406 log_fatal("Internal inconsistency (%d) at %s:%d.",
4407 client->refresh_type, MDL);
4411 * Start_time starts at the first transmission.
4413 if (client->txcount == 0) {
4414 client->start_time.tv_sec = cur_tv.tv_sec;
4415 client->start_time.tv_usec = cur_tv.tv_usec;
4418 /* elapsed = cur - start */
4419 elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
4420 elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
4421 if (elapsed.tv_usec < 0) {
4422 elapsed.tv_sec -= 1;
4423 elapsed.tv_usec += 1000000;
4425 if (((client->MRC != 0) && (client->txcount > client->MRC)) ||
4426 ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD))) {
4427 /* We're done. Move on to the next phase, if any. */
4428 dhc6_check_times(client);
4429 return;
4433 * Check whether the server has sent a unicast option; if so, we can
4434 * use the address it specified for RENEWs.
4436 oc = lookup_option(&dhcpv6_universe, lease->options, D6O_UNICAST);
4437 if (oc && evaluate_option_cache(&ds, NULL, NULL, NULL,
4438 lease->options, NULL, &global_scope,
4439 oc, MDL)) {
4440 if (ds.len < 16) {
4441 log_error("Invalid unicast option length %d.", ds.len);
4442 } else {
4443 memset(&unicast, 0, sizeof(DHCPv6DestAddr));
4444 unicast.sin6_family = AF_INET6;
4445 unicast.sin6_port = remote_port;
4446 memcpy(&unicast.sin6_addr, ds.data, 16);
4447 if (client->refresh_type == DHCPV6_RENEW) {
4448 dest_addr = &unicast;
4452 data_string_forget(&ds, MDL);
4455 /* Commence forming a renew packet. */
4456 memset(&ds, 0, sizeof(ds));
4457 if (!buffer_allocate(&ds.buffer, 4, MDL)) {
4458 log_error("Unable to allocate memory for packet.");
4459 return;
4461 ds.data = ds.buffer->data;
4462 ds.len = 4;
4464 ds.buffer->data[0] = client->refresh_type;
4465 memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
4467 /* Form an elapsed option. */
4468 /* Maximum value is 65535 1/100s coded as 0xffff. */
4469 if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
4470 ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
4471 client->elapsed = 0xffff;
4472 } else {
4473 client->elapsed = elapsed.tv_sec * 100;
4474 client->elapsed += elapsed.tv_usec / 10000;
4477 if (client->elapsed == 0)
4478 log_debug("XMT: Forming %s, 0 ms elapsed.",
4479 dhcpv6_type_names[client->refresh_type]);
4480 else
4481 log_debug("XMT: Forming %s, %u0 ms elapsed.",
4482 dhcpv6_type_names[client->refresh_type],
4483 (unsigned)client->elapsed);
4485 client->elapsed = htons(client->elapsed);
4487 make_client6_options(client, &client->sent_options, lease,
4488 client->refresh_type);
4490 /* Put in any options from the sent cache. */
4491 dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
4492 client->sent_options, &global_scope,
4493 &dhcpv6_universe);
4495 /* Append IA's */
4496 if (wanted_ia_na &&
4497 dhc6_add_ia_na(client, &ds, lease,
4498 client->refresh_type) != ISC_R_SUCCESS) {
4499 data_string_forget(&ds, MDL);
4500 return;
4502 if (wanted_ia_pd &&
4503 dhc6_add_ia_pd(client, &ds, lease,
4504 client->refresh_type) != ISC_R_SUCCESS) {
4505 data_string_forget(&ds, MDL);
4506 return;
4509 log_info("XMT: %s on %s, interval %ld0ms.",
4510 dhcpv6_type_names[client->refresh_type],
4511 client->name ? client->name : client->interface->name,
4512 (long int)client->RT);
4514 send_ret = send_packet6(client->interface, ds.data, ds.len, dest_addr);
4516 if (send_ret != ds.len) {
4517 log_error("dhc6: send_packet6() sent %d of %d bytes",
4518 send_ret, ds.len);
4521 data_string_forget(&ds, MDL);
4523 /* Wait RT */
4524 tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
4525 tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
4526 if (tv.tv_usec >= 1000000) {
4527 tv.tv_sec += 1;
4528 tv.tv_usec -= 1000000;
4530 add_timeout(&tv, do_refresh6, client, NULL, NULL);
4532 dhc6_retrans_advance(client);
4535 /* start_rebind6() gets us all set up to go and rebind a lease. Note that
4536 * client->next_MRD must be set before entering this function. In this case,
4537 * MRD must be set to the maximum time any address in the packet will
4538 * expire.
4540 void
4541 start_rebind6(void *input)
4543 struct client_state *client;
4545 client = (struct client_state *)input;
4547 log_info("PRC: Rebinding lease on %s.",
4548 client->name ? client->name : client->interface->name);
4549 client->state = S_REBINDING;
4551 client->v6_handler = reply_handler;
4553 /* Times per RFC3315 section 18.1.4. */
4554 client->IRT = REB_TIMEOUT * 100;
4555 client->MRT = REB_MAX_RT * 100;
4556 client->MRC = 0;
4557 /* MRD is special in rebind - it's determined by the timer
4558 * state.
4560 client->MRD = client->next_MRD - cur_time;
4562 dhc6_retrans_init(client);
4564 client->refresh_type = DHCPV6_REBIND;
4565 do_refresh6(client);
4568 /* do_depref() runs through a given lease's addresses, for each that has
4569 * not yet been depreffed, shells out to the dhclient-script to inform it
4570 * of the status change. The dhclient-script should then do...something...
4571 * to encourage applications to move off the address and onto one of the
4572 * remaining 'preferred' addresses.
4574 void
4575 do_depref(void *input)
4577 struct client_state *client;
4578 struct dhc6_lease *lease;
4579 struct dhc6_ia *ia;
4580 struct dhc6_addr *addr;
4582 client = (struct client_state *)input;
4584 lease = client->active_lease;
4585 if (lease == NULL)
4586 return;
4588 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
4589 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
4590 if (addr->flags & DHC6_ADDR_DEPREFFED)
4591 continue;
4593 if (addr->starts + addr->preferred_life <= cur_time) {
4594 script_init(client, "DEPREF6", NULL);
4595 dhc6_marshall_values("cur_", client, lease,
4596 ia, addr);
4597 script_write_requested6(client);
4598 script_go(client);
4600 addr->flags |= DHC6_ADDR_DEPREFFED;
4602 if (ia->ia_type != D6O_IA_PD)
4603 log_info("PRC: Address %s depreferred.",
4604 piaddr(addr->address));
4605 else
4606 log_info("PRC: Prefix %s/%u depreferred.",
4607 piaddr(addr->address),
4608 (unsigned) addr->plen);
4610 #if defined (NSUPDATE)
4611 /* Remove DDNS bindings at depref time. */
4612 if ((ia->ia_type == D6O_IA_NA) &&
4613 client->config->do_forward_update)
4614 client_dns_remove(client,
4615 &addr->address);
4616 #endif
4621 dhc6_check_times(client);
4624 /* do_expire() searches through all the addresses on a given lease, and
4625 * expires/removes any addresses that are no longer valid.
4627 void
4628 do_expire(void *input)
4630 struct client_state *client;
4631 struct dhc6_lease *lease;
4632 struct dhc6_ia *ia;
4633 struct dhc6_addr *addr;
4634 int has_addrs = ISC_FALSE;
4636 client = (struct client_state *)input;
4638 lease = client->active_lease;
4639 if (lease == NULL)
4640 return;
4642 for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
4643 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
4644 if (addr->flags & DHC6_ADDR_EXPIRED)
4645 continue;
4647 if (addr->starts + addr->max_life <= cur_time) {
4648 script_init(client, "EXPIRE6", NULL);
4649 dhc6_marshall_values("old_", client, lease,
4650 ia, addr);
4651 script_write_requested6(client);
4652 script_go(client);
4654 addr->flags |= DHC6_ADDR_EXPIRED;
4656 if (ia->ia_type != D6O_IA_PD)
4657 log_info("PRC: Address %s expired.",
4658 piaddr(addr->address));
4659 else
4660 log_info("PRC: Prefix %s/%u expired.",
4661 piaddr(addr->address),
4662 (unsigned) addr->plen);
4664 #if defined (NSUPDATE)
4665 /* We remove DNS records at depref time, but
4666 * it is possible that we might get here
4667 * without depreffing.
4669 if ((ia->ia_type == D6O_IA_NA) &&
4670 client->config->do_forward_update &&
4671 !(addr->flags & DHC6_ADDR_DEPREFFED))
4672 client_dns_remove(client,
4673 &addr->address);
4674 #endif
4676 continue;
4679 has_addrs = ISC_TRUE;
4683 /* Clean up empty leases. */
4684 if (has_addrs == ISC_FALSE) {
4685 log_info("PRC: Bound lease is devoid of active addresses."
4686 " Re-initializing.");
4688 dhc6_lease_destroy(&lease, MDL);
4689 client->active_lease = NULL;
4691 start_init6(client);
4692 return;
4695 /* Schedule the next run through. */
4696 dhc6_check_times(client);
4700 * Run client script to unconfigure interface.
4701 * Called with reason STOP6 when dhclient -x is run, or with reason
4702 * RELEASE6 when server has replied to a Release message.
4703 * Stateless is a special case.
4705 void
4706 unconfigure6(struct client_state *client, const char *reason)
4708 struct dhc6_ia *ia;
4709 struct dhc6_addr *addr;
4711 if (stateless) {
4712 script_init(client, reason, NULL);
4713 if (client->active_lease != NULL)
4714 script_write_params6(client, "old_",
4715 client->active_lease->options);
4716 script_write_requested6(client);
4717 script_go(client);
4718 return;
4721 if (client->active_lease == NULL)
4722 return;
4724 for (ia = client->active_lease->bindings ; ia != NULL ; ia = ia->next) {
4725 if (ia->ia_type == D6O_IA_TA)
4726 continue;
4728 for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
4729 script_init(client, reason, NULL);
4730 dhc6_marshall_values("old_", client,
4731 client->active_lease, ia, addr);
4732 script_write_requested6(client);
4733 script_go(client);
4735 #if defined (NSUPDATE)
4736 if ((ia->ia_type == D6O_IA_NA) &&
4737 client->config->do_forward_update)
4738 client_dns_remove(client, &addr->address);
4739 #endif
4744 static void
4745 refresh_info_request6(void *input)
4747 struct client_state *client;
4749 client = (struct client_state *)input;
4750 start_info_request6(client);
4753 /* Timeout for Information-Request (using the IRT option).
4755 static void
4756 dhc6_check_irt(struct client_state *client)
4758 struct option **req;
4759 struct option_cache *oc;
4760 TIME expire = MAX_TIME;
4761 struct timeval tv;
4762 int i;
4763 isc_boolean_t found = ISC_FALSE;
4765 cancel_timeout(refresh_info_request6, client);
4767 req = client->config->requested_options;
4768 for (i = 0; req[i] != NULL; i++) {
4769 if (req[i] == irt_option) {
4770 found = ISC_TRUE;
4771 break;
4774 /* Simply return gives a endless loop waiting for nothing. */
4775 if (!found)
4776 exit(0);
4778 oc = lookup_option(&dhcpv6_universe, client->active_lease->options,
4779 D6O_INFORMATION_REFRESH_TIME);
4780 if (oc != NULL) {
4781 struct data_string irt;
4783 memset(&irt, 0, sizeof(irt));
4784 if (!evaluate_option_cache(&irt, NULL, NULL, client,
4785 client->active_lease->options,
4786 NULL, &global_scope, oc, MDL) ||
4787 (irt.len < 4)) {
4788 log_error("Can't evaluate IRT.");
4789 } else {
4790 expire = getULong(irt.data);
4791 if (expire < IRT_MINIMUM)
4792 expire = IRT_MINIMUM;
4793 if (expire == 0xffffffff)
4794 expire = MAX_TIME;
4796 data_string_forget(&irt, MDL);
4797 } else
4798 expire = IRT_DEFAULT;
4800 if (expire != MAX_TIME) {
4801 log_debug("PRC: Refresh event scheduled in %u seconds.",
4802 (unsigned) expire);
4803 tv.tv_sec = cur_time + expire;
4804 tv.tv_usec = 0;
4805 add_timeout(&tv, refresh_info_request6, client, NULL, NULL);
4809 /* We got a Reply. Give dhclient-script a tickle to inform it about
4810 * the new values, and then lay in wait for the next event.
4812 static void
4813 start_informed(struct client_state *client)
4815 client->v6_handler = informed_handler;
4817 log_debug("PRC: Done.");
4819 client->state = S_BOUND;
4821 script_init(client, "RENEW6", NULL);
4822 if (client->old_lease != NULL)
4823 script_write_params6(client, "old_",
4824 client->old_lease->options);
4825 script_write_params6(client, "new_", client->active_lease->options);
4826 script_write_requested6(client);
4827 script_go(client);
4829 go_daemon();
4831 if (client->old_lease != NULL) {
4832 dhc6_lease_destroy(&client->old_lease, MDL);
4833 client->old_lease = NULL;
4836 /* Schedule events. */
4837 dhc6_check_irt(client);
4840 /* While informed, ignore packets.
4842 void
4843 informed_handler(struct packet *packet, struct client_state *client)
4845 log_debug("RCV: Input packets are ignored once bound.");
4848 /* make_client6_options() fetches option caches relevant to the client's
4849 * scope and places them into the sent_options cache. This cache is later
4850 * used to populate DHCPv6 output packets with options.
4852 static void
4853 make_client6_options(struct client_state *client, struct option_state **op,
4854 struct dhc6_lease *lease, u_int8_t message)
4856 struct option_cache *oc;
4857 struct option **req;
4858 struct buffer *buffer;
4859 int buflen, i, oro_len;
4861 if ((op == NULL) || (client == NULL))
4862 return;
4864 if (*op)
4865 option_state_dereference(op, MDL);
4867 /* Create a cache to carry options to transmission. */
4868 option_state_allocate(op, MDL);
4870 /* Create and store an 'elapsed time' option in the cache. */
4871 oc = NULL;
4872 if (option_cache_allocate(&oc, MDL)) {
4873 const unsigned char *cdata;
4875 cdata = (unsigned char *)&client->elapsed;
4877 if (make_const_data(&oc->expression, cdata, 2, 0, 0, MDL)) {
4878 option_reference(&oc->option, elapsed_option, MDL);
4879 save_option(&dhcpv6_universe, *op, oc);
4882 option_cache_dereference(&oc, MDL);
4885 /* Bring in any configured options to send. */
4886 if (client->config->on_transmission)
4887 execute_statements_in_scope(NULL, NULL, NULL, client,
4888 lease ? lease->options : NULL,
4889 *op, &global_scope,
4890 client->config->on_transmission,
4891 NULL, NULL);
4893 /* Rapid-commit is only for SOLICITs. */
4894 if (message != DHCPV6_SOLICIT)
4895 delete_option(&dhcpv6_universe, *op, D6O_RAPID_COMMIT);
4897 /* See if the user configured a DUID in a relevant scope. If not,
4898 * introduce our default manufactured id.
4900 if ((oc = lookup_option(&dhcpv6_universe, *op,
4901 D6O_CLIENTID)) == NULL) {
4902 if (!option_cache(&oc, &default_duid, NULL, clientid_option,
4903 MDL))
4904 log_fatal("Failure assembling a DUID.");
4906 save_option(&dhcpv6_universe, *op, oc);
4907 option_cache_dereference(&oc, MDL);
4910 /* In cases where we're responding to a single server, put the
4911 * server's id in the response.
4913 * Note that lease is NULL for SOLICIT or INFO request messages,
4914 * and otherwise MUST be present.
4916 if (lease == NULL) {
4917 if ((message != DHCPV6_SOLICIT) &&
4918 (message != DHCPV6_INFORMATION_REQUEST))
4919 log_fatal("Impossible condition at %s:%d.", MDL);
4920 } else if ((message != DHCPV6_REBIND) &&
4921 (message != DHCPV6_CONFIRM)) {
4922 oc = lookup_option(&dhcpv6_universe, lease->options,
4923 D6O_SERVERID);
4924 if (oc != NULL)
4925 save_option(&dhcpv6_universe, *op, oc);
4928 /* 'send dhcp6.oro foo;' syntax we used in 4.0.0a1/a2 has been
4929 * deprecated by adjustments to the 'request' syntax also used for
4930 * DHCPv4.
4932 if (lookup_option(&dhcpv6_universe, *op, D6O_ORO) != NULL)
4933 log_error("'send dhcp6.oro' syntax is deprecated, please "
4934 "use the 'request' syntax (\"man dhclient.conf\").");
4936 /* Construct and store an ORO (Option Request Option). It is a
4937 * fatal error to fail to send an ORO (of at least zero length).
4939 * Discussion: RFC3315 appears to be inconsistent in its statements
4940 * of whether or not the ORO is mandatory. In section 18.1.1
4941 * ("Creation and Transmission of Request Messages"):
4943 * The client MUST include an Option Request option (see section
4944 * 22.7) to indicate the options the client is interested in
4945 * receiving. The client MAY include options with data values as
4946 * hints to the server about parameter values the client would like
4947 * to have returned.
4949 * This MUST is missing from the creation/transmission of other
4950 * messages (such as Renew and Rebind), and the section 22.7 ("Option
4951 * Request Option" format and definition):
4953 * A client MAY include an Option Request option in a Solicit,
4954 * Request, Renew, Rebind, Confirm or Information-request message to
4955 * inform the server about options the client wants the server to
4956 * send to the client. A server MAY include an Option Request
4957 * option in a Reconfigure option to indicate which options the
4958 * client should request from the server.
4960 * seems to relax the requirement from MUST to MAY (and still other
4961 * language in RFC3315 supports this).
4963 * In lieu of a clarification of RFC3315, we will conform with the
4964 * MUST. Instead of an absent ORO, we will if there are no options
4965 * to request supply an empty ORO. Theoretically, an absent ORO is
4966 * difficult to interpret (does the client want all options or no
4967 * options?). A zero-length ORO is intuitively clear: requesting
4968 * nothing.
4970 buffer = NULL;
4971 oro_len = 0;
4972 buflen = 32;
4973 if (!buffer_allocate(&buffer, buflen, MDL))
4974 log_fatal("Out of memory constructing DHCPv6 ORO.");
4975 req = client->config->requested_options;
4976 if (req != NULL) {
4977 for (i = 0 ; req[i] != NULL ; i++) {
4978 if (buflen == oro_len) {
4979 struct buffer *tmpbuf = NULL;
4981 buflen += 32;
4983 /* Shell game. */
4984 buffer_reference(&tmpbuf, buffer, MDL);
4985 buffer_dereference(&buffer, MDL);
4987 if (!buffer_allocate(&buffer, buflen, MDL))
4988 log_fatal("Out of memory resizing "
4989 "DHCPv6 ORO buffer.");
4991 memcpy(buffer->data, tmpbuf->data, oro_len);
4993 buffer_dereference(&tmpbuf, MDL);
4996 if (req[i]->universe == &dhcpv6_universe) {
4997 /* Append the code to the ORO. */
4998 putUShort(buffer->data + oro_len,
4999 req[i]->code);
5000 oro_len += 2;
5005 oc = NULL;
5006 if (make_const_option_cache(&oc, &buffer, NULL, oro_len,
5007 oro_option, MDL)) {
5008 save_option(&dhcpv6_universe, *op, oc);
5009 } else {
5010 log_fatal("Unable to create ORO option cache.");
5014 * Note: make_const_option_cache() consumes the buffer, we do not
5015 * need to dereference it (XXX).
5017 option_cache_dereference(&oc, MDL);
5020 /* A clone of the DHCPv4 script_write_params() minus the DHCPv4-specific
5021 * filename, server-name, etc specifics.
5023 * Simply, store all values present in all universes of the option state
5024 * (probably derived from a DHCPv6 packet) into environment variables
5025 * named after the option names (and universe names) but with the 'prefix'
5026 * prepended.
5028 * Later, dhclient-script may compare for example "new_time_servers" and
5029 * "old_time_servers" for differences, and only upon detecting a change
5030 * bother to rewrite ntp.conf and restart it. Or something along those
5031 * generic lines.
5033 static void
5034 script_write_params6(struct client_state *client, const char *prefix,
5035 struct option_state *options)
5037 struct envadd_state es;
5038 int i;
5040 if (options == NULL)
5041 return;
5043 es.client = client;
5044 es.prefix = prefix;
5046 for (i = 0 ; i < options->universe_count ; i++) {
5047 option_space_foreach(NULL, NULL, client, NULL, options,
5048 &global_scope, universes[i], &es,
5049 client_option_envadd);
5054 * A clone of the DHCPv4 routine.
5055 * Write out the environment variables for the objects that the
5056 * client requested. If the object was requested the variable will be:
5057 * requested_<option_name>=1
5058 * If it wasn't requested there won't be a variable.
5060 static void script_write_requested6(client)
5061 struct client_state *client;
5063 int i;
5064 struct option **req;
5065 char name[256];
5066 req = client->config->requested_options;
5068 if (req == NULL)
5069 return;
5071 for (i = 0 ; req[i] != NULL ; i++) {
5072 if ((req[i]->universe == &dhcpv6_universe) &&
5073 dhcp_option_ev_name (name, sizeof(name), req[i])) {
5074 client_envadd(client, "requested_", name, "%d", 1);
5080 * Check if there is something not fully defined in the active lease.
5082 static isc_boolean_t
5083 active_prefix(struct client_state *client)
5085 struct dhc6_lease *lease;
5086 struct dhc6_ia *ia;
5087 struct dhc6_addr *pref;
5088 char zeros[16];
5090 lease = client->active_lease;
5091 if (lease == NULL)
5092 return ISC_FALSE;
5093 memset(zeros, 0, 16);
5094 for (ia = lease->bindings; ia != NULL; ia = ia->next) {
5095 if (ia->ia_type != D6O_IA_PD)
5096 continue;
5097 for (pref = ia->addrs; pref != NULL; pref = pref->next) {
5098 if (pref->plen == 0)
5099 return ISC_FALSE;
5100 if (pref->address.len != 16)
5101 return ISC_FALSE;
5102 if (memcmp(pref->address.iabuf, zeros, 16) == 0)
5103 return ISC_FALSE;
5106 return ISC_TRUE;
5108 #endif /* DHCPv6 */