1 /* $NetBSD: dhc6.c,v 1.6 2014/07/12 12:09:37 spz Exp $ */
2 /* dhc6.c - DHCPv6 client routines. */
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.
22 * Redwood City, CA 94063
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 $");
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
,
89 static isc_result_t
dhc6_add_ia_ta(struct client_state
*client
,
90 struct data_string
*packet
,
91 struct dhc6_lease
*lease
,
93 static isc_result_t
dhc6_add_ia_pd(struct client_state
*client
,
94 struct data_string
*packet
,
95 struct dhc6_lease
*lease
,
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
,
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
);
124 extern int stateless
;
127 * Assign DHCPv6 port numbers as a client.
130 dhcpv6_client_assignments(void)
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");
143 local_port
= htons(546);
145 local_port
= ent
->s_port
;
148 if (remote_port
== 0) {
149 ent
= getservbyname("dhcpv6-server", "udp");
151 remote_port
= htons(547);
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
);
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.");
175 if (!option_code_hash_lookup(&ia_na_option
, dhcpv6_universe
.code_hash
,
177 log_fatal("Unable to find the IA_NA option definition.");
180 if (!option_code_hash_lookup(&ia_ta_option
, dhcpv6_universe
.code_hash
,
182 log_fatal("Unable to find the IA_TA option definition.");
185 if (!option_code_hash_lookup(&ia_pd_option
, dhcpv6_universe
.code_hash
,
187 log_fatal("Unable to find the IA_PD option definition.");
190 if (!option_code_hash_lookup(&iaaddr_option
, dhcpv6_universe
.code_hash
,
192 log_fatal("Unable to find the IAADDR option definition.");
195 if (!option_code_hash_lookup(&iaprefix_option
,
196 dhcpv6_universe
.code_hash
,
198 log_fatal("Unable to find the IAPREFIX option definition.");
201 if (!option_code_hash_lookup(&oro_option
, dhcpv6_universe
.code_hash
,
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
,
208 log_fatal("Unable to find the IRT option definition.");
210 #ifndef __CYGWIN32__ /* XXX */
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:
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
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
242 * A zero or less timeout is a bad thing...we don't want to
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. */
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)]. */
270 /* Offset it to uncover potential negative values. */
276 /* Initialize message exchange timers (set RT from Initial-RT). */
278 dhc6_retrans_init(struct client_state
*client
)
282 /* Initialize timers. */
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)
290 #elif (RAND_MAX >= 0x0000ffff)
291 xid
= (random() << 16) ^ random();
292 #elif (RAND_MAX >= 0x000000ff)
293 xid
= (random() << 16) ^ (random() << 8) ^ random();
295 # error "Random number generator of less than 8 bits not supported."
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. */
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) {
314 elapsed
.tv_usec
+= 1000000;
316 /* retrans_advance is called after consuming client->RT. */
318 elapsed
.tv_sec
+= client
->RT
/ 100;
319 elapsed
.tv_usec
+= (client
->RT
% 100) * 10000;
320 if (elapsed
.tv_usec
>= 1000000) {
322 elapsed
.tv_usec
-= 1000000;
326 * RT for each subsequent message transmission is based on the previous
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:
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) {
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) {
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;
372 /* Quick validation of DHCPv6 ADVERTISE packet contents. */
374 valid_reply(struct packet
*packet
, struct client_state
*client
)
376 struct data_string sid
, cid
;
377 struct option_cache
*oc
;
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.");
388 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_CLIENTID
);
390 !evaluate_option_cache(&sid
, packet
, NULL
, client
, packet
->options
,
391 client
->sent_options
, &global_scope
, oc
,
393 log_error("Response without a client identifier.");
397 oc
= lookup_option(&dhcpv6_universe
, client
->sent_options
,
400 !evaluate_option_cache(&cid
, packet
, NULL
, client
,
401 client
->sent_options
, NULL
, &global_scope
,
403 log_error("Local client identifier is missing!");
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.");
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
);
429 log_error("Out of memory for v6 lease structure.");
433 data_string_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(©
->options
, lease
->options
, file
, line
);
441 insert_ia
= ©
->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(©
, file
, line
);
450 insert_ia
= &(*insert_ia
)->next
;
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
= ©
->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(©
, file
, line
);
483 insert_addr
= &(*insert_addr
)->next
;
486 if (ia
->options
!= NULL
)
487 option_state_reference(©
->options
, ia
->options
,
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
);
506 memcpy(©
->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(©
->options
, addr
->options
,
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
);
535 log_error("Out of memory for v6 lease structure.");
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
);
547 evaluate_option_cache(&ds
, packet
, NULL
, NULL
, lease
->options
,
548 NULL
, &global_scope
, oc
, MDL
)) {
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
);
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
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
);
576 * Dig into recursive DHCPv6 pockets for IA_TA and contained IAADDR
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
);
586 * Dig into recursive DHCPv6 pockets for IA_PD and contained IAPREFIX
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
);
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
);
604 !evaluate_option_cache(&lease
->server_id
, packet
, NULL
, NULL
,
605 lease
->options
, NULL
, &global_scope
,
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
);
614 log_debug("RCV: X-- Server ID: %s",
615 print_hex_1(lease
->server_id
.len
,
616 lease
->server_id
.data
, 52));
623 dhc6_parse_ia_na(struct dhc6_ia
**pia
, struct packet
*packet
,
624 struct option_state
*options
)
626 struct data_string ds
;
628 struct option_cache
*oc
;
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
);
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
,
641 &global_scope
, oc
, MDL
) &&
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
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.");
672 data_string_forget(&ds
, MDL
);
677 log_debug("RCV: | X-- [Options]");
679 if (!option_state_allocate(&ia
->options
,
681 log_error("Out of memory allocating "
682 "IA_NA option state.");
684 data_string_forget(&ds
, MDL
);
685 return ISC_R_NOMEMORY
;
688 if (!parse_option_buffer(ia
->options
,
692 log_error("Corrupt IA_NA options.");
693 option_state_dereference(&ia
->options
,
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
,
705 if (result
!= ISC_R_SUCCESS
) {
706 option_state_dereference(&ia
->options
,
718 log_error("Invalid IA_NA option cache.");
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
;
731 dhc6_parse_ia_ta(struct dhc6_ia
**pia
, struct packet
*packet
,
732 struct option_state
*options
)
734 struct data_string ds
;
736 struct option_cache
*oc
;
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
);
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
,
749 &global_scope
, oc
, MDL
) &&
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
);
762 log_debug("RCV: | X-- [Options]");
764 if (!option_state_allocate(&ia
->options
,
766 log_error("Out of memory allocating "
767 "IA_TA option state.");
769 data_string_forget(&ds
, MDL
);
770 return ISC_R_NOMEMORY
;
773 if (!parse_option_buffer(ia
->options
,
777 log_error("Corrupt IA_TA options.");
778 option_state_dereference(&ia
->options
,
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
,
790 if (result
!= ISC_R_SUCCESS
) {
791 option_state_dereference(&ia
->options
,
803 log_error("Invalid IA_TA option cache.");
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
;
816 dhc6_parse_ia_pd(struct dhc6_ia
**pia
, struct packet
*packet
,
817 struct option_state
*options
)
819 struct data_string ds
;
821 struct option_cache
*oc
;
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
);
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
,
834 &global_scope
, oc
, MDL
) &&
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.");
861 data_string_forget(&ds
, MDL
);
866 log_debug("RCV: | X-- [Options]");
868 if (!option_state_allocate(&ia
->options
,
870 log_error("Out of memory allocating "
871 "IA_PD option state.");
873 data_string_forget(&ds
, MDL
);
874 return ISC_R_NOMEMORY
;
877 if (!parse_option_buffer(ia
->options
,
881 log_error("Corrupt IA_PD options.");
882 option_state_dereference(&ia
->options
,
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
,
895 if (result
!= ISC_R_SUCCESS
) {
896 option_state_dereference(&ia
->options
,
908 log_error("Invalid IA_PD option cache.");
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
;
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
);
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
,
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.",
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.");
965 data_string_forget(&ds
, MDL
);
970 * Fortunately this is the last recursion in the
974 if (!option_state_allocate(&addr
->options
,
976 log_error("Out of memory allocating "
977 "IAADDR option state.");
979 data_string_forget(&ds
, MDL
);
980 return ISC_R_NOMEMORY
;
983 if (!parse_option_buffer(addr
->options
,
987 log_error("Corrupt IAADDR options.");
988 option_state_dereference(&addr
->options
,
991 data_string_forget(&ds
, MDL
);
992 return DHCP_R_BADPARSE
;
996 if (addr
->options
!= NULL
)
997 log_debug("RCV: | | | X-- "
1000 data_string_forget(&ds
, MDL
);
1003 paddr
= &addr
->next
;
1005 log_error("Invalid IAADDR option cache.");
1008 data_string_forget(&ds
, MDL
);
1009 return ISC_R_UNEXPECTED
;
1012 delete_option(&dhcpv6_universe
, options
, D6O_IAADDR
);
1014 return ISC_R_SUCCESS
;
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
);
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
,
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.",
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.");
1059 data_string_forget(&ds
, MDL
);
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.");
1071 data_string_forget(&ds
, MDL
);
1076 * Fortunately this is the last recursion in the
1080 if (!option_state_allocate(&pfx
->options
,
1082 log_error("Out of memory allocating "
1083 "IAPREFIX option state.");
1085 data_string_forget(&ds
, MDL
);
1086 return ISC_R_NOMEMORY
;
1089 if (!parse_option_buffer(pfx
->options
,
1092 &dhcpv6_universe
)) {
1093 log_error("Corrupt IAPREFIX options.");
1094 option_state_dereference(&pfx
->options
,
1097 data_string_forget(&ds
, MDL
);
1098 return DHCP_R_BADPARSE
;
1102 if (pfx
->options
!= NULL
)
1103 log_debug("RCV: | | | X-- "
1106 data_string_forget(&ds
, MDL
);
1111 log_error("Invalid IAPREFIX option cache.");
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. */
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.");
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
) {
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
);
1153 * Traverse the addresses list, and destroy their contents, and NULL the
1157 dhc6_ia_destroy(struct dhc6_ia
**src
, const char *file
, int line
)
1159 struct dhc6_addr
*addr
, *naddr
;
1162 if (src
== NULL
|| *src
== NULL
) {
1163 log_error("Attempt to destroy null IA.");
1168 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= naddr
) {
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
);
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.
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
);
1200 head
= &(*head
)->next
;
1208 * Not really clear what to do here yet.
1211 dhc6_score_lease(struct client_state
*client
, struct dhc6_lease
*lease
)
1214 struct dhc6_addr
*addr
;
1215 struct option
**req
;
1219 return lease
->score
;
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
;
1227 for (i
= 0 ; req
[i
] != NULL
; i
++) {
1228 if (lookup_option(&dhcpv6_universe
, lease
->options
,
1229 req
[i
]->code
) == NULL
) {
1231 return lease
->score
;
1236 /* If this lease contains a requested option, improve its score. */
1237 req
= client
->config
->requested_options
;
1239 for (i
= 0 ; req
[i
] != NULL
; i
++) {
1240 if (lookup_option(&dhcpv6_universe
, lease
->options
,
1241 req
[i
]->code
) != NULL
)
1246 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
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.
1262 start_init6(struct client_state
*client
)
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;
1273 /* Default is 0 (no max) but -1 changes this. */
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) {
1305 tv
.tv_usec
-= 1000000;
1307 add_timeout(&tv
, do_init6
, client
, NULL
, NULL
);
1314 * start_info_request6() kicks off the process, transmitting an info
1315 * request packet and scheduling a retransmission event.
1318 start_info_request6(struct client_state
*client
)
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;
1329 /* Default is 0 (no max) but -1 changes this. */
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) {
1349 tv
.tv_usec
-= 1000000;
1351 add_timeout(&tv
, do_info_request6
, client
, NULL
, NULL
);
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.
1363 start_confirm6(struct client_state
*client
)
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
);
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;
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) {
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
);
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
;
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;
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
);
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.
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
;
1497 int i
, idx
, len
, send_ret
;
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
);
1510 switch(check_timing6(client
, DHCPV6_SOLICIT
, "Solicit", NULL
, &ds
)) {
1511 case CHK_TIM_MRC_EXCEEDED
:
1512 case CHK_TIM_ALLOC_FAILURE
:
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())
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
,
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
;
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
);
1552 ia
.data
= ia
.buffer
->data
;
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;
1564 len
= client
->interface
->hw_address
.hlen
;
1566 memcpy(ia
.buffer
->data
,
1567 client
->interface
->hw_address
.hbuf
+ idx
,
1570 ia
.buffer
->data
[3] += i
;
1572 t1
= client
->config
->requested_lease
/ 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
,
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 "
1596 "Ignoring. (%s:%d)",
1597 old_addr
->address
.len
,
1602 if (!buffer_allocate(&addr
.buffer
, 24, MDL
)) {
1603 log_error("Unable to allocate memory "
1605 data_string_forget(&ia
, MDL
);
1606 data_string_forget(&ds
, MDL
);
1609 addr
.data
= addr
.buffer
->data
;
1612 memcpy(addr
.buffer
->data
,
1613 old_addr
->address
.iabuf
,
1616 t1
= client
->config
->requested_lease
;
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 "
1626 log_debug("XMT: | | X-- Request valid "
1630 append_option(&ia
, &dhcpv6_universe
,
1634 data_string_forget(&addr
, MDL
);
1638 append_option(&ds
, &dhcpv6_universe
, ia_na_option
, &ia
);
1639 data_string_forget(&ia
, MDL
);
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
);
1655 ia
.data
= ia
.buffer
->data
;
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;
1667 len
= client
->interface
->hw_address
.hlen
;
1669 memcpy(ia
.buffer
->data
,
1670 client
->interface
->hw_address
.hbuf
+ idx
,
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
,
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 "
1692 "Ignoring. (%s:%d)",
1693 old_addr
->address
.len
,
1698 if (!buffer_allocate(&addr
.buffer
, 24, MDL
)) {
1699 log_error("Unable to allocate memory "
1701 data_string_forget(&ia
, MDL
);
1702 data_string_forget(&ds
, MDL
);
1705 addr
.data
= addr
.buffer
->data
;
1708 memcpy(addr
.buffer
->data
,
1709 old_addr
->address
.iabuf
,
1712 t1
= client
->config
->requested_lease
;
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 "
1722 log_debug("XMT: | | X-- Request valid "
1726 append_option(&ia
, &dhcpv6_universe
,
1730 data_string_forget(&addr
, MDL
);
1734 append_option(&ds
, &dhcpv6_universe
, ia_ta_option
, &ia
);
1735 data_string_forget(&ia
, MDL
);
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
);
1751 ia
.data
= ia
.buffer
->data
;
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;
1763 len
= client
->interface
->hw_address
.hlen
;
1765 memcpy(ia
.buffer
->data
,
1766 client
->interface
->hw_address
.hbuf
+ idx
,
1769 ia
.buffer
->data
[3] += i
;
1771 t1
= client
->config
->requested_lease
/ 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
,
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)",
1799 if (!buffer_allocate(&addr
.buffer
, 25, MDL
)) {
1800 log_error("Unable to allocate memory "
1802 data_string_forget(&ia
, MDL
);
1803 data_string_forget(&ds
, MDL
);
1806 addr
.data
= addr
.buffer
->data
;
1809 t1
= client
->config
->requested_lease
;
1811 putULong(addr
.buffer
->data
, t1
);
1812 putULong(addr
.buffer
->data
+ 4, t2
);
1814 putUChar(addr
.buffer
->data
+ 8,
1816 memcpy(addr
.buffer
->data
+ 9,
1817 old_addr
->address
.iabuf
,
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 "
1826 log_debug("XMT: | | X-- Request valid "
1830 append_option(&ia
, &dhcpv6_universe
,
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",
1855 data_string_forget(&ds
, MDL
);
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) {
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. */
1871 do_info_request6(void *input
)
1873 struct client_state
*client
;
1874 struct data_string ds
;
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
:
1885 case CHK_TIM_MRD_EXCEEDED
:
1887 case CHK_TIM_SUCCESS
:
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
,
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",
1910 data_string_forget(&ds
, MDL
);
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) {
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.
1928 do_confirm6(void *input
)
1930 struct client_state
*client
;
1931 struct data_string ds
;
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
);
1960 case CHK_TIM_ALLOC_FAILURE
:
1962 case CHK_TIM_SUCCESS
:
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
,
1974 dhc6_add_ia_na(client
, &ds
, client
->active_lease
,
1975 DHCPV6_CONFIRM
) != ISC_R_SUCCESS
) {
1976 data_string_forget(&ds
, MDL
);
1980 dhc6_add_ia_ta(client
, &ds
, client
->active_lease
,
1981 DHCPV6_CONFIRM
) != ISC_R_SUCCESS
) {
1982 data_string_forget(&ds
, MDL
);
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
,
1994 if (send_ret
!= ds
.len
) {
1995 log_error("dhc6: sendpacket6() sent %d of %d bytes",
1999 data_string_forget(&ds
, MDL
);
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) {
2006 tv
.tv_usec
-= 1000000;
2008 add_timeout(&tv
, do_confirm6
, client
, NULL
, NULL
);
2010 dhc6_retrans_advance(client
);
2014 * Release addresses.
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
)
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;
2042 client
->MRC
= REL_MAX_RC
;
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.
2054 do_release6(void *input
)
2056 struct client_state
*client
;
2057 struct data_string ds
;
2063 if ((client
->active_lease
== NULL
) || !active_prefix(client
))
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
:
2072 case CHK_TIM_SUCCESS
:
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
,
2085 /* Append IA's (but don't release temporary addresses). */
2087 dhc6_add_ia_na(client
, &ds
, client
->active_lease
,
2088 DHCPV6_RELEASE
) != ISC_R_SUCCESS
) {
2089 data_string_forget(&ds
, MDL
);
2093 dhc6_add_ia_pd(client
, &ds
, client
->active_lease
,
2094 DHCPV6_RELEASE
) != ISC_R_SUCCESS
) {
2095 data_string_forget(&ds
, MDL
);
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
,
2106 if (send_ret
!= ds
.len
) {
2107 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2111 data_string_forget(&ds
, MDL
);
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) {
2118 tv
.tv_usec
-= 1000000;
2120 add_timeout(&tv
, do_release6
, client
, NULL
, NULL
);
2121 dhc6_retrans_advance(client
);
2125 dhc6_lease_destroy(&client
->active_lease
, MDL
);
2126 client
->active_lease
= NULL
;
2127 if (stopping_finished())
2131 /* status_log() just puts a status code into displayable form and logs it
2135 status_log(int code
, const char *scope
, const char *additional
, int len
)
2137 const char *msg
= NULL
;
2140 case STATUS_Success
:
2144 case STATUS_UnspecFail
:
2148 case STATUS_NoAddrsAvail
:
2149 msg
= "NoAddrsAvail";
2152 case STATUS_NoBinding
:
2156 case STATUS_NotOnLink
:
2160 case STATUS_UseMulticast
:
2161 msg
= "UseMulticast";
2164 case STATUS_NoPrefixAvail
:
2165 msg
= "NoPrefixAvail";
2174 log_info("%s status code %s: %s", scope
, msg
,
2176 (const unsigned char *)additional
, 50));
2178 log_info("%s status code %s.", scope
, msg
);
2181 /* Acquire a status code.
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
);
2204 evaluate_option_cache(&ds
, NULL
, NULL
, NULL
, options
,
2205 NULL
, &global_scope
, oc
, MDL
)) {
2207 log_error("Invalid status code length %d.", ds
.len
);
2208 rval
= DHCP_R_FORMERR
;
2210 *code
= getUShort(ds
.data
);
2212 if ((msg
!= NULL
) && (ds
.len
> 2)) {
2213 data_string_copy(msg
, &ds
, MDL
);
2218 data_string_forget(&ds
, MDL
);
2222 return ISC_R_NOTFOUND
;
2225 /* Look at status codes in an advertise, and reform the return value.
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
)
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.
2263 dhc6_check_advertise(struct dhc6_lease
*lease
)
2266 struct dhc6_addr
*addr
;
2267 isc_result_t rval
= ISC_R_SUCCESS
;
2268 int have_addrs
= ISC_FALSE
;
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
) {
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
)
2296 rval
= dhc6_check_status(rval
, addr
->options
,
2298 have_addrs
= ISC_TRUE
;
2302 if (have_addrs
!= ISC_TRUE
)
2303 rval
= ISC_R_ADDRNOTAVAIL
;
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
,
2316 log_fatal("Impossible condition at %s:%d.", MDL
);
2318 if (client
== NULL
) {
2319 *rvalp
= DHCP_R_INVALIDARG
;
2323 if (*rvalp
== ISC_R_SUCCESS
)
2326 /* No possible action in any case... */
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
,
2338 struct dhc6_lease
*lease
;
2342 log_fatal("Impossible condition at %s:%d.", MDL
);
2344 if (client
== NULL
) {
2345 *rvalp
= DHCP_R_INVALIDARG
;
2350 if (rval
== ISC_R_SUCCESS
)
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. */
2366 /* If the server can't deal with us, either try the
2367 * next advertised server, or continue retrying if there
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
);
2379 } else /* Take no action - continue to retry. */
2382 /* If the server has no addresses, try other servers if
2383 * we got some, otherwise go to INIT to hope for more
2386 case STATUS_NoAddrsAvail
:
2387 case STATUS_NoPrefixAvail
:
2388 if (client
->state
== S_REBOOTING
)
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
);
2400 start_init6(client
);
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
);
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
);
2439 dhc6_withdraw_lease(struct client_state
*client
)
2442 struct dhc6_addr
*addr
;
2444 if ((client
== NULL
) || (client
->active_lease
== NULL
))
2447 for (ia
= client
->active_lease
->bindings
; ia
!= NULL
;
2449 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
2450 addr
->max_life
= addr
->preferred_life
= 0;
2454 /* Perform expiry. */
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
,
2469 log_fatal("Impossible condition at %s:%d.", MDL
);
2471 if (client
== NULL
) {
2472 *rvalp
= DHCP_R_INVALIDARG
;
2477 if (rval
== ISC_R_SUCCESS
)
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. */
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
,
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
);
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
2535 case STATUS_NoAddrsAvail
:
2536 case STATUS_NoPrefixAvail
:
2537 /* Head back to init, keeping any active bindings (!). */
2538 start_init6(client
);
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
);
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
,
2570 log_fatal("Impossible condition at %s:%d.", MDL
);
2572 if (client
== NULL
) {
2573 *rvalp
= DHCP_R_INVALIDARG
;
2578 if (rval
== ISC_R_SUCCESS
)
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
:
2591 /* NoBinding is not an error */
2592 case STATUS_NoBinding
:
2593 if (rval
== ISC_R_FAILURE
)
2594 *rvalp
= ISC_R_SUCCESS
;
2597 /* Should not happen */
2598 case STATUS_NoAddrsAvail
:
2599 case STATUS_NoPrefixAvail
:
2603 case STATUS_NotOnLink
:
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
,
2623 /* Look at a new and old lease, and make sure the new information is not
2624 * losing us any state.
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);
2632 struct dhc6_addr
*addr
;
2633 isc_result_t rval
= ISC_R_SUCCESS
;
2638 if ((client
== NULL
) || (new == NULL
))
2639 return DHCP_R_INVALIDARG
;
2641 switch (client
->state
) {
2643 action
= dhc6_init_action
;
2648 action
= dhc6_select_action
;
2653 action
= dhc6_reply_action
;
2657 action
= dhc6_stop_action
;
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
) {
2685 log_error("dhc6_check_reply: no type.");
2686 return DHCP_R_INVALIDARG
;
2688 rval
= dhc6_check_status(rval
, ia
->options
,
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
)
2699 rval
= dhc6_check_status(rval
, addr
->options
,
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
)
2710 /* No old lease in rapid-commit. */
2711 if (client
->state
== S_INIT
)
2714 switch (client
->state
) {
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.",
2734 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
2735 client
->selected_lease
= NULL
;
2737 start_selecting6(client
);
2739 return ISC_R_CANCELED
;
2745 /* This leaves one RFC3315 status check unimplemented:
2747 * - sends a Renew/Rebind if the IA is not in the Reply
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.
2758 /* Nothing critical to do at this stage. */
2762 log_fatal("REALLY impossible condition at %s:%d.", MDL
);
2763 return ISC_R_CANCELED
;
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).
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
)
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.");
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
);
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
);
2820 log_debug("RCV: Advertisement recorded.");
2823 /* info_request_handler() accepts a Reply to an Info-request.
2826 info_request_handler(struct packet
*packet
, struct client_state
*client
)
2828 isc_result_t check_status
;
2831 if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
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.");
2842 check_status
= dhc6_check_status(ISC_R_SUCCESS
, packet
->options
,
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
)
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
)
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.
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
);
2892 } else if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
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.");
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.");
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.
2918 check_status
= dhc6_check_reply(client
, lease
);
2919 if (check_status
!= ISC_R_SUCCESS
) {
2920 dhc6_lease_destroy(&lease
, MDL
);
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
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
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
;
2990 if (head
== NULL
|| *head
== NULL
)
2995 rscore
= dhc6_score_lease(client
, rval
);
2996 candp
= &rval
->next
;
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
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
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.");
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, "
3045 } else if (cscore
< rscore
) {
3046 log_debug("PRC: | X-- Rejected, equal preference, "
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.");
3057 log_debug("PRC: | X-- Rejected, equal preference, "
3058 "equal score, binary greater server ID.");
3067 /* Remove the selected lease from the chain. */
3073 /* Select a lease out of the advertised leases and setup state to try and
3074 * acquire that lease.
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!");
3087 log_debug("PRC: Selecting best advertised lease.");
3088 client
->state
= S_SELECTING
;
3090 lease
= dhc6_best_lease(client
, &client
->advertised_leases
);
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
;
3103 dhc6_retrans_init(client
);
3105 client
->v6_handler
= reply_handler
;
3107 /* ("re")transmit the first packet. */
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.
3116 do_select6(void *input
)
3118 struct client_state
*client
;
3119 struct dhc6_lease
*lease
;
3120 struct data_string ds
;
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 "
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
);
3149 start_init6(client
);
3151 case CHK_TIM_ALLOC_FAILURE
:
3153 case CHK_TIM_SUCCESS
:
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
,
3174 /* Now append any IA's, and within them any IAADDR/IAPREFIXs. */
3176 dhc6_add_ia_na(client
, &ds
, lease
,
3177 DHCPV6_REQUEST
) != ISC_R_SUCCESS
) {
3178 data_string_forget(&ds
, MDL
);
3182 dhc6_add_ia_ta(client
, &ds
, lease
,
3183 DHCPV6_REQUEST
) != ISC_R_SUCCESS
) {
3184 data_string_forget(&ds
, MDL
);
3188 dhc6_add_ia_pd(client
, &ds
, lease
,
3189 DHCPV6_REQUEST
) != ISC_R_SUCCESS
) {
3190 data_string_forget(&ds
, MDL
);
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",
3205 data_string_forget(&ds
, MDL
);
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) {
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.
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
;
3230 isc_result_t rval
= ISC_R_SUCCESS
;
3233 memset(&iads
, 0, sizeof(iads
));
3234 memset(&addrds
, 0, sizeof(addrds
));
3235 for (ia
= lease
->bindings
;
3236 ia
!= NULL
&& rval
== ISC_R_SUCCESS
;
3238 if (ia
->ia_type
!= D6O_IA_NA
)
3241 if (!buffer_allocate(&iads
.buffer
, 12, MDL
)) {
3242 log_error("Unable to allocate memory for IA_NA.");
3243 rval
= ISC_R_NOMEMORY
;
3247 /* Copy the IAID into the packet buffer. */
3248 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
3249 iads
.data
= iads
.buffer
->data
;
3253 case DHCPV6_REQUEST
:
3257 t1
= client
->config
->requested_lease
/ 2;
3259 #if MAX_TIME > 0xffffffff
3260 if (t1
> 0xffffffff)
3262 if (t2
> 0xffffffff)
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",
3272 log_debug("XMT: | X-- Requested rebind +%u",
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));
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
3296 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
3299 if (addr
->address
.len
!= 16) {
3300 log_error("Illegal IPv6 address length (%d), "
3301 "ignoring. (%s:%d)",
3302 addr
->address
.len
, MDL
);
3306 if (!buffer_allocate(&addrds
.buffer
, 24, MDL
)) {
3307 log_error("Unable to allocate memory for "
3309 rval
= ISC_R_NOMEMORY
;
3313 addrds
.data
= addrds
.buffer
->data
;
3316 /* Copy the address into the packet buffer. */
3317 memcpy(addrds
.buffer
->data
, addr
->address
.iabuf
, 16);
3319 /* Copy in additional information as appropriate */
3321 case DHCPV6_REQUEST
:
3324 t1
= client
->config
->requested_lease
;
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",
3338 case DHCPV6_CONFIRM
:
3340 * Set preferred and max life to zero,
3343 memset(addrds
.buffer
->data
+ 16, 0, 8);
3344 log_debug("XMT: | X-- Confirm Address %s",
3345 piaddr(addr
->address
));
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
));
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
));
3363 log_fatal("Impossible condition at %s:%d.",
3367 append_option(&iads
, &dhcpv6_universe
, iaaddr_option
,
3369 data_string_forget(&addrds
, MDL
);
3373 * It doesn't make sense to make a request without an
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
,
3385 data_string_forget(&iads
, MDL
);
3391 /* For each IA_TA in the lease, for each address in the IA_TA,
3392 * append that information onto the packet-so-far.
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
;
3402 isc_result_t rval
= ISC_R_SUCCESS
;
3405 memset(&iads
, 0, sizeof(iads
));
3406 memset(&addrds
, 0, sizeof(addrds
));
3407 for (ia
= lease
->bindings
;
3408 ia
!= NULL
&& rval
== ISC_R_SUCCESS
;
3410 if (ia
->ia_type
!= D6O_IA_TA
)
3413 if (!buffer_allocate(&iads
.buffer
, 4, MDL
)) {
3414 log_error("Unable to allocate memory for IA_TA.");
3415 rval
= ISC_R_NOMEMORY
;
3419 /* Copy the IAID into the packet buffer. */
3420 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
3421 iads
.data
= iads
.buffer
->data
;
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
3433 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
3436 if (addr
->address
.len
!= 16) {
3437 log_error("Illegal IPv6 address length (%d), "
3438 "ignoring. (%s:%d)",
3439 addr
->address
.len
, MDL
);
3443 if (!buffer_allocate(&addrds
.buffer
, 24, MDL
)) {
3444 log_error("Unable to allocate memory for "
3446 rval
= ISC_R_NOMEMORY
;
3450 addrds
.data
= addrds
.buffer
->data
;
3453 /* Copy the address into the packet buffer. */
3454 memcpy(addrds
.buffer
->data
, addr
->address
.iabuf
, 16);
3456 /* Copy in additional information as appropriate */
3458 case DHCPV6_REQUEST
:
3461 t1
= client
->config
->requested_lease
;
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",
3475 case DHCPV6_CONFIRM
:
3477 * Set preferred and max life to zero,
3480 memset(addrds
.buffer
->data
+ 16, 0, 8);
3481 log_debug("XMT: | X-- Confirm Address %s",
3482 piaddr(addr
->address
));
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
));
3493 log_fatal("Impossible condition at %s:%d.",
3497 append_option(&iads
, &dhcpv6_universe
, iaaddr_option
,
3499 data_string_forget(&addrds
, MDL
);
3503 * It doesn't make sense to make a request without an
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
,
3515 data_string_forget(&iads
, MDL
);
3521 /* For each IA_PD in the lease, for each prefix in the IA_PD,
3522 * append that information onto the packet-so-far.
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
;
3532 isc_result_t rval
= ISC_R_SUCCESS
;
3535 memset(&iads
, 0, sizeof(iads
));
3536 memset(&prefds
, 0, sizeof(prefds
));
3537 for (ia
= lease
->bindings
;
3538 ia
!= NULL
&& rval
== ISC_R_SUCCESS
;
3540 if (ia
->ia_type
!= D6O_IA_PD
)
3543 if (!buffer_allocate(&iads
.buffer
, 12, MDL
)) {
3544 log_error("Unable to allocate memory for IA_PD.");
3545 rval
= ISC_R_NOMEMORY
;
3549 /* Copy the IAID into the packet buffer. */
3550 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
3551 iads
.data
= iads
.buffer
->data
;
3555 case DHCPV6_REQUEST
:
3559 t1
= client
->config
->requested_lease
/ 2;
3561 #if MAX_TIME > 0xffffffff
3562 if (t1
> 0xffffffff)
3564 if (t2
> 0xffffffff)
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",
3574 log_debug("XMT: | X-- Requested rebind +%u",
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));
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
3596 if (pref
->flags
& DHC6_ADDR_EXPIRED
)
3599 if (pref
->address
.len
!= 16) {
3600 log_error("Illegal IPv6 prefix "
3601 "ignoring. (%s:%d)",
3606 if (pref
->plen
== 0) {
3607 log_info("Null IPv6 prefix, "
3608 "ignoring. (%s:%d)",
3612 if (!buffer_allocate(&prefds
.buffer
, 25, MDL
)) {
3613 log_error("Unable to allocate memory for "
3615 rval
= ISC_R_NOMEMORY
;
3619 prefds
.data
= prefds
.buffer
->data
;
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
,
3628 /* Copy in additional information as appropriate */
3630 case DHCPV6_REQUEST
:
3633 t1
= client
->config
->requested_lease
;
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",
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
);
3657 log_fatal("Impossible condition at %s:%d.",
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
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
);
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
)
3697 if (client
->active_lease
!= NULL
)
3704 /* reply_handler() accepts a Reply while we're attempting Select or Renew or
3705 * Rebind. Basically any Reply packet.
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
)
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.");
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.
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
)
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
)
3754 dhc6_lease_destroy(&client
->active_lease
, MDL
);
3755 client
->active_lease
= NULL
;
3756 /* We should never wait for nothing!? */
3757 if (stopping_finished())
3762 /* Action was taken, so now that we've torn down our scheduled
3763 * retransmissions, return.
3765 if (check_status
== ISC_R_CANCELED
)
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
);
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.
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
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
);
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
);
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",
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
));
3870 client_envadd(client
, prefix
, "iaid", "%s",
3871 print_hex_1(4, ia
->iaid
, 12));
3872 client_envadd(client
, prefix
, "starts", "%d",
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.
3883 dhc6_check_times(struct client_state
*client
)
3885 struct dhc6_lease
*lease
;
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
;
3893 lease
= client
->active_lease
;
3895 /* Bit spammy. We should probably keep record of scheduled
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)
3914 tmp
= addr
->starts
+
3915 addr
->preferred_life
;
3921 if (!(addr
->flags
& DHC6_ADDR_EXPIRED
)) {
3922 /* Find EPOCH-relative expiration. */
3923 if (addr
->max_life
== 0xffffffff)
3926 tmp
= addr
->starts
+ addr
->max_life
;
3928 /* Make the times ia->starts relative. */
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
;
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;
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)
3963 tmp
= ia
->starts
+ ia
->renew
;
3968 if (ia
->rebind
== 0) {
3969 /* Set rebind to 3/4 expiration interval. */
3971 tmp
+= use_expire
+ (use_expire
/ 2);
3972 } else if (ia
->rebind
== 0xffffffff)
3975 tmp
= ia
->starts
+ ia
->rebind
;
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
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
);
4012 switch(client
->state
) {
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
;
4025 add_timeout(&tv
, start_renew6
, client
, NULL
, NULL
);
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
;
4044 add_timeout(&tv
, start_rebind6
, client
, NULL
, NULL
);
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
;
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
));
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
;
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
)
4086 for (ia
= head
; ia
!= NULL
; ia
= ia
->next
) {
4087 if (ia
->ia_type
!= type
)
4089 if (memcmp(ia
->iaid
, id
, 4) == 0)
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))
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
,
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.
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
;
4141 if ((dst
== NULL
) || (src
== NULL
))
4144 for (sia
= src
->bindings
; sia
!= NULL
; sia
= sia
->next
) {
4145 dia
= find_ia(dst
->bindings
, sia
->ia_type
, (char *)sia
->iaid
);
4148 tia
= dhc6_dup_ia(sia
, MDL
);
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
;
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
,
4166 daddr
= find_pref(dia
->addrs
,
4170 if (daddr
== NULL
) {
4171 taddr
= dhc6_dup_addr(saddr
, MDL
);
4174 log_fatal("Out of memory "
4176 "Unable to continue "
4181 /* XXX: consider sorting? */
4182 taddr
->next
= dia
->addrs
;
4190 /* If we made changes, reset the score to 0 so it is recalculated. */
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
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
;
4207 #if defined (NSUPDATE)
4208 TIME dns_update_offset
= 1;
4211 lease
= client
->active_lease
;
4212 if (lease
== NULL
) {
4213 log_error("Cannot enter bound state unless an active lease "
4217 lease
->released
= ISC_FALSE
;
4218 old
= client
->old_lease
;
4220 client
->v6_handler
= bound_handler
;
4222 switch (client
->state
) {
4224 case S_REBOOTING
: /* Pretend we got bound. */
4237 log_fatal("Impossible condition at %s:%d.", MDL
);
4238 /* Silence compiler warnings. */
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);
4250 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
4252 oldia
= find_ia(old
->bindings
,
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
,
4264 oldaddr
= find_pref(oldia
->addrs
,
4270 #if defined (NSUPDATE)
4271 if ((oldaddr
== NULL
) && (ia
->ia_type
== D6O_IA_NA
))
4272 dhclient_schedule_updates(client
,
4274 dns_update_offset
++);
4277 /* Shell out to setup the new binding. */
4278 script_init(client
, reason
, NULL
);
4281 dhc6_marshall_values("old_", client
, old
,
4283 dhc6_marshall_values("new_", client
, lease
, ia
, addr
);
4284 script_write_requested6(client
);
4289 /* XXX: maybe we should loop on the old values instead? */
4290 if (ia
->addrs
== NULL
) {
4291 script_init(client
, reason
, NULL
);
4294 dhc6_marshall_values("old_", client
, old
,
4297 oldia
->addrs
: NULL
);
4299 dhc6_marshall_values("new_", client
, lease
, ia
,
4301 script_write_requested6(client
);
4307 /* XXX: maybe we should loop on the old values instead? */
4308 if (lease
->bindings
== NULL
) {
4309 script_init(client
, reason
, NULL
);
4312 dhc6_marshall_values("old_", client
, old
,
4314 (old
->bindings
!= NULL
) ?
4315 old
->bindings
->addrs
: NULL
);
4317 dhc6_marshall_values("new_", client
, lease
, NULL
, NULL
);
4318 script_write_requested6(client
);
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.
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.
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;
4364 /* MRD is special in renew - we need to set it by checking timer
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.
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
;
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.");
4399 /* Ensure we're emitting a valid message type. */
4400 switch (client
->refresh_type
) {
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
);
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
,
4441 log_error("Invalid unicast option length %d.", ds
.len
);
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.");
4461 ds
.data
= ds
.buffer
->data
;
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;
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
]);
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
,
4497 dhc6_add_ia_na(client
, &ds
, lease
,
4498 client
->refresh_type
) != ISC_R_SUCCESS
) {
4499 data_string_forget(&ds
, MDL
);
4503 dhc6_add_ia_pd(client
, &ds
, lease
,
4504 client
->refresh_type
) != ISC_R_SUCCESS
) {
4505 data_string_forget(&ds
, MDL
);
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",
4521 data_string_forget(&ds
, MDL
);
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) {
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
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;
4557 /* MRD is special in rebind - it's determined by the timer
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.
4575 do_depref(void *input
)
4577 struct client_state
*client
;
4578 struct dhc6_lease
*lease
;
4580 struct dhc6_addr
*addr
;
4582 client
= (struct client_state
*)input
;
4584 lease
= client
->active_lease
;
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
)
4593 if (addr
->starts
+ addr
->preferred_life
<= cur_time
) {
4594 script_init(client
, "DEPREF6", NULL
);
4595 dhc6_marshall_values("cur_", client
, lease
,
4597 script_write_requested6(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
));
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
,
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.
4628 do_expire(void *input
)
4630 struct client_state
*client
;
4631 struct dhc6_lease
*lease
;
4633 struct dhc6_addr
*addr
;
4634 int has_addrs
= ISC_FALSE
;
4636 client
= (struct client_state
*)input
;
4638 lease
= client
->active_lease
;
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
)
4647 if (addr
->starts
+ addr
->max_life
<= cur_time
) {
4648 script_init(client
, "EXPIRE6", NULL
);
4649 dhc6_marshall_values("old_", client
, lease
,
4651 script_write_requested6(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
));
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
,
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
);
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.
4706 unconfigure6(struct client_state
*client
, const char *reason
)
4709 struct dhc6_addr
*addr
;
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
);
4721 if (client
->active_lease
== NULL
)
4724 for (ia
= client
->active_lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
4725 if (ia
->ia_type
== D6O_IA_TA
)
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
);
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
);
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).
4756 dhc6_check_irt(struct client_state
*client
)
4758 struct option
**req
;
4759 struct option_cache
*oc
;
4760 TIME expire
= MAX_TIME
;
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
) {
4774 /* Simply return gives a endless loop waiting for nothing. */
4778 oc
= lookup_option(&dhcpv6_universe
, client
->active_lease
->options
,
4779 D6O_INFORMATION_REFRESH_TIME
);
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
) ||
4788 log_error("Can't evaluate IRT.");
4790 expire
= getULong(irt
.data
);
4791 if (expire
< IRT_MINIMUM
)
4792 expire
= IRT_MINIMUM
;
4793 if (expire
== 0xffffffff)
4796 data_string_forget(&irt
, MDL
);
4798 expire
= IRT_DEFAULT
;
4800 if (expire
!= MAX_TIME
) {
4801 log_debug("PRC: Refresh event scheduled in %u seconds.",
4803 tv
.tv_sec
= cur_time
+ expire
;
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.
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
);
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.
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.
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
))
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. */
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
,
4890 client
->config
->on_transmission
,
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
,
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
,
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
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
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
4973 if (!buffer_allocate(&buffer
, buflen
, MDL
))
4974 log_fatal("Out of memory constructing DHCPv6 ORO.");
4975 req
= client
->config
->requested_options
;
4977 for (i
= 0 ; req
[i
] != NULL
; i
++) {
4978 if (buflen
== oro_len
) {
4979 struct buffer
*tmpbuf
= NULL
;
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
,
5006 if (make_const_option_cache(&oc
, &buffer
, NULL
, oro_len
,
5008 save_option(&dhcpv6_universe
, *op
, oc
);
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'
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
5034 script_write_params6(struct client_state
*client
, const char *prefix
,
5035 struct option_state
*options
)
5037 struct envadd_state es
;
5040 if (options
== NULL
)
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
;
5064 struct option
**req
;
5066 req
= client
->config
->requested_options
;
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
;
5087 struct dhc6_addr
*pref
;
5090 lease
= client
->active_lease
;
5093 memset(zeros
, 0, 16);
5094 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
5095 if (ia
->ia_type
!= D6O_IA_PD
)
5097 for (pref
= ia
->addrs
; pref
!= NULL
; pref
= pref
->next
) {
5098 if (pref
->plen
== 0)
5100 if (pref
->address
.len
!= 16)
5102 if (memcmp(pref
->address
.iabuf
, zeros
, 16) == 0)