1 /* dhc6.c - DHCPv6 client routines. */
4 * Copyright (c) 2012-2016 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Internet Systems Consortium, Inc.
21 * Redwood City, CA 94063
23 * https://www.isc.org/
30 struct sockaddr_in6 DHCPv6DestAddr
;
33 * Option definition structures that are used by the software - declared
34 * here once and assigned at startup to save lookups.
36 struct option
*clientid_option
= NULL
;
37 struct option
*elapsed_option
= NULL
;
38 struct option
*ia_na_option
= NULL
;
39 struct option
*ia_ta_option
= NULL
;
40 struct option
*ia_pd_option
= NULL
;
41 struct option
*iaaddr_option
= NULL
;
42 struct option
*iaprefix_option
= NULL
;
43 struct option
*oro_option
= NULL
;
44 struct option
*irt_option
= NULL
;
46 static struct dhc6_lease
*dhc6_dup_lease(struct dhc6_lease
*lease
,
47 const char *file
, int line
);
48 static struct dhc6_ia
*dhc6_dup_ia(struct dhc6_ia
*ia
,
49 const char *file
, int line
);
50 static struct dhc6_addr
*dhc6_dup_addr(struct dhc6_addr
*addr
,
51 const char *file
, int line
);
52 static void dhc6_ia_destroy(struct dhc6_ia
**src
, const char *file
, int line
);
53 static isc_result_t
dhc6_parse_ia_na(struct dhc6_ia
**pia
,
54 struct packet
*packet
,
55 struct option_state
*options
,
57 static isc_result_t
dhc6_parse_ia_ta(struct dhc6_ia
**pia
,
58 struct packet
*packet
,
59 struct option_state
*options
,
61 static isc_result_t
dhc6_parse_ia_pd(struct dhc6_ia
**pia
,
62 struct packet
*packet
,
63 struct option_state
*options
,
65 static isc_result_t
dhc6_parse_addrs(struct dhc6_addr
**paddr
,
66 struct packet
*packet
,
67 struct option_state
*options
);
68 static isc_result_t
dhc6_parse_prefixes(struct dhc6_addr
**ppref
,
69 struct packet
*packet
,
70 struct option_state
*options
);
71 static struct dhc6_ia
*find_ia(struct dhc6_ia
*head
,
72 u_int16_t type
, const char *id
);
73 static struct dhc6_addr
*find_addr(struct dhc6_addr
*head
,
74 struct iaddr
*address
);
75 static struct dhc6_addr
*find_pref(struct dhc6_addr
*head
,
76 struct iaddr
*prefix
, u_int8_t plen
);
77 void init_handler(struct packet
*packet
, struct client_state
*client
);
78 void info_request_handler(struct packet
*packet
, struct client_state
*client
);
79 void rapid_commit_handler(struct packet
*packet
, struct client_state
*client
);
80 void do_init6(void *input
);
81 void do_info_request6(void *input
);
82 void do_confirm6(void *input
);
83 void reply_handler(struct packet
*packet
, struct client_state
*client
);
84 static isc_result_t
dhc6_create_iaid(struct client_state
*client
,
85 struct data_string
*ia
,
88 static int dhc6_count_ia(struct dhc6_lease
*lease
,
90 static isc_result_t
dhc6_bare_ia_xx(struct client_state
*client
,
91 struct data_string
*packet
,
94 static isc_result_t
dhc6_add_ia_na(struct client_state
*client
,
95 struct data_string
*packet
,
96 struct dhc6_lease
*lease
,
100 static isc_result_t
dhc6_add_ia_ta(struct client_state
*client
,
101 struct data_string
*packet
,
102 struct dhc6_lease
*lease
,
106 static isc_result_t
dhc6_add_ia_pd(struct client_state
*client
,
107 struct data_string
*packet
,
108 struct dhc6_lease
*lease
,
112 static isc_boolean_t
stopping_finished(void);
113 static void dhc6_merge_lease(struct dhc6_lease
*src
, struct dhc6_lease
*dst
);
114 void do_select6(void *input
);
115 void do_refresh6(void *input
);
116 static void do_release6(void *input
);
117 static void start_bound(struct client_state
*client
);
118 static void start_informed(struct client_state
*client
);
119 void informed_handler(struct packet
*packet
, struct client_state
*client
);
120 void bound_handler(struct packet
*packet
, struct client_state
*client
);
121 void start_renew6(void *input
);
122 void start_rebind6(void *input
);
123 void do_depref(void *input
);
124 void do_expire(void *input
);
125 static void make_client6_options(struct client_state
*client
,
126 struct option_state
**op
,
127 struct dhc6_lease
*lease
, u_int8_t message
);
128 static void script_write_params6(struct client_state
*client
,
130 struct option_state
*options
);
131 static void script_write_requested6(struct client_state
*client
);
132 static isc_boolean_t
active_prefix(struct client_state
*client
);
134 static int check_timing6(struct client_state
*client
, u_int8_t msg_type
,
135 char *msg_str
, struct dhc6_lease
*lease
,
136 struct data_string
*ds
);
137 static isc_result_t
dhc6_get_status_code(struct option_state
*options
,
139 struct data_string
*msg
);
140 static isc_result_t
dhc6_check_status(isc_result_t rval
,
141 struct option_state
*options
,
146 extern int stateless
;
149 * Assign DHCPv6 port numbers as a client.
152 dhcpv6_client_assignments(void)
157 if (path_dhclient_pid
== NULL
)
158 path_dhclient_pid
= _PATH_DHCLIENT6_PID
;
159 if (path_dhclient_db
== NULL
)
160 path_dhclient_db
= _PATH_DHCLIENT6_DB
;
162 if (local_port
== 0) {
163 ent
= getservbyname("dhcpv6-client", "udp");
165 local_port
= htons(546);
167 local_port
= ent
->s_port
;
170 if (remote_port
== 0) {
171 ent
= getservbyname("dhcpv6-server", "udp");
173 remote_port
= htons(547);
175 remote_port
= ent
->s_port
;
178 memset(&DHCPv6DestAddr
, 0, sizeof(DHCPv6DestAddr
));
179 DHCPv6DestAddr
.sin6_family
= AF_INET6
;
180 DHCPv6DestAddr
.sin6_port
= remote_port
;
181 if (inet_pton(AF_INET6
, All_DHCP_Relay_Agents_and_Servers
,
182 &DHCPv6DestAddr
.sin6_addr
) <= 0) {
183 log_fatal("Bad address %s", All_DHCP_Relay_Agents_and_Servers
);
187 if (!option_code_hash_lookup(&clientid_option
,
188 dhcpv6_universe
.code_hash
, &code
, 0, MDL
))
189 log_fatal("Unable to find the CLIENTID option definition.");
191 code
= D6O_ELAPSED_TIME
;
192 if (!option_code_hash_lookup(&elapsed_option
,
193 dhcpv6_universe
.code_hash
, &code
, 0, MDL
))
194 log_fatal("Unable to find the ELAPSED_TIME option definition.");
197 if (!option_code_hash_lookup(&ia_na_option
, dhcpv6_universe
.code_hash
,
199 log_fatal("Unable to find the IA_NA option definition.");
202 if (!option_code_hash_lookup(&ia_ta_option
, dhcpv6_universe
.code_hash
,
204 log_fatal("Unable to find the IA_TA option definition.");
207 if (!option_code_hash_lookup(&ia_pd_option
, dhcpv6_universe
.code_hash
,
209 log_fatal("Unable to find the IA_PD option definition.");
212 if (!option_code_hash_lookup(&iaaddr_option
, dhcpv6_universe
.code_hash
,
214 log_fatal("Unable to find the IAADDR option definition.");
217 if (!option_code_hash_lookup(&iaprefix_option
,
218 dhcpv6_universe
.code_hash
,
220 log_fatal("Unable to find the IAPREFIX option definition.");
223 if (!option_code_hash_lookup(&oro_option
, dhcpv6_universe
.code_hash
,
225 log_fatal("Unable to find the ORO option definition.");
227 code
= D6O_INFORMATION_REFRESH_TIME
;
228 if (!option_code_hash_lookup(&irt_option
, dhcpv6_universe
.code_hash
,
230 log_fatal("Unable to find the IRT option definition.");
232 #ifndef __CYGWIN32__ /* XXX */
238 * Instead of implementing RFC3315 RAND (section 14) as a float "between"
239 * -0.1 and 0.1 non-inclusive, we implement it as an integer.
241 * The result is expected to follow this table:
244 * - ERROR - base <= 0
245 * 0 1 0..0 1 <= base <= 10
246 * 1 3 -1..1 11 <= base <= 20
247 * 2 5 -2..2 21 <= base <= 30
248 * 3 7 -3..3 31 <= base <= 40
251 * XXX: For this to make sense, we really need to do timing on a
252 * XXX: usec scale...we currently can assume zero for any value less than
253 * XXX: 11, which are very common in early stages of transmission for most
264 * A zero or less timeout is a bad thing...we don't want to
268 log_fatal("Impossible condition at %s:%d.", MDL
);
271 * The first thing we do is count how many random integers we want
272 * in either direction (best thought of as the maximum negative
273 * integer, as we will subtract this potentially from a random 0).
275 split
= (base
- 1) / 10;
277 /* Don't bother with the rest of the math if we know we'll get 0. */
282 * Then we count the total number of integers in this set. This
283 * is twice the number of integers in positive and negative
284 * directions, plus zero (-1, 0, 1 is 3, -2..2 adds 2 to 5, so forth).
286 range
= (split
* 2) + 1;
288 /* Take a random number from [0..(range-1)]. */
292 /* Offset it to uncover potential negative values. */
298 /* Initialize message exchange timers (set RT from Initial-RT). */
300 dhc6_retrans_init(struct client_state
*client
)
304 /* Initialize timers. */
306 client
->RT
= client
->IRT
+ dhc6_rand(client
->IRT
);
308 /* Generate a new random 24-bit transaction ID for this exchange. */
310 #if (RAND_MAX >= 0x00ffffff)
312 #elif (RAND_MAX >= 0x0000ffff)
313 xid
= (random() << 16) ^ random();
314 #elif (RAND_MAX >= 0x000000ff)
315 xid
= (random() << 16) ^ (random() << 8) ^ random();
317 # error "Random number generator of less than 8 bits not supported."
320 client
->dhcpv6_transaction_id
[0] = (xid
>> 16) & 0xff;
321 client
->dhcpv6_transaction_id
[1] = (xid
>> 8) & 0xff;
322 client
->dhcpv6_transaction_id
[2] = xid
& 0xff;
325 /* Advance the DHCPv6 retransmission state once. */
327 dhc6_retrans_advance(struct client_state
*client
)
329 struct timeval elapsed
, elapsed_plus_rt
;
331 /* elapsed = cur - start */
332 elapsed
.tv_sec
= cur_tv
.tv_sec
- client
->start_time
.tv_sec
;
333 elapsed
.tv_usec
= cur_tv
.tv_usec
- client
->start_time
.tv_usec
;
334 if (elapsed
.tv_usec
< 0) {
336 elapsed
.tv_usec
+= 1000000;
338 /* retrans_advance is called after consuming client->RT. */
340 elapsed
.tv_sec
+= client
->RT
/ 100;
341 elapsed
.tv_usec
+= (client
->RT
% 100) * 10000;
342 if (elapsed
.tv_usec
>= 1000000) {
344 elapsed
.tv_usec
-= 1000000;
347 * Save what the time will be after the current RT to determine
348 * what the delta to MRD will be.
350 elapsed_plus_rt
.tv_sec
= elapsed
.tv_sec
;
351 elapsed_plus_rt
.tv_usec
= elapsed
.tv_usec
;
354 * RT for each subsequent message transmission is based on the previous
357 * RT = 2*RTprev + RAND*RTprev
359 client
->RT
+= client
->RT
+ dhc6_rand(client
->RT
);
362 * MRT specifies an upper bound on the value of RT (disregarding the
363 * randomization added by the use of RAND). If MRT has a value of 0,
364 * there is no upper limit on the value of RT. Otherwise:
367 * RT = MRT + RAND*MRT
369 if ((client
->MRT
!= 0) && (client
->RT
> client
->MRT
))
370 client
->RT
= client
->MRT
+ dhc6_rand(client
->MRT
);
373 * Further, if there's an MRD, we should wake up upon reaching
374 * the MRD rather than at some point after it.
376 if (client
->MRD
== 0) {
381 /* elapsed += client->RT */
382 elapsed
.tv_sec
+= client
->RT
/ 100;
383 elapsed
.tv_usec
+= (client
->RT
% 100) * 10000;
384 if (elapsed
.tv_usec
>= 1000000) {
386 elapsed
.tv_usec
-= 1000000;
388 if (elapsed
.tv_sec
>= client
->MRD
) {
390 * The desired RT is the time that will be remaining in MRD
391 * when the current timeout finishes. We then have
392 * desired RT = MRD - (elapsed time + previous RT); or
393 * desired RT = MRD - elapsed_plut_rt;
395 client
->RT
= client
->MRD
- elapsed_plus_rt
.tv_sec
;
396 client
->RT
= (client
->RT
* 100) -
397 (elapsed_plus_rt
.tv_usec
/ 10000);
404 /* Quick validation of DHCPv6 ADVERTISE packet contents. */
406 valid_reply(struct packet
*packet
, struct client_state
*client
)
408 struct data_string sid
, cid
;
409 struct option_cache
*oc
;
412 memset(&sid
, 0, sizeof(sid
));
413 memset(&cid
, 0, sizeof(cid
));
415 if (!lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
)) {
416 log_error("Response without a server identifier received.");
420 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_CLIENTID
);
422 !evaluate_option_cache(&sid
, packet
, NULL
, client
, packet
->options
,
423 client
->sent_options
, &global_scope
, oc
,
425 log_error("Response without a client identifier.");
429 oc
= lookup_option(&dhcpv6_universe
, client
->sent_options
,
432 !evaluate_option_cache(&cid
, packet
, NULL
, client
,
433 client
->sent_options
, NULL
, &global_scope
,
435 log_error("Local client identifier is missing!");
440 sid
.len
!= cid
.len
||
441 memcmp(sid
.data
, cid
.data
, sid
.len
)) {
442 log_error("Advertise with matching transaction ID, but "
443 "mismatching client id.");
447 /* clean up pointers to the strings */
448 if (sid
.data
!= NULL
)
449 data_string_forget(&sid
, MDL
);
450 if (cid
.data
!= NULL
)
451 data_string_forget(&cid
, MDL
);
457 * Create a complete copy of a DHCPv6 lease structure.
459 static struct dhc6_lease
*
460 dhc6_dup_lease(struct dhc6_lease
*lease
, const char *file
, int line
)
462 struct dhc6_lease
*copy
;
463 struct dhc6_ia
**insert_ia
, *ia
;
465 copy
= dmalloc(sizeof(*copy
), file
, line
);
467 log_error("Out of memory for v6 lease structure.");
471 data_string_copy(©
->server_id
, &lease
->server_id
, file
, line
);
472 copy
->pref
= lease
->pref
;
474 memcpy(copy
->dhcpv6_transaction_id
, lease
->dhcpv6_transaction_id
,
475 sizeof(copy
->dhcpv6_transaction_id
));
477 option_state_reference(©
->options
, lease
->options
, file
, line
);
479 insert_ia
= ©
->bindings
;
480 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
481 *insert_ia
= dhc6_dup_ia(ia
, file
, line
);
483 if (*insert_ia
== NULL
) {
484 dhc6_lease_destroy(©
, file
, line
);
488 insert_ia
= &(*insert_ia
)->next
;
495 * Duplicate an IA structure.
497 static struct dhc6_ia
*
498 dhc6_dup_ia(struct dhc6_ia
*ia
, const char *file
, int line
)
500 struct dhc6_ia
*copy
;
501 struct dhc6_addr
**insert_addr
, *addr
;
503 copy
= dmalloc(sizeof(*ia
), file
, line
);
505 log_error("Out of memory for v6 duplicate IA structure.");
509 memcpy(copy
->iaid
, ia
->iaid
, sizeof(copy
->iaid
));
511 copy
->ia_type
= ia
->ia_type
;
512 copy
->starts
= ia
->starts
;
513 copy
->renew
= ia
->renew
;
514 copy
->rebind
= ia
->rebind
;
516 insert_addr
= ©
->addrs
;
517 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
518 *insert_addr
= dhc6_dup_addr(addr
, file
, line
);
520 if (*insert_addr
== NULL
) {
521 dhc6_ia_destroy(©
, file
, line
);
525 insert_addr
= &(*insert_addr
)->next
;
528 if (ia
->options
!= NULL
)
529 option_state_reference(©
->options
, ia
->options
,
536 * Duplicate an IAADDR or IAPREFIX structure.
538 static struct dhc6_addr
*
539 dhc6_dup_addr(struct dhc6_addr
*addr
, const char *file
, int line
)
541 struct dhc6_addr
*copy
;
543 copy
= dmalloc(sizeof(*addr
), file
, line
);
548 memcpy(©
->address
, &addr
->address
, sizeof(copy
->address
));
550 copy
->plen
= addr
->plen
;
551 copy
->flags
= addr
->flags
;
552 copy
->starts
= addr
->starts
;
553 copy
->preferred_life
= addr
->preferred_life
;
554 copy
->max_life
= addr
->max_life
;
556 if (addr
->options
!= NULL
)
557 option_state_reference(©
->options
, addr
->options
,
564 * Form a DHCPv6 lease structure based upon packet contents. Creates and
565 * populates IA's and any IAADDR/IAPREFIX's they contain.
566 * Parsed options are deleted in order to not save them in the lease file.
568 * If we get a status code of NoAddrs or NoPrefix we toss the affected
569 * IAs. If it as at the top level we toss all IAs of that type. If it
570 * is in an IA we only toss that one. According to the spec we shouldn't
571 * get a NoPrefix status at the top level but we will allow it.
574 static struct dhc6_lease
*
575 dhc6_leaseify(struct packet
*packet
, struct client_state
* client
)
577 struct data_string ds
;
578 struct dhc6_lease
*lease
;
579 struct option_cache
*oc
;
582 lease
= dmalloc(sizeof(*lease
), MDL
);
584 log_error("Out of memory for v6 lease structure.");
588 memcpy(lease
->dhcpv6_transaction_id
, packet
->dhcpv6_transaction_id
, 3);
589 option_state_reference(&lease
->options
, packet
->options
, MDL
);
591 memset(&ds
, 0, sizeof(ds
));
593 /* Determine preference (default zero). */
594 oc
= lookup_option(&dhcpv6_universe
, lease
->options
, D6O_PREFERENCE
);
596 evaluate_option_cache(&ds
, packet
, NULL
, NULL
, lease
->options
,
597 NULL
, &global_scope
, oc
, MDL
)) {
599 log_error("Invalid length of DHCPv6 Preference option "
600 "(%d != 1)", ds
.len
);
601 data_string_forget(&ds
, MDL
);
602 dhc6_lease_destroy(&lease
, MDL
);
605 lease
->pref
= ds
.data
[0];
606 log_debug("RCV: X-- Preference %u.",
607 (unsigned)lease
->pref
);
610 data_string_forget(&ds
, MDL
);
612 delete_option(&dhcpv6_universe
, lease
->options
, D6O_PREFERENCE
);
614 /* Get the top level status code. If the code is NoAddrsAvail
615 * or NoPrefixAvail strip it from the options as we don't
616 * want it to show up in check_[advertise reply]. We
617 * pass it along to the parse_ia_xx routines and they
618 * will drop the affected IAs for NoAddrs or NoPrefix,
619 * other status codes will be ignored and handled by
620 * the check_[advertise reply] routines.
622 code
= STATUS_Success
;
623 if ((dhc6_get_status_code(lease
->options
, &code
, NULL
) == ISC_R_SUCCESS
)
625 ((code
== STATUS_NoAddrsAvail
) || (code
== STATUS_NoPrefixAvail
))) {
626 delete_option(&dhcpv6_universe
, lease
->options
,
631 * Dig into recursive DHCPv6 pockets for IA_NA and contained IAADDR
634 if (dhc6_parse_ia_na(&lease
->bindings
, packet
,
635 lease
->options
, code
) != ISC_R_SUCCESS
) {
636 /* Error conditions are logged by the caller. */
637 dhc6_lease_destroy(&lease
, MDL
);
641 * Dig into recursive DHCPv6 pockets for IA_TA and contained IAADDR
644 if (dhc6_parse_ia_ta(&lease
->bindings
, packet
,
645 lease
->options
, code
) != ISC_R_SUCCESS
) {
646 /* Error conditions are logged by the caller. */
647 dhc6_lease_destroy(&lease
, MDL
);
651 * Dig into recursive DHCPv6 pockets for IA_PD and contained IAPREFIX
654 if (dhc6_parse_ia_pd(&lease
->bindings
, packet
,
655 lease
->options
, code
) != ISC_R_SUCCESS
) {
656 /* Error conditions are logged by the caller. */
657 dhc6_lease_destroy(&lease
, MDL
);
662 * This is last because in the future we may want to make a different
663 * key based upon additional information from the packet (we may need
664 * to allow multiple leases in one client state per server, but we're
665 * not sure based on what additional keys now).
667 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
669 !evaluate_option_cache(&lease
->server_id
, packet
, NULL
, NULL
,
670 lease
->options
, NULL
, &global_scope
,
672 lease
->server_id
.len
== 0) {
673 /* This should be impossible due to validation checks earlier.
675 log_error("Invalid SERVERID option cache.");
676 dhc6_lease_destroy(&lease
, MDL
);
679 log_debug("RCV: X-- Server ID: %s",
680 print_hex_1(lease
->server_id
.len
,
681 lease
->server_id
.data
, 52));
684 execute_statements_in_scope(NULL
, (struct packet
*)packet
, NULL
,
685 client
, lease
->options
, lease
->options
,
686 &global_scope
, client
->config
->on_receipt
,
693 dhc6_parse_ia_na(struct dhc6_ia
**pia
, struct packet
*packet
,
694 struct option_state
*options
, unsigned code
)
696 struct data_string ds
;
698 struct option_cache
*oc
;
702 memset(&ds
, 0, sizeof(ds
));
704 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IA_NA
);
705 for ( ; oc
!= NULL
; oc
= oc
->next
) {
706 ia
= dmalloc(sizeof(*ia
), MDL
);
708 log_error("Out of memory allocating IA_NA structure.");
709 return ISC_R_NOMEMORY
;
710 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
712 &global_scope
, oc
, MDL
) &&
714 memcpy(ia
->iaid
, ds
.data
, 4);
715 ia
->ia_type
= D6O_IA_NA
;
716 ia
->starts
= cur_time
;
717 ia
->renew
= getULong(ds
.data
+ 4);
718 ia
->rebind
= getULong(ds
.data
+ 8);
720 log_debug("RCV: X-- IA_NA %s",
721 print_hex_1(4, ia
->iaid
, 59));
722 /* XXX: This should be the printed time I think. */
723 log_debug("RCV: | X-- starts %u",
724 (unsigned)ia
->starts
);
725 log_debug("RCV: | X-- t1 - renew +%u", ia
->renew
);
726 log_debug("RCV: | X-- t2 - rebind +%u", ia
->rebind
);
729 * RFC3315 section 22.4, discard IA_NA's that
730 * have t1 greater than t2, and both not zero.
731 * Since RFC3315 defines this behaviour, it is not
732 * an error - just normal operation.
734 * Note that RFC3315 says we MUST honor these values
735 * if they are not zero. So insane values are
738 if ((ia
->renew
> 0) && (ia
->rebind
> 0) &&
739 (ia
->renew
> ia
->rebind
)) {
740 log_debug("RCV: | !-- INVALID renew/rebind "
741 "times, IA_NA discarded.");
743 data_string_forget(&ds
, MDL
);
748 log_debug("RCV: | X-- [Options]");
750 if (!option_state_allocate(&ia
->options
,
752 log_error("Out of memory allocating "
753 "IA_NA option state.");
755 data_string_forget(&ds
, MDL
);
756 return ISC_R_NOMEMORY
;
759 if (!parse_option_buffer(ia
->options
,
763 log_error("Corrupt IA_NA options.");
764 option_state_dereference(&ia
->options
,
767 data_string_forget(&ds
, MDL
);
768 return DHCP_R_BADPARSE
;
771 data_string_forget(&ds
, MDL
);
773 if (ia
->options
!= NULL
) {
774 result
= dhc6_parse_addrs(&ia
->addrs
, packet
,
776 if (result
!= ISC_R_SUCCESS
) {
777 option_state_dereference(&ia
->options
,
784 /* If we have no addresses or the top level status code
785 * or the status code in this IA indicate no addresses
788 ia_code
= STATUS_Success
;
789 if ((ia
->addrs
== NULL
) ||
790 (code
== STATUS_NoAddrsAvail
) ||
791 ((ia
->options
!= NULL
) &&
792 (dhc6_get_status_code(ia
->options
, &ia_code
, NULL
)
794 (ia_code
== STATUS_NoAddrsAvail
))) {
795 log_debug("RCV: | !-- Status code of "
796 "no addrs, IA_NA discarded.");
797 dhc6_ia_destroy(&ia
, MDL
);
806 log_error("Invalid IA_NA option cache.");
809 data_string_forget(&ds
, MDL
);
810 return ISC_R_UNEXPECTED
;
813 delete_option(&dhcpv6_universe
, options
, D6O_IA_NA
);
815 return ISC_R_SUCCESS
;
819 dhc6_parse_ia_ta(struct dhc6_ia
**pia
, struct packet
*packet
,
820 struct option_state
*options
, unsigned code
)
822 struct data_string ds
;
824 struct option_cache
*oc
;
828 memset(&ds
, 0, sizeof(ds
));
830 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IA_TA
);
831 for ( ; oc
!= NULL
; oc
= oc
->next
) {
832 ia
= dmalloc(sizeof(*ia
), MDL
);
834 log_error("Out of memory allocating IA_TA structure.");
835 return ISC_R_NOMEMORY
;
836 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
838 &global_scope
, oc
, MDL
) &&
840 memcpy(ia
->iaid
, ds
.data
, 4);
841 ia
->ia_type
= D6O_IA_TA
;
842 ia
->starts
= cur_time
;
844 log_debug("RCV: X-- IA_TA %s",
845 print_hex_1(4, ia
->iaid
, 59));
846 /* XXX: This should be the printed time I think. */
847 log_debug("RCV: | X-- starts %u",
848 (unsigned)ia
->starts
);
851 log_debug("RCV: | X-- [Options]");
853 if (!option_state_allocate(&ia
->options
,
855 log_error("Out of memory allocating "
856 "IA_TA option state.");
858 data_string_forget(&ds
, MDL
);
859 return ISC_R_NOMEMORY
;
862 if (!parse_option_buffer(ia
->options
,
866 log_error("Corrupt IA_TA options.");
867 option_state_dereference(&ia
->options
,
870 data_string_forget(&ds
, MDL
);
871 return DHCP_R_BADPARSE
;
874 data_string_forget(&ds
, MDL
);
876 if (ia
->options
!= NULL
) {
877 result
= dhc6_parse_addrs(&ia
->addrs
, packet
,
879 if (result
!= ISC_R_SUCCESS
) {
880 option_state_dereference(&ia
->options
,
887 /* If we have no addresses or the top level status code
888 * or the status code in this IA indicate no addresses
891 ia_code
= STATUS_Success
;
892 if ((ia
->addrs
== NULL
) ||
893 (code
== STATUS_NoAddrsAvail
) ||
894 ((ia
->options
!= NULL
) &&
895 (dhc6_get_status_code(ia
->options
, &ia_code
, NULL
)
897 (ia_code
== STATUS_NoAddrsAvail
))) {
898 log_debug("RCV: | !-- Status code of "
899 "no addrs, IA_TA discarded.");
900 dhc6_ia_destroy(&ia
, MDL
);
909 log_error("Invalid IA_TA option cache.");
912 data_string_forget(&ds
, MDL
);
913 return ISC_R_UNEXPECTED
;
916 delete_option(&dhcpv6_universe
, options
, D6O_IA_TA
);
918 return ISC_R_SUCCESS
;
922 dhc6_parse_ia_pd(struct dhc6_ia
**pia
, struct packet
*packet
,
923 struct option_state
*options
, unsigned code
)
925 struct data_string ds
;
927 struct option_cache
*oc
;
931 memset(&ds
, 0, sizeof(ds
));
933 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IA_PD
);
934 for ( ; oc
!= NULL
; oc
= oc
->next
) {
935 ia
= dmalloc(sizeof(*ia
), MDL
);
937 log_error("Out of memory allocating IA_PD structure.");
938 return ISC_R_NOMEMORY
;
939 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
941 &global_scope
, oc
, MDL
) &&
943 memcpy(ia
->iaid
, ds
.data
, 4);
944 ia
->ia_type
= D6O_IA_PD
;
945 ia
->starts
= cur_time
;
946 ia
->renew
= getULong(ds
.data
+ 4);
947 ia
->rebind
= getULong(ds
.data
+ 8);
949 log_debug("RCV: X-- IA_PD %s",
950 print_hex_1(4, ia
->iaid
, 59));
951 /* XXX: This should be the printed time I think. */
952 log_debug("RCV: | X-- starts %u",
953 (unsigned)ia
->starts
);
954 log_debug("RCV: | X-- t1 - renew +%u", ia
->renew
);
955 log_debug("RCV: | X-- t2 - rebind +%u", ia
->rebind
);
958 * RFC3633 section 9, discard IA_PD's that
959 * have t1 greater than t2, and both not zero.
960 * Since RFC3633 defines this behaviour, it is not
961 * an error - just normal operation.
963 if ((ia
->renew
> 0) && (ia
->rebind
> 0) &&
964 (ia
->renew
> ia
->rebind
)) {
965 log_debug("RCV: | !-- INVALID renew/rebind "
966 "times, IA_PD discarded.");
968 data_string_forget(&ds
, MDL
);
973 log_debug("RCV: | X-- [Options]");
975 if (!option_state_allocate(&ia
->options
,
977 log_error("Out of memory allocating "
978 "IA_PD option state.");
980 data_string_forget(&ds
, MDL
);
981 return ISC_R_NOMEMORY
;
984 if (!parse_option_buffer(ia
->options
,
988 log_error("Corrupt IA_PD options.");
989 option_state_dereference(&ia
->options
,
992 data_string_forget(&ds
, MDL
);
993 return DHCP_R_BADPARSE
;
996 data_string_forget(&ds
, MDL
);
998 if (ia
->options
!= NULL
) {
999 result
= dhc6_parse_prefixes(&ia
->addrs
,
1002 if (result
!= ISC_R_SUCCESS
) {
1003 option_state_dereference(&ia
->options
,
1010 /* If we have no prefixes or the top level status code
1011 * or the status code in this IA indicate no prefixes
1014 ia_code
= STATUS_Success
;
1015 if ((ia
->addrs
== NULL
) ||
1016 (code
== STATUS_NoPrefixAvail
) ||
1017 ((ia
->options
!= NULL
) &&
1018 (dhc6_get_status_code(ia
->options
, &ia_code
, NULL
)
1019 == ISC_R_SUCCESS
) &&
1020 (ia_code
== STATUS_NoPrefixAvail
))) {
1021 log_debug("RCV: | !-- Status code of "
1022 "no prefix, IA_PD discarded.");
1023 dhc6_ia_destroy(&ia
, MDL
);
1027 while (*pia
!= NULL
)
1028 pia
= &(*pia
)->next
;
1032 log_error("Invalid IA_PD option cache.");
1035 data_string_forget(&ds
, MDL
);
1036 return ISC_R_UNEXPECTED
;
1039 delete_option(&dhcpv6_universe
, options
, D6O_IA_PD
);
1041 return ISC_R_SUCCESS
;
1046 dhc6_parse_addrs(struct dhc6_addr
**paddr
, struct packet
*packet
,
1047 struct option_state
*options
)
1049 struct data_string ds
;
1050 struct option_cache
*oc
;
1051 struct dhc6_addr
*addr
;
1052 isc_result_t rval
= ISC_R_SUCCESS
;
1055 memset(&ds
, 0, sizeof(ds
));
1057 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IAADDR
);
1058 for ( ; oc
!= NULL
; oc
= oc
->next
) {
1059 addr
= dmalloc(sizeof(*addr
), MDL
);
1061 log_error("Out of memory allocating "
1062 "address structure.");
1063 return ISC_R_NOMEMORY
;
1064 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
1065 options
, NULL
, &global_scope
,
1069 addr
->address
.len
= 16;
1070 memcpy(addr
->address
.iabuf
, ds
.data
, 16);
1071 addr
->starts
= cur_time
;
1072 addr
->preferred_life
= getULong(ds
.data
+ 16);
1073 addr
->max_life
= getULong(ds
.data
+ 20);
1075 log_debug("RCV: | | X-- IAADDR %s",
1076 piaddr(addr
->address
));
1077 log_debug("RCV: | | | X-- Preferred lifetime %u.",
1078 addr
->preferred_life
);
1079 log_debug("RCV: | | | X-- Max lifetime %u.",
1083 * RFC 3315 section 22.6 says we must discard
1084 * addresses whose pref is later than valid.
1086 if ((addr
->preferred_life
> addr
->max_life
)) {
1087 log_debug("RCV: | | | !-- INVALID lifetimes, "
1088 "IAADDR discarded. Check your "
1089 "server configuration.");
1091 data_string_forget(&ds
, MDL
);
1096 * Fortunately this is the last recursion in the
1100 if (!option_state_allocate(&addr
->options
,
1102 log_error("Out of memory allocating "
1103 "IAADDR option state.");
1105 data_string_forget(&ds
, MDL
);
1106 return ISC_R_NOMEMORY
;
1109 if (!parse_option_buffer(addr
->options
,
1112 &dhcpv6_universe
)) {
1113 log_error("Corrupt IAADDR options.");
1114 option_state_dereference(&addr
->options
,
1117 data_string_forget(&ds
, MDL
);
1118 return DHCP_R_BADPARSE
;
1122 data_string_forget(&ds
, MDL
);
1124 if (addr
->options
!= NULL
) {
1125 log_debug("RCV: | | | X-- [Options]");
1127 /* Get the status code if the return value
1128 * indicates an error or the status code
1129 * indicates no address toss the address
1131 code
= STATUS_Success
;
1132 rval
= dhc6_check_status(ISC_R_SUCCESS
,
1135 if (rval
!= ISC_R_SUCCESS
) {
1136 log_debug("RCV: | | | X-- Status code"
1137 " issue, IAADDR discarded.");
1138 option_state_dereference(&addr
->options
,
1146 paddr
= &addr
->next
;
1148 log_error("Invalid IAADDR option cache.");
1151 data_string_forget(&ds
, MDL
);
1152 return ISC_R_UNEXPECTED
;
1155 delete_option(&dhcpv6_universe
, options
, D6O_IAADDR
);
1157 return ISC_R_SUCCESS
;
1161 dhc6_parse_prefixes(struct dhc6_addr
**ppfx
, struct packet
*packet
,
1162 struct option_state
*options
)
1164 struct data_string ds
;
1165 struct option_cache
*oc
;
1166 struct dhc6_addr
*pfx
;
1167 isc_result_t rval
= ISC_R_SUCCESS
;
1170 memset(&ds
, 0, sizeof(ds
));
1172 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IAPREFIX
);
1173 for ( ; oc
!= NULL
; oc
= oc
->next
) {
1174 pfx
= dmalloc(sizeof(*pfx
), MDL
);
1176 log_error("Out of memory allocating "
1177 "prefix structure.");
1178 return ISC_R_NOMEMORY
;
1179 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
1180 options
, NULL
, &global_scope
,
1184 pfx
->preferred_life
= getULong(ds
.data
);
1185 pfx
->max_life
= getULong(ds
.data
+ 4);
1186 pfx
->plen
= getUChar(ds
.data
+ 8);
1187 pfx
->address
.len
= 16;
1188 memcpy(pfx
->address
.iabuf
, ds
.data
+ 9, 16);
1189 pfx
->starts
= cur_time
;
1191 log_debug("RCV: | | X-- IAPREFIX %s/%d",
1192 piaddr(pfx
->address
), (int)pfx
->plen
);
1193 log_debug("RCV: | | | X-- Preferred lifetime %u.",
1194 pfx
->preferred_life
);
1195 log_debug("RCV: | | | X-- Max lifetime %u.",
1198 /* Sanity check over the prefix length */
1199 if ((pfx
->plen
< 4) || (pfx
->plen
> 128)) {
1200 log_debug("RCV: | | | !-- INVALID prefix "
1201 "length, IAPREFIX discarded. "
1202 "Check your server configuration.");
1204 data_string_forget(&ds
, MDL
);
1208 * RFC 3633 section 10 says we must discard
1209 * prefixes whose pref is later than valid.
1211 if ((pfx
->preferred_life
> pfx
->max_life
)) {
1212 log_debug("RCV: | | | !-- INVALID lifetimes, "
1213 "IAPREFIX discarded. Check your "
1214 "server configuration.");
1216 data_string_forget(&ds
, MDL
);
1221 * Fortunately this is the last recursion in the
1225 if (!option_state_allocate(&pfx
->options
,
1227 log_error("Out of memory allocating "
1228 "IAPREFIX option state.");
1230 data_string_forget(&ds
, MDL
);
1231 return ISC_R_NOMEMORY
;
1234 if (!parse_option_buffer(pfx
->options
,
1237 &dhcpv6_universe
)) {
1238 log_error("Corrupt IAPREFIX options.");
1239 option_state_dereference(&pfx
->options
,
1242 data_string_forget(&ds
, MDL
);
1243 return DHCP_R_BADPARSE
;
1247 data_string_forget(&ds
, MDL
);
1249 if (pfx
->options
!= NULL
) {
1250 log_debug("RCV: | | | X-- [Options]");
1252 /* Get the status code if the return value
1253 * indicates an error or the status code
1254 * indicates no prefix toss the prefix
1256 code
= STATUS_Success
;
1257 rval
= dhc6_check_status(ISC_R_SUCCESS
,
1260 if (rval
!= ISC_R_SUCCESS
) {
1261 log_debug("RCV: | | | X-- Status code"
1262 " issue IAPREFIX discarded.");
1263 option_state_dereference(&pfx
->options
,
1273 log_error("Invalid IAPREFIX option cache.");
1276 data_string_forget(&ds
, MDL
);
1277 return ISC_R_UNEXPECTED
;
1280 delete_option(&dhcpv6_universe
, options
, D6O_IAPREFIX
);
1282 return ISC_R_SUCCESS
;
1285 /* Clean up a lease object, deallocate all its parts, and set it to NULL. */
1287 dhc6_lease_destroy(struct dhc6_lease
**src
, const char *file
, int line
)
1289 struct dhc6_ia
*ia
, *nia
;
1290 struct dhc6_lease
*lease
;
1292 if (src
== NULL
|| *src
== NULL
) {
1293 log_error("Attempt to destroy null lease.");
1298 if (lease
->server_id
.len
!= 0)
1299 data_string_forget(&lease
->server_id
, file
, line
);
1301 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= nia
) {
1304 dhc6_ia_destroy(&ia
, file
, line
);
1307 if (lease
->options
!= NULL
)
1308 option_state_dereference(&lease
->options
, file
, line
);
1310 dfree(lease
, file
, line
);
1315 * Traverse the addresses list, and destroy their contents, and NULL the
1319 dhc6_ia_destroy(struct dhc6_ia
**src
, const char *file
, int line
)
1321 struct dhc6_addr
*addr
, *naddr
;
1324 if (src
== NULL
|| *src
== NULL
) {
1325 log_error("Attempt to destroy null IA.");
1330 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= naddr
) {
1333 if (addr
->options
!= NULL
)
1334 option_state_dereference(&addr
->options
, file
, line
);
1336 dfree(addr
, file
, line
);
1339 if (ia
->options
!= NULL
)
1340 option_state_dereference(&ia
->options
, file
, line
);
1342 dfree(ia
, file
, line
);
1347 * For a given lease, insert it into the tail of the lease list. Upon
1348 * finding a duplicate by server id, remove it and take over its position.
1351 insert_lease(struct dhc6_lease
**head
, struct dhc6_lease
*new)
1353 while (*head
!= NULL
) {
1354 if ((*head
)->server_id
.len
== new->server_id
.len
&&
1355 memcmp((*head
)->server_id
.data
, new->server_id
.data
,
1356 new->server_id
.len
) == 0) {
1357 new->next
= (*head
)->next
;
1358 dhc6_lease_destroy(head
, MDL
);
1362 head
= &(*head
)->next
;
1371 * \brief Determine a score for a lease. We use this to
1372 * compare and choose leases if we receive multiple candidates.
1374 * We originally started with scores of 50 for a binding and 100 for
1375 * an address. This would select multiple adresses over multiple
1376 * bindings. As part of the 7550 work I've changed this to be
1377 * 10000 for a binding, 100 for an address and 1 for an option.
1378 * This will cause us to choose a lease with more bindings over
1379 * a lease with less bindings but more addresses which seems
1380 * to be the best selection criteria to me.
1381 * In theory we could end up with a lease with enough addresses
1382 * or options being better but at 100 to 1 I don't think it's likely.
1384 * \param client = the state of the entire client
1385 * \param lease = the lease to score.
1387 * \retrun the score of the lease
1390 /* The scores for individual items. */
1391 #ifdef USE_ORIGINAL_CLIENT_LEASE_WEIGHTS
1392 #define SCORE_BINDING 50
1393 #define SCORE_ADDRESS 100
1395 #define SCORE_BINDING 10000
1396 #define SCORE_ADDRESS 100
1399 #define SCORE_OPTION 1
1400 /* We need a lease with at least 1 binding and 1 address */
1401 #define SCORE_MIN (SCORE_BINDING + SCORE_ADDRESS)
1404 dhc6_score_lease(struct client_state
*client
, struct dhc6_lease
*lease
)
1407 struct dhc6_addr
*addr
;
1408 struct option
**req
;
1412 return lease
->score
;
1414 lease
->score
= SCORE_OPTION
;
1416 /* If this lease lacks a required option, dump it. */
1417 /* XXX: we should be able to cache the failure... */
1418 req
= client
->config
->required_options
;
1420 for (i
= 0 ; req
[i
] != NULL
; i
++) {
1421 if (lookup_option(&dhcpv6_universe
, lease
->options
,
1422 req
[i
]->code
) == NULL
) {
1424 return lease
->score
;
1429 /* If this lease contains a requested option, improve its score. */
1430 req
= client
->config
->requested_options
;
1432 for (i
= 0 ; req
[i
] != NULL
; i
++) {
1433 if (lookup_option(&dhcpv6_universe
, lease
->options
,
1434 req
[i
]->code
) != NULL
)
1435 lease
->score
+= SCORE_OPTION
;
1439 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
1440 lease
->score
+= SCORE_BINDING
;
1442 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
1443 lease
->score
+= SCORE_ADDRESS
;
1447 return lease
->score
;
1451 * start_init6() kicks off the process, transmitting a packet and
1452 * scheduling a retransmission event.
1455 start_init6(struct client_state
*client
)
1459 log_debug("PRC: Soliciting for leases (INIT).");
1460 client
->state
= S_INIT
;
1462 /* Initialize timers, RFC3315 section 17.1.2. */
1463 client
->IRT
= SOL_TIMEOUT
* 100;
1464 client
->MRT
= SOL_MAX_RT
* 100;
1466 /* Default is 0 (no max) but -1 changes this. */
1470 client
->MRD
= client
->config
->timeout
;
1472 dhc6_retrans_init(client
);
1475 * RFC3315 section 17.1.2 goes out of its way:
1476 * Also, the first RT MUST be selected to be strictly greater than IRT
1477 * by choosing RAND to be strictly greater than 0.
1479 /* if RAND < 0 then RAND = -RAND */
1480 if (client
->RT
<= client
->IRT
)
1481 client
->RT
= client
->IRT
+ (client
->IRT
- client
->RT
);
1482 /* if RAND == 0 then RAND = 1 */
1483 if (client
->RT
<= client
->IRT
)
1484 client
->RT
= client
->IRT
+ 1;
1486 client
->v6_handler
= init_handler
;
1489 * RFC3315 section 17.1.2 says we MUST start the first packet
1490 * between 0 and SOL_MAX_DELAY seconds. The good news is
1491 * SOL_MAX_DELAY is 1.
1493 tv
.tv_sec
= cur_tv
.tv_sec
;
1494 tv
.tv_usec
= cur_tv
.tv_usec
;
1495 tv
.tv_usec
+= (random() % (SOL_MAX_DELAY
* 100)) * 10000;
1496 if (tv
.tv_usec
>= 1000000) {
1498 tv
.tv_usec
-= 1000000;
1500 add_timeout(&tv
, do_init6
, client
, NULL
, NULL
);
1507 * start_info_request6() kicks off the process, transmitting an info
1508 * request packet and scheduling a retransmission event.
1511 start_info_request6(struct client_state
*client
)
1515 log_debug("PRC: Requesting information (INIT).");
1516 client
->state
= S_INIT
;
1518 /* Initialize timers, RFC3315 section 18.1.5. */
1519 client
->IRT
= INF_TIMEOUT
* 100;
1520 client
->MRT
= INF_MAX_RT
* 100;
1522 /* Default is 0 (no max) but -1 changes this. */
1526 client
->MRD
= client
->config
->timeout
;
1528 dhc6_retrans_init(client
);
1530 client
->v6_handler
= info_request_handler
;
1533 * RFC3315 section 18.1.5 says we MUST start the first packet
1534 * between 0 and INF_MAX_DELAY seconds. The good news is
1535 * INF_MAX_DELAY is 1.
1537 tv
.tv_sec
= cur_tv
.tv_sec
;
1538 tv
.tv_usec
= cur_tv
.tv_usec
;
1539 tv
.tv_usec
+= (random() % (INF_MAX_DELAY
* 100)) * 10000;
1540 if (tv
.tv_usec
>= 1000000) {
1542 tv
.tv_usec
-= 1000000;
1544 add_timeout(&tv
, do_info_request6
, client
, NULL
, NULL
);
1551 * start_confirm6() kicks off an "init-reboot" version of the process, at
1552 * startup to find out if old bindings are 'fair' and at runtime whenever
1553 * a link cycles state we'll eventually want to do this.
1556 start_confirm6(struct client_state
*client
)
1560 /* If there is no active lease, there is nothing to check. */
1561 if ((client
->active_lease
== NULL
) ||
1562 !active_prefix(client
) ||
1563 client
->active_lease
->released
) {
1564 start_init6(client
);
1568 log_debug("PRC: Confirming active lease (INIT-REBOOT).");
1569 client
->state
= S_REBOOTING
;
1571 /* Initialize timers, RFC3315 section 17.1.3. */
1572 client
->IRT
= CNF_TIMEOUT
* 100;
1573 client
->MRT
= CNF_MAX_RT
* 100;
1575 client
->MRD
= CNF_MAX_RD
;
1577 dhc6_retrans_init(client
);
1579 client
->v6_handler
= reply_handler
;
1582 * RFC3315 section 18.1.2 says we MUST start the first packet
1583 * between 0 and CNF_MAX_DELAY seconds. The good news is
1584 * CNF_MAX_DELAY is 1.
1586 tv
.tv_sec
= cur_tv
.tv_sec
;
1587 tv
.tv_usec
= cur_tv
.tv_usec
;
1588 tv
.tv_usec
+= (random() % (CNF_MAX_DELAY
* 100)) * 10000;
1589 if (tv
.tv_usec
>= 1000000) {
1591 tv
.tv_usec
-= 1000000;
1594 /* We do a rebind instead of a confirm if the user
1595 * is requesting PDs or previously requesed PDs or
1596 * increased the number of NAs or TAs they want
1597 * Confirms don't tell us if PDs are still on-link and
1598 * we won't add new IAs on a confirm.
1601 if ((wanted_ia_pd
!= 0) ||
1602 (dhc6_count_ia(client
->active_lease
, D6O_IA_PD
) != 0) ||
1603 (dhc6_count_ia(client
->active_lease
, D6O_IA_NA
) < wanted_ia_na
) ||
1604 (dhc6_count_ia(client
->active_lease
, D6O_IA_TA
) < wanted_ia_ta
)) {
1605 client
->state
= S_REBINDING
;
1606 client
->refresh_type
= DHCPV6_REBIND
;
1607 add_timeout(&tv
, do_refresh6
, client
, NULL
, NULL
);
1609 add_timeout(&tv
, do_confirm6
, client
, NULL
, NULL
);
1613 * check_timing6() check on the timing for sending a v6 message
1614 * and then do the basic initialization for a v6 message.
1616 #define CHK_TIM_SUCCESS 0
1617 #define CHK_TIM_MRC_EXCEEDED 1
1618 #define CHK_TIM_MRD_EXCEEDED 2
1619 #define CHK_TIM_ALLOC_FAILURE 3
1622 check_timing6 (struct client_state
*client
, u_int8_t msg_type
,
1623 char *msg_str
, struct dhc6_lease
*lease
,
1624 struct data_string
*ds
)
1626 struct timeval elapsed
;
1629 * Start_time starts at the first transmission.
1631 if (client
->txcount
== 0) {
1632 client
->start_time
.tv_sec
= cur_tv
.tv_sec
;
1633 client
->start_time
.tv_usec
= cur_tv
.tv_usec
;
1634 } else if ((client
->MRC
!= 0) && (client
->txcount
> client
->MRC
)) {
1635 log_info("Max retransmission count exceeded.");
1636 return(CHK_TIM_MRC_EXCEEDED
);
1639 /* elapsed = cur - start */
1640 elapsed
.tv_sec
= cur_tv
.tv_sec
- client
->start_time
.tv_sec
;
1641 elapsed
.tv_usec
= cur_tv
.tv_usec
- client
->start_time
.tv_usec
;
1642 if (elapsed
.tv_usec
< 0) {
1643 elapsed
.tv_sec
-= 1;
1644 elapsed
.tv_usec
+= 1000000;
1647 /* Check if finished (-1 argument). */
1648 if ((client
->MRD
!= 0) && (elapsed
.tv_sec
>= client
->MRD
)) {
1649 log_info("Max retransmission duration exceeded.");
1650 return(CHK_TIM_MRD_EXCEEDED
);
1653 memset(ds
, 0, sizeof(*ds
));
1654 if (!buffer_allocate(&(ds
->buffer
), 4, MDL
)) {
1655 log_error("Unable to allocate memory for %s.", msg_str
);
1656 return(CHK_TIM_ALLOC_FAILURE
);
1658 ds
->data
= ds
->buffer
->data
;
1661 ds
->buffer
->data
[0] = msg_type
;
1662 memcpy(ds
->buffer
->data
+ 1, client
->dhcpv6_transaction_id
, 3);
1664 /* Form an elapsed option. */
1665 /* Maximum value is 65535 1/100s coded as 0xffff. */
1666 if ((elapsed
.tv_sec
< 0) || (elapsed
.tv_sec
> 655) ||
1667 ((elapsed
.tv_sec
== 655) && (elapsed
.tv_usec
> 350000))) {
1668 client
->elapsed
= 0xffff;
1670 client
->elapsed
= elapsed
.tv_sec
* 100;
1671 client
->elapsed
+= elapsed
.tv_usec
/ 10000;
1674 if (client
->elapsed
== 0)
1675 log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str
);
1677 log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str
,
1678 (unsigned)client
->elapsed
);
1680 client
->elapsed
= htons(client
->elapsed
);
1682 make_client6_options(client
, &client
->sent_options
, lease
, msg_type
);
1684 return(CHK_TIM_SUCCESS
);
1689 * \brief Create an iaid from information from the client.
1691 * \param client = the state of the entire client
1692 * \param ia = the ia to fill in
1693 * \param idx = index of the ia in case we are doing multiples
1694 * \param len = length of the base IA (4 for TA, 12 for NA & PD)
1696 * \return ISC_R_SUCCESS - all is well continue, any other return indicates
1697 * an error and the packet should be tossed
1701 dhc6_create_iaid(struct client_state
*client
,
1702 struct data_string
*ia
,
1706 int start_idx
, copy_len
;
1708 memset(ia
, 0, sizeof(*ia
));
1709 if (!buffer_allocate(&ia
->buffer
, 12, MDL
)) {
1710 return (ISC_R_NOMEMORY
);
1712 ia
->data
= ia
->buffer
->data
;
1716 * A simple IAID is the last 4 bytes
1717 * of the hardware address.
1719 if (client
->interface
->hw_address
.hlen
> 4) {
1720 start_idx
= client
->interface
->hw_address
.hlen
- 4;
1724 copy_len
= client
->interface
->hw_address
.hlen
;
1726 memcpy(ia
->buffer
->data
,
1727 client
->interface
->hw_address
.hbuf
+ start_idx
,
1730 ia
->buffer
->data
[3] += idx
;
1732 return (ISC_R_SUCCESS
);
1737 * \brief Add bare IA_NAs, IA_TAs or IA_PDs to the packet we are building.
1739 * Attempt to add the number of bare IAs indicated by wanted to
1740 * the packet. As we have already added a number of IAs based
1741 * on what is in the current lease after we create an IAID we check
1742 * it against the current lease and skip any that are already in use.
1744 * \param client = the state of the entire client
1745 * \param packet = the packet we are building and where we
1746 * shall append the IA_NA, IA_TA or IA_PDs we create
1747 * \param wanted = the number of IA_NA, IA_TA or IA_PDs we want to create
1748 * \param ia_type = the type of the IAs we want to create: NA, TA or PD.
1750 * \return ISC_R_SUCCESS - all is well continue, any other return indicates
1751 * an error and the packet should be tossed
1754 dhc6_bare_ia_xx(struct client_state
*client
,
1755 struct data_string
*packet
,
1759 struct dhc6_ia
*old_ia
;
1760 struct data_string ia
;
1765 struct option
*type_option
;
1767 /* figure out what type of option we are working with */
1770 type_string
= "IA_NA";
1771 type_option
= ia_na_option
;
1775 type_string
= "IA_TA";
1776 type_option
= ia_ta_option
;
1780 type_string
= "IA_PD";
1781 type_option
= ia_pd_option
;
1785 return (ISC_R_FAILURE
);
1788 for (i
= 0; wanted
!= 0; i
++) {
1789 rval
= dhc6_create_iaid(client
, &ia
, i
, len
);
1790 if (rval
!= ISC_R_SUCCESS
) {
1791 log_error("Unable to allocate memory for %s.",
1796 /* If we are already using this IAID, skip it and try again */
1797 if ((client
->active_lease
!= NULL
) &&
1798 ((old_ia
= find_ia(client
->active_lease
->bindings
,
1800 (char *)ia
.buffer
->data
)) != NULL
)) {
1801 data_string_forget(&ia
, MDL
);
1805 /* We have a good IAID, log it */
1806 log_debug("XMT: X-- %s %s",
1807 type_string
, print_hex_1(4, ia
.buffer
->data
, 55));
1809 /* If we are requesting an NA or a PD we also want to add
1810 * the renew and rebind times we are requesting.
1813 t1
= client
->config
->requested_lease
/ 2;
1815 putULong(ia
.buffer
->data
+ 4, t1
);
1816 putULong(ia
.buffer
->data
+ 8, t2
);
1818 log_debug("XMT: | X-- Request renew in +%u",
1820 log_debug("XMT: | X-- Request rebind in +%u",
1824 /* and append it to the packet */
1825 append_option(packet
, &dhcpv6_universe
, type_option
, &ia
);
1826 data_string_forget(&ia
, MDL
);
1828 /* decrement the number of IAs we want */
1832 return (ISC_R_SUCCESS
);
1836 * do_init6() marshals and transmits a solicit.
1839 do_init6(void *input
)
1841 struct client_state
*client
;
1842 struct dhc6_ia
*old_ia
;
1843 struct dhc6_addr
*old_addr
;
1844 struct data_string ds
;
1845 struct data_string ia
;
1846 struct data_string addr
;
1854 * In RFC3315 section 17.1.2, the retransmission timer is
1855 * used as the selecting timer.
1857 if (client
->advertised_leases
!= NULL
) {
1858 start_selecting6(client
);
1862 switch(check_timing6(client
, DHCPV6_SOLICIT
, "Solicit", NULL
, &ds
)) {
1863 case CHK_TIM_MRC_EXCEEDED
:
1864 case CHK_TIM_ALLOC_FAILURE
:
1866 case CHK_TIM_MRD_EXCEEDED
:
1867 client
->state
= S_STOPPED
;
1868 if (client
->active_lease
!= NULL
) {
1869 dhc6_lease_destroy(&client
->active_lease
, MDL
);
1870 client
->active_lease
= NULL
;
1872 /* Stop if and only if this is the last client. */
1873 if (stopping_finished())
1879 * Fetch any configured 'sent' options (includes DUID) in wire format.
1881 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
,
1882 NULL
, client
->sent_options
, &global_scope
,
1885 /* Use a specific handler with rapid-commit. */
1886 if (lookup_option(&dhcpv6_universe
, client
->sent_options
,
1887 D6O_RAPID_COMMIT
) != NULL
) {
1888 client
->v6_handler
= rapid_commit_handler
;
1892 for (i
= 0; i
< wanted_ia_na
; i
++) {
1894 * XXX: maybe the IA_NA('s) should be put into the sent_options
1895 * cache. They'd have to be pulled down as they also contain
1896 * different option caches in the same universe...
1898 if (dhc6_create_iaid(client
, &ia
, i
, 12) != ISC_R_SUCCESS
) {
1899 log_error("Unable to allocate memory for IA_NA.");
1900 data_string_forget(&ds
, MDL
);
1904 t1
= client
->config
->requested_lease
/ 2;
1906 putULong(ia
.buffer
->data
+ 4, t1
);
1907 putULong(ia
.buffer
->data
+ 8, t2
);
1909 log_debug("XMT: X-- IA_NA %s",
1910 print_hex_1(4, ia
.buffer
->data
, 55));
1911 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1
);
1912 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2
);
1914 if ((client
->active_lease
!= NULL
) &&
1915 ((old_ia
= find_ia(client
->active_lease
->bindings
,
1917 (char *)ia
.buffer
->data
)) != NULL
)) {
1919 * For each address in the old IA_NA,
1920 * request a binding.
1922 memset(&addr
, 0, sizeof(addr
));
1923 for (old_addr
= old_ia
->addrs
; old_addr
!= NULL
;
1924 old_addr
= old_addr
->next
) {
1925 if (old_addr
->address
.len
!= 16) {
1926 log_error("Invalid IPv6 address "
1928 "Ignoring. (%s:%d)",
1929 old_addr
->address
.len
,
1934 if (!buffer_allocate(&addr
.buffer
, 24, MDL
)) {
1935 log_error("Unable to allocate memory "
1937 data_string_forget(&ia
, MDL
);
1938 data_string_forget(&ds
, MDL
);
1941 addr
.data
= addr
.buffer
->data
;
1944 memcpy(addr
.buffer
->data
,
1945 old_addr
->address
.iabuf
,
1948 t1
= client
->config
->requested_lease
;
1950 putULong(addr
.buffer
->data
+ 16, t1
);
1951 putULong(addr
.buffer
->data
+ 20, t2
);
1953 log_debug("XMT: | X-- Request address %s.",
1954 piaddr(old_addr
->address
));
1955 log_debug("XMT: | | X-- Request "
1958 log_debug("XMT: | | X-- Request valid "
1962 append_option(&ia
, &dhcpv6_universe
,
1966 data_string_forget(&addr
, MDL
);
1970 append_option(&ds
, &dhcpv6_universe
, ia_na_option
, &ia
);
1971 data_string_forget(&ia
, MDL
);
1975 for (i
= 0; i
< wanted_ia_ta
; i
++) {
1977 * XXX: maybe the IA_TA('s) should be put into the sent_options
1978 * cache. They'd have to be pulled down as they also contain
1979 * different option caches in the same universe...
1981 if (dhc6_create_iaid(client
, &ia
, i
, 4) != ISC_R_SUCCESS
) {
1982 log_error("Unable to allocate memory for IA_TA.");
1983 data_string_forget(&ds
, MDL
);
1987 log_debug("XMT: X-- IA_TA %s",
1988 print_hex_1(4, ia
.buffer
->data
, 55));
1990 if ((client
->active_lease
!= NULL
) &&
1991 ((old_ia
= find_ia(client
->active_lease
->bindings
,
1993 (char *)ia
.buffer
->data
)) != NULL
)) {
1995 * For each address in the old IA_TA,
1996 * request a binding.
1998 memset(&addr
, 0, sizeof(addr
));
1999 for (old_addr
= old_ia
->addrs
; old_addr
!= NULL
;
2000 old_addr
= old_addr
->next
) {
2001 if (old_addr
->address
.len
!= 16) {
2002 log_error("Invalid IPv6 address "
2004 "Ignoring. (%s:%d)",
2005 old_addr
->address
.len
,
2010 if (!buffer_allocate(&addr
.buffer
, 24, MDL
)) {
2011 log_error("Unable to allocate memory "
2013 data_string_forget(&ia
, MDL
);
2014 data_string_forget(&ds
, MDL
);
2017 addr
.data
= addr
.buffer
->data
;
2020 memcpy(addr
.buffer
->data
,
2021 old_addr
->address
.iabuf
,
2024 t1
= client
->config
->requested_lease
;
2026 putULong(addr
.buffer
->data
+ 16, t1
);
2027 putULong(addr
.buffer
->data
+ 20, t2
);
2029 log_debug("XMT: | X-- Request address %s.",
2030 piaddr(old_addr
->address
));
2031 log_debug("XMT: | | X-- Request "
2034 log_debug("XMT: | | X-- Request valid "
2038 append_option(&ia
, &dhcpv6_universe
,
2042 data_string_forget(&addr
, MDL
);
2046 append_option(&ds
, &dhcpv6_universe
, ia_ta_option
, &ia
);
2047 data_string_forget(&ia
, MDL
);
2051 for (i
= 0; i
< wanted_ia_pd
; i
++) {
2053 * XXX: maybe the IA_PD('s) should be put into the sent_options
2054 * cache. They'd have to be pulled down as they also contain
2055 * different option caches in the same universe...
2057 memset(&ia
, 0, sizeof(ia
));
2058 if (dhc6_create_iaid(client
, &ia
, i
, 12) != ISC_R_SUCCESS
) {
2059 log_error("Unable to allocate memory for IA_PD.");
2060 data_string_forget(&ds
, MDL
);
2064 t1
= client
->config
->requested_lease
/ 2;
2066 putULong(ia
.buffer
->data
+ 4, t1
);
2067 putULong(ia
.buffer
->data
+ 8, t2
);
2069 log_debug("XMT: X-- IA_PD %s",
2070 print_hex_1(4, ia
.buffer
->data
, 55));
2071 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1
);
2072 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2
);
2074 if ((client
->active_lease
!= NULL
) &&
2075 ((old_ia
= find_ia(client
->active_lease
->bindings
,
2077 (char *)ia
.buffer
->data
)) != NULL
)) {
2079 * For each prefix in the old IA_PD,
2080 * request a binding.
2082 memset(&addr
, 0, sizeof(addr
));
2083 for (old_addr
= old_ia
->addrs
; old_addr
!= NULL
;
2084 old_addr
= old_addr
->next
) {
2085 if (old_addr
->address
.len
!= 16) {
2086 log_error("Invalid IPv6 prefix, "
2087 "Ignoring. (%s:%d)",
2092 if (!buffer_allocate(&addr
.buffer
, 25, MDL
)) {
2093 log_error("Unable to allocate memory "
2095 data_string_forget(&ia
, MDL
);
2096 data_string_forget(&ds
, MDL
);
2099 addr
.data
= addr
.buffer
->data
;
2102 t1
= client
->config
->requested_lease
;
2104 putULong(addr
.buffer
->data
, t1
);
2105 putULong(addr
.buffer
->data
+ 4, t2
);
2107 putUChar(addr
.buffer
->data
+ 8,
2109 memcpy(addr
.buffer
->data
+ 9,
2110 old_addr
->address
.iabuf
,
2113 log_debug("XMT: | X-- Request prefix %s/%u.",
2114 piaddr(old_addr
->address
),
2115 (unsigned) old_addr
->plen
);
2116 log_debug("XMT: | | X-- Request "
2119 log_debug("XMT: | | X-- Request valid "
2123 append_option(&ia
, &dhcpv6_universe
,
2127 data_string_forget(&addr
, MDL
);
2131 append_option(&ds
, &dhcpv6_universe
, ia_pd_option
, &ia
);
2132 data_string_forget(&ia
, MDL
);
2135 /* Transmit and wait. */
2137 log_info("XMT: Solicit on %s, interval %ld0ms.",
2138 client
->name
? client
->name
: client
->interface
->name
,
2139 (long int)client
->RT
);
2141 send_ret
= send_packet6(client
->interface
,
2142 ds
.data
, ds
.len
, &DHCPv6DestAddr
);
2143 if (send_ret
!= ds
.len
) {
2144 log_error("dhc6: send_packet6() sent %d of %d bytes",
2148 data_string_forget(&ds
, MDL
);
2151 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2152 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2153 if (tv
.tv_usec
>= 1000000) {
2155 tv
.tv_usec
-= 1000000;
2157 add_timeout(&tv
, do_init6
, client
, NULL
, NULL
);
2159 dhc6_retrans_advance(client
);
2162 /* do_info_request6() marshals and transmits an information-request. */
2164 do_info_request6(void *input
)
2166 struct client_state
*client
;
2167 struct data_string ds
;
2173 switch(check_timing6(client
, DHCPV6_INFORMATION_REQUEST
,
2174 "Info-Request", NULL
, &ds
)) {
2175 case CHK_TIM_MRC_EXCEEDED
:
2176 case CHK_TIM_ALLOC_FAILURE
:
2178 case CHK_TIM_MRD_EXCEEDED
:
2180 case CHK_TIM_SUCCESS
:
2184 /* Fetch any configured 'sent' options (includes DUID) in wire format.
2186 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
,
2187 NULL
, client
->sent_options
, &global_scope
,
2190 /* Transmit and wait. */
2192 log_info("XMT: Info-Request on %s, interval %ld0ms.",
2193 client
->name
? client
->name
: client
->interface
->name
,
2194 (long int)client
->RT
);
2196 send_ret
= send_packet6(client
->interface
,
2197 ds
.data
, ds
.len
, &DHCPv6DestAddr
);
2198 if (send_ret
!= ds
.len
) {
2199 log_error("dhc6: send_packet6() sent %d of %d bytes",
2203 data_string_forget(&ds
, MDL
);
2206 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2207 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2208 if (tv
.tv_usec
>= 1000000) {
2210 tv
.tv_usec
-= 1000000;
2212 add_timeout(&tv
, do_info_request6
, client
, NULL
, NULL
);
2214 dhc6_retrans_advance(client
);
2217 /* do_confirm6() creates a Confirm packet and transmits it. This function
2218 * is called on every timeout to (re)transmit.
2221 do_confirm6(void *input
)
2223 struct client_state
*client
;
2224 struct data_string ds
;
2225 int send_ret
, added
;
2230 if (client
->active_lease
== NULL
)
2231 log_fatal("Impossible condition at %s:%d.", MDL
);
2233 /* In section 17.1.3, it is said:
2235 * If the client receives no responses before the message
2236 * transmission process terminates, as described in section 14,
2237 * the client SHOULD continue to use any IP addresses, using the
2238 * last known lifetimes for those addresses, and SHOULD continue
2239 * to use any other previously obtained configuration parameters.
2241 * So if confirm times out, we go active.
2243 * XXX: Should we reduce all IA's t1 to 0, so that we renew and
2244 * stick there until we get a reply?
2247 switch(check_timing6(client
, DHCPV6_CONFIRM
, "Confirm",
2248 client
->active_lease
, &ds
)) {
2249 case CHK_TIM_MRC_EXCEEDED
:
2250 case CHK_TIM_MRD_EXCEEDED
:
2251 start_bound(client
);
2253 case CHK_TIM_ALLOC_FAILURE
:
2255 case CHK_TIM_SUCCESS
:
2259 /* Fetch any configured 'sent' options (includes DUID') in wire format.
2261 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
, NULL
,
2262 client
->sent_options
, &global_scope
,
2267 dhc6_add_ia_na(client
, &ds
, client
->active_lease
,
2268 DHCPV6_CONFIRM
, 0, &added
) != ISC_R_SUCCESS
) {
2269 data_string_forget(&ds
, MDL
);
2273 dhc6_add_ia_ta(client
, &ds
, client
->active_lease
,
2274 DHCPV6_CONFIRM
, 0, &added
) != ISC_R_SUCCESS
) {
2275 data_string_forget(&ds
, MDL
);
2279 /* Transmit and wait. */
2281 log_info("XMT: Confirm on %s, interval %ld0ms.",
2282 client
->name
? client
->name
: client
->interface
->name
,
2283 (long int)client
->RT
);
2285 send_ret
= send_packet6(client
->interface
, ds
.data
, ds
.len
,
2287 if (send_ret
!= ds
.len
) {
2288 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2292 data_string_forget(&ds
, MDL
);
2295 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2296 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2297 if (tv
.tv_usec
>= 1000000) {
2299 tv
.tv_usec
-= 1000000;
2301 add_timeout(&tv
, do_confirm6
, client
, NULL
, NULL
);
2303 dhc6_retrans_advance(client
);
2307 * Release addresses.
2310 start_release6(struct client_state
*client
)
2312 /* Cancel any pending transmissions */
2313 cancel_timeout(do_confirm6
, client
);
2314 cancel_timeout(do_select6
, client
);
2315 cancel_timeout(do_refresh6
, client
);
2316 cancel_timeout(do_release6
, client
);
2317 client
->state
= S_STOPPED
;
2320 * It is written: "The client MUST NOT use any of the addresses it
2321 * is releasing as the source address in the Release message or in
2322 * any subsequently transmitted message." So unconfigure now.
2324 unconfigure6(client
, "RELEASE6");
2326 /* Note this in the lease file. */
2327 if (client
->active_lease
== NULL
)
2329 client
->active_lease
->released
= ISC_TRUE
;
2330 write_client6_lease(client
, client
->active_lease
, 0, 1);
2332 /* Set timers per RFC3315 section 18.1.6. */
2333 client
->IRT
= REL_TIMEOUT
* 100;
2335 client
->MRC
= REL_MAX_RC
;
2338 dhc6_retrans_init(client
);
2339 client
->v6_handler
= reply_handler
;
2341 do_release6(client
);
2344 * do_release6() creates a Release packet and transmits it.
2347 do_release6(void *input
)
2349 struct client_state
*client
;
2350 struct data_string ds
;
2351 int send_ret
, added
;
2356 if ((client
->active_lease
== NULL
) || !active_prefix(client
))
2359 switch(check_timing6(client
, DHCPV6_RELEASE
, "Release",
2360 client
->active_lease
, &ds
)) {
2361 case CHK_TIM_MRC_EXCEEDED
:
2362 case CHK_TIM_ALLOC_FAILURE
:
2363 case CHK_TIM_MRD_EXCEEDED
:
2365 case CHK_TIM_SUCCESS
:
2370 * Don't use unicast as we don't know if we still have an
2371 * available address with enough scope.
2374 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
, NULL
,
2375 client
->sent_options
, &global_scope
,
2378 /* Append IA's (but don't release temporary addresses). */
2380 dhc6_add_ia_na(client
, &ds
, client
->active_lease
,
2381 DHCPV6_RELEASE
, 0, &added
) != ISC_R_SUCCESS
) {
2382 data_string_forget(&ds
, MDL
);
2386 dhc6_add_ia_pd(client
, &ds
, client
->active_lease
,
2387 DHCPV6_RELEASE
, 0, &added
) != ISC_R_SUCCESS
) {
2388 data_string_forget(&ds
, MDL
);
2392 /* Transmit and wait. */
2393 log_info("XMT: Release on %s, interval %ld0ms.",
2394 client
->name
? client
->name
: client
->interface
->name
,
2395 (long int)client
->RT
);
2397 send_ret
= send_packet6(client
->interface
, ds
.data
, ds
.len
,
2399 if (send_ret
!= ds
.len
) {
2400 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2404 data_string_forget(&ds
, MDL
);
2407 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2408 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2409 if (tv
.tv_usec
>= 1000000) {
2411 tv
.tv_usec
-= 1000000;
2413 add_timeout(&tv
, do_release6
, client
, NULL
, NULL
);
2414 dhc6_retrans_advance(client
);
2418 dhc6_lease_destroy(&client
->active_lease
, MDL
);
2419 client
->active_lease
= NULL
;
2420 if (stopping_finished())
2424 /* status_log() just puts a status code into displayable form and logs it
2428 status_log(int code
, const char *scope
, const char *additional
, int len
)
2430 const char *msg
= NULL
;
2433 case STATUS_Success
:
2437 case STATUS_UnspecFail
:
2441 case STATUS_NoAddrsAvail
:
2442 msg
= "NoAddrsAvail";
2445 case STATUS_NoBinding
:
2449 case STATUS_NotOnLink
:
2453 case STATUS_UseMulticast
:
2454 msg
= "UseMulticast";
2457 case STATUS_NoPrefixAvail
:
2458 msg
= "NoPrefixAvail";
2467 log_info("%s status code %s: %s", scope
, msg
,
2469 (const unsigned char *)additional
, 50));
2471 log_info("%s status code %s.", scope
, msg
);
2474 /* Acquire a status code.
2477 dhc6_get_status_code(struct option_state
*options
, unsigned *code
,
2478 struct data_string
*msg
)
2480 struct option_cache
*oc
;
2481 struct data_string ds
;
2482 isc_result_t rval
= ISC_R_SUCCESS
;
2484 if ((options
== NULL
) || (code
== NULL
))
2485 return DHCP_R_INVALIDARG
;
2487 if ((msg
!= NULL
) && (msg
->len
!= 0))
2488 return DHCP_R_INVALIDARG
;
2490 memset(&ds
, 0, sizeof(ds
));
2492 /* Assume success if there is no option. */
2493 *code
= STATUS_Success
;
2495 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_STATUS_CODE
);
2497 evaluate_option_cache(&ds
, NULL
, NULL
, NULL
, options
,
2498 NULL
, &global_scope
, oc
, MDL
)) {
2500 log_error("Invalid status code length %d.", ds
.len
);
2501 rval
= DHCP_R_FORMERR
;
2503 *code
= getUShort(ds
.data
);
2505 if ((msg
!= NULL
) && (ds
.len
> 2)) {
2506 data_string_copy(msg
, &ds
, MDL
);
2511 data_string_forget(&ds
, MDL
);
2515 return ISC_R_NOTFOUND
;
2518 /* Look at status codes in an advertise, and reform the return value.
2521 dhc6_check_status(isc_result_t rval
, struct option_state
*options
,
2522 const char *scope
, unsigned *code
)
2524 struct data_string msg
;
2525 isc_result_t status
;
2527 if ((scope
== NULL
) || (code
== NULL
))
2528 return DHCP_R_INVALIDARG
;
2530 /* If we don't find a code, we assume success. */
2531 *code
= STATUS_Success
;
2533 /* If there is no options cache, then there is no code. */
2534 if (options
!= NULL
) {
2535 memset(&msg
, 0, sizeof(msg
));
2536 status
= dhc6_get_status_code(options
, code
, &msg
);
2538 if (status
== ISC_R_SUCCESS
) {
2539 status_log(*code
, scope
, (char *)msg
.data
, msg
.len
);
2540 data_string_forget(&msg
, MDL
);
2542 if (*code
!= STATUS_Success
)
2543 rval
= ISC_R_FAILURE
;
2545 } else if (status
!= ISC_R_NOTFOUND
)
2552 /* Determine if this packet could provide usable information.
2553 * We check the status codes at the top level and at the IA level,
2554 * IAADDRS have already been checked in the leaseify step and any with
2555 * a bad format or status code that wasn't success have been dropped.
2557 * leaseify has also already removed any IAs for which the top level status
2558 * code or the IA status code indicated no addresses or prefixes were
2562 dhc6_check_advertise(struct dhc6_lease
*lease
)
2565 isc_result_t rval
= ISC_R_SUCCESS
;
2566 int have_addrs
= ISC_FALSE
;
2569 int got_na
= 0, got_ta
= 0, got_pd
= 0;
2571 rval
= dhc6_check_status(rval
, lease
->options
, "message", &code
);
2573 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
2574 switch (ia
->ia_type
) {
2588 log_error("dhc6_check_advertise: no type.");
2589 return ISC_R_FAILURE
;
2591 /* Currently we toss packets if we have an error getting a
2592 * status code or if the status code isn't success, so
2593 * no need to loop through the addresses */
2594 rval
= dhc6_check_status(rval
, ia
->options
, scope
, &code
);
2595 if (rval
!= ISC_R_SUCCESS
)
2598 /* We don't need to check status on IAADDRS here as we already
2599 * did it as part of the leaseify step and tossed bad IAADDRS.
2600 * We are just checking to see if we have any addrs.
2601 * Should we check the addr itself for usability?
2603 if (ia
->addrs
!= NULL
) {
2604 have_addrs
= ISC_TRUE
;
2608 /* If we didn't get some addrs or the user required us to
2609 * get all of the requested IAs and we didn't return an error
2611 if ((have_addrs
!= ISC_TRUE
) ||
2612 ((require_all_ias
!= 0) &&
2613 ((got_na
< wanted_ia_na
) ||
2614 (got_ta
< wanted_ia_ta
) ||
2615 (got_pd
< wanted_ia_pd
))))
2616 rval
= ISC_R_ADDRNOTAVAIL
;
2621 /* status code <-> action matrix for the client in INIT state
2622 * (rapid/commit). Returns always false as no action is defined.
2624 static isc_boolean_t
2625 dhc6_init_action(struct client_state
*client
, isc_result_t
*rvalp
,
2629 log_fatal("Impossible condition at %s:%d.", MDL
);
2631 if (client
== NULL
) {
2632 *rvalp
= DHCP_R_INVALIDARG
;
2636 if (*rvalp
== ISC_R_SUCCESS
)
2639 /* No possible action in any case... */
2643 /* status code <-> action matrix for the client in SELECT state
2644 * (request/reply). Returns true if action was taken (and the
2645 * packet should be ignored), or false if no action was taken.
2647 static isc_boolean_t
2648 dhc6_select_action(struct client_state
*client
, isc_result_t
*rvalp
,
2651 struct dhc6_lease
*lease
;
2655 log_fatal("Impossible condition at %s:%d.", MDL
);
2657 if (client
== NULL
) {
2658 *rvalp
= DHCP_R_INVALIDARG
;
2663 if (rval
== ISC_R_SUCCESS
)
2667 /* We may have an earlier failure status code (so no
2668 * success rval), and a success code now. This
2669 * doesn't upgrade the rval to success, but it does
2670 * mean we take no action here.
2672 case STATUS_Success
:
2673 /* Gimpy server, or possibly an attacker. */
2674 case STATUS_NoBinding
:
2675 case STATUS_UseMulticast
:
2676 /* Take no action. */
2679 /* If the server can't deal with us, either try the
2680 * next advertised server, or continue retrying if there
2684 case STATUS_UnspecFail
:
2685 if (client
->advertised_leases
!= NULL
) {
2686 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
2687 client
->selected_lease
= NULL
;
2689 start_selecting6(client
);
2692 } else /* Take no action - continue to retry. */
2695 /* If the server has no addresses, try other servers if
2696 * we got some, otherwise go to INIT to hope for more
2699 case STATUS_NoAddrsAvail
:
2700 case STATUS_NoPrefixAvail
:
2701 if (client
->state
== S_REBOOTING
)
2704 if (client
->selected_lease
== NULL
)
2705 log_fatal("Impossible case at %s:%d.", MDL
);
2707 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
2708 client
->selected_lease
= NULL
;
2710 if (client
->advertised_leases
!= NULL
)
2711 start_selecting6(client
);
2713 start_init6(client
);
2717 /* If we got a NotOnLink from a Confirm, then we're not
2718 * on link. Kill the old-active binding and start over.
2720 * If we got a NotOnLink from our Request, something weird
2721 * happened. Start over from scratch anyway.
2723 case STATUS_NotOnLink
:
2724 if (client
->state
== S_REBOOTING
) {
2725 if (client
->active_lease
== NULL
)
2726 log_fatal("Impossible case at %s:%d.", MDL
);
2728 dhc6_lease_destroy(&client
->active_lease
, MDL
);
2730 if (client
->selected_lease
== NULL
)
2731 log_fatal("Impossible case at %s:%d.", MDL
);
2733 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
2734 client
->selected_lease
= NULL
;
2736 while (client
->advertised_leases
!= NULL
) {
2737 lease
= client
->advertised_leases
;
2738 client
->advertised_leases
= lease
->next
;
2740 dhc6_lease_destroy(&lease
, MDL
);
2744 start_init6(client
);
2752 dhc6_withdraw_lease(struct client_state
*client
)
2755 struct dhc6_addr
*addr
;
2757 if ((client
== NULL
) || (client
->active_lease
== NULL
))
2760 for (ia
= client
->active_lease
->bindings
; ia
!= NULL
;
2762 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
2763 addr
->max_life
= addr
->preferred_life
= 0;
2767 /* Perform expiry. */
2771 /* status code <-> action matrix for the client in BOUND state
2772 * (request/reply). Returns true if action was taken (and the
2773 * packet should be ignored), or false if no action was taken.
2775 static isc_boolean_t
2776 dhc6_reply_action(struct client_state
*client
, isc_result_t
*rvalp
,
2782 log_fatal("Impossible condition at %s:%d.", MDL
);
2784 if (client
== NULL
) {
2785 *rvalp
= DHCP_R_INVALIDARG
;
2790 if (rval
== ISC_R_SUCCESS
)
2794 /* It's possible an earlier status code set rval to a failure
2795 * code, and we've encountered a later success.
2797 case STATUS_Success
:
2798 /* In "refreshes" (where we get replies), we probably
2799 * still have a valid lease. So "take no action" and
2800 * the upper levels will keep retrying until the lease
2801 * expires (or we rebind).
2803 case STATUS_UnspecFail
:
2804 /* For unknown codes...it's a soft (retryable) error. */
2808 /* The server is telling us to use a multicast address, so
2809 * we have to delete the unicast option from the active
2810 * lease, then allow retransmission to occur normally.
2811 * (XXX: It might be preferable in this case to retransmit
2812 * sooner than the current interval, but for now we don't.)
2814 case STATUS_UseMulticast
:
2815 if (client
->active_lease
!= NULL
)
2816 delete_option(&dhcp_universe
,
2817 client
->active_lease
->options
,
2821 /* "When the client receives a NotOnLink status from the
2822 * server in response to a Request, the client can either
2823 * re-issue the Request without specifying any addresses
2824 * or restart the DHCP server discovery process."
2826 * This is strange. If competing server evaluation is
2827 * useful (and therefore in the protocol), then why would
2828 * a client's first reaction be to request from the same
2829 * server on a different link? Surely you'd want to
2830 * re-evaluate your server selection.
2832 * Well, I guess that's the answer.
2834 case STATUS_NotOnLink
:
2835 /* In this case, we need to rescind all current active
2836 * bindings (just 'expire' them all normally, if early).
2837 * They're no use to us on the wrong link. Then head back
2838 * to init, redo server selection and get new addresses.
2840 dhc6_withdraw_lease(client
);
2843 /* "If the status code is NoAddrsAvail, the client has
2844 * received no usable addresses in the IA and may choose
2845 * to try obtaining addresses for the IA from another
2848 case STATUS_NoAddrsAvail
:
2849 case STATUS_NoPrefixAvail
:
2850 /* Head back to init, keeping any active bindings (!). */
2851 start_init6(client
);
2854 /* - sends a Request message if the IA contained a Status
2855 * Code option with the NoBinding status (and does not
2856 * send any additional Renew/Rebind messages)
2858 case STATUS_NoBinding
:
2859 if (client
->advertised_leases
!= NULL
)
2860 log_fatal("Impossible condition at %s:%d.", MDL
);
2862 client
->advertised_leases
=
2863 dhc6_dup_lease(client
->active_lease
, MDL
);
2864 start_selecting6(client
);
2871 /* status code <-> action matrix for the client in STOPPED state
2872 * (release/decline). Returns true if action was taken (and the
2873 * packet should be ignored), or false if no action was taken.
2874 * NoBinding is translated into Success.
2876 static isc_boolean_t
2877 dhc6_stop_action(struct client_state
*client
, isc_result_t
*rvalp
,
2883 log_fatal("Impossible condition at %s:%d.", MDL
);
2885 if (client
== NULL
) {
2886 *rvalp
= DHCP_R_INVALIDARG
;
2891 if (rval
== ISC_R_SUCCESS
)
2895 /* It's possible an earlier status code set rval to a failure
2896 * code, and we've encountered a later success.
2898 case STATUS_Success
:
2899 /* For unknown codes...it's a soft (retryable) error. */
2900 case STATUS_UnspecFail
:
2904 /* NoBinding is not an error */
2905 case STATUS_NoBinding
:
2906 if (rval
== ISC_R_FAILURE
)
2907 *rvalp
= ISC_R_SUCCESS
;
2910 /* Should not happen */
2911 case STATUS_NoAddrsAvail
:
2912 case STATUS_NoPrefixAvail
:
2916 case STATUS_NotOnLink
:
2919 /* The server is telling us to use a multicast address, so
2920 * we have to delete the unicast option from the active
2921 * lease, then allow retransmission to occur normally.
2922 * (XXX: It might be preferable in this case to retransmit
2923 * sooner than the current interval, but for now we don't.)
2925 case STATUS_UseMulticast
:
2926 if (client
->active_lease
!= NULL
)
2927 delete_option(&dhcp_universe
,
2928 client
->active_lease
->options
,
2936 /* Look at a new and old lease, and make sure the new information is not
2937 * losing us any state.
2940 dhc6_check_reply(struct client_state
*client
, struct dhc6_lease
*new)
2942 isc_boolean_t (*action
)(struct client_state
*,
2943 isc_result_t
*, unsigned);
2945 isc_result_t rval
= ISC_R_SUCCESS
;
2949 int have_addrs
= ISC_FALSE
;
2950 int got_na
= 0, got_ta
= 0, got_pd
= 0;
2952 if ((client
== NULL
) || (new == NULL
))
2953 return DHCP_R_INVALIDARG
;
2955 switch (client
->state
) {
2957 action
= dhc6_init_action
;
2962 action
= dhc6_select_action
;
2967 action
= dhc6_reply_action
;
2971 action
= dhc6_stop_action
;
2975 log_fatal("Impossible condition at %s:%d.", MDL
);
2976 return ISC_R_CANCELED
;
2979 /* If there is a code to extract, and if there is some
2980 * action to take based on that code, then take the action
2981 * and do not continue.
2983 rval
= dhc6_check_status(rval
, new->options
, "message", &code
);
2984 if (action(client
, &rval
, code
))
2985 return ISC_R_CANCELED
;
2987 for (ia
= new->bindings
; ia
!= NULL
; ia
= ia
->next
) {
2988 switch (ia
->ia_type
) {
3002 log_error("dhc6_check_reply: no type.");
3003 return DHCP_R_INVALIDARG
;
3005 rval
= dhc6_check_status(rval
, ia
->options
, scope
, &code
);
3007 if (action(client
, &rval
, code
))
3008 return ISC_R_CANCELED
;
3010 if (ia
->addrs
!= NULL
) {
3011 have_addrs
= ISC_TRUE
;
3015 /* A Confirm->Reply is unsuitable for comparison to the old lease. */
3016 if (client
->state
== S_REBOOTING
)
3019 /* We expect the lease to have at least one address and if
3020 * required all of the requested IAs if not flag it as
3021 * NoAddrs and call the action routine to try again.
3023 * Currently we don't completely handle TAs in all cases
3024 * so we don't check them for requires. I've left the
3025 * check in and commented it as I eventually do want
3026 * us to check for TAs as well. SAR
3028 if ((have_addrs
!= ISC_TRUE
) ||
3029 ((require_all_ias
!= 0) &&
3030 ((got_na
< wanted_ia_na
) ||
3031 /*(got_ta < wanted_ia_ta) ||*/
3032 (got_pd
< wanted_ia_pd
)))) {
3033 rval
= ISC_R_FAILURE
;
3034 if (action(client
, &rval
, STATUS_NoAddrsAvail
) == ISC_TRUE
) {
3035 return ISC_R_CANCELED
;
3039 /* No old lease in rapid-commit. */
3040 if (client
->state
== S_INIT
)
3043 switch (client
->state
) {
3045 /* Compare the new lease with the selected lease to make
3046 * sure there is no risky business.
3048 nscore
= dhc6_score_lease(client
, new);
3049 sscore
= dhc6_score_lease(client
, client
->selected_lease
);
3050 if ((client
->advertised_leases
!= NULL
) &&
3051 (nscore
< (sscore
/ 2))) {
3052 /* XXX: An attacker might reply this way to make
3053 * XXX: sure we latch onto their configuration.
3054 * XXX: We might want to ignore the packet and
3055 * XXX: schedule re-selection at the next timeout?
3057 log_error("PRC: BAIT AND SWITCH detected. Score of "
3058 "supplied lease (%d) is substantially "
3059 "smaller than the advertised score (%d). "
3060 "Trying other servers.",
3063 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
3064 client
->selected_lease
= NULL
;
3066 start_selecting6(client
);
3068 return ISC_R_CANCELED
;
3074 /* This leaves one RFC3315 status check unimplemented:
3076 * - sends a Renew/Rebind if the IA is not in the Reply
3079 * We rely on the scheduling system to note that the IA has
3080 * not left Renewal/Rebinding/whatever since it still carries
3081 * old times from the last successful binding. So this is
3082 * implemented actually, just not explicitly.
3087 /* Nothing critical to do at this stage. */
3091 log_fatal("REALLY impossible condition at %s:%d.", MDL
);
3092 return ISC_R_CANCELED
;
3098 /* While in init state, we only collect advertisements. If there happens
3099 * to be an advertisement with a preference option of 255, that's an
3100 * automatic exit. Otherwise, we collect advertisements until our timeout
3101 * expires (client->RT).
3104 init_handler(struct packet
*packet
, struct client_state
*client
)
3106 struct dhc6_lease
*lease
;
3108 /* In INIT state, we send solicits, we only expect to get
3109 * advertises (rapid commit has its own handler).
3111 if (packet
->dhcpv6_msg_type
!= DHCPV6_ADVERTISE
)
3114 /* RFC3315 section 15.3 validation (same as 15.10 since we
3115 * always include a client id).
3117 if (!valid_reply(packet
, client
)) {
3118 log_error("Invalid Advertise - rejecting.");
3122 lease
= dhc6_leaseify(packet
, client
);
3124 /* Out of memory or corrupt packet condition...hopefully a temporary
3125 * problem. Returning now makes us try to retransmit later.
3130 if (dhc6_check_advertise(lease
) != ISC_R_SUCCESS
) {
3131 log_debug("PRC: Lease failed to satisfy.");
3132 dhc6_lease_destroy(&lease
, MDL
);
3136 insert_lease(&client
->advertised_leases
, lease
);
3138 /* According to RFC3315 section 17.1.2, the client MUST wait for
3139 * the first RT before selecting a lease. But on the 400th RT,
3140 * we dont' want to wait the full timeout if we finally get an
3141 * advertise. We could probably wait a second, but ohwell,
3142 * RFC3315 doesn't say so.
3144 * If the lease is highest possible preference, 255, RFC3315 claims
3145 * we should continue immediately even on the first RT. We probably
3146 * should not if the advertise contains less than one IA and address.
3148 if ((client
->txcount
> 1) ||
3149 ((lease
->pref
== 255) &&
3150 (dhc6_score_lease(client
, lease
) > SCORE_MIN
))) {
3151 log_debug("RCV: Advertisement immediately selected.");
3152 cancel_timeout(do_init6
, client
);
3153 start_selecting6(client
);
3155 log_debug("RCV: Advertisement recorded.");
3158 /* info_request_handler() accepts a Reply to an Info-request.
3161 info_request_handler(struct packet
*packet
, struct client_state
*client
)
3163 isc_result_t check_status
;
3166 if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
3169 /* RFC3315 section 15.10 validation (same as 15.3 since we
3170 * always include a client id).
3172 if (!valid_reply(packet
, client
)) {
3173 log_error("Invalid Reply - rejecting.");
3177 check_status
= dhc6_check_status(ISC_R_SUCCESS
, packet
->options
,
3180 if (check_status
!= ISC_R_SUCCESS
) {
3181 /* If no action was taken, but there is an error, then
3182 * we wait for a retransmission.
3184 if (check_status
!= ISC_R_CANCELED
)
3188 /* We're done retransmitting at this point. */
3189 cancel_timeout(do_info_request6
, client
);
3191 /* Action was taken, so now that we've torn down our scheduled
3192 * retransmissions, return.
3194 if (check_status
== ISC_R_CANCELED
)
3197 /* Cleanup if a previous attempt to go bound failed. */
3198 if (client
->old_lease
!= NULL
) {
3199 dhc6_lease_destroy(&client
->old_lease
, MDL
);
3200 client
->old_lease
= NULL
;
3203 /* Cache options in the active_lease. */
3204 if (client
->active_lease
!= NULL
)
3205 client
->old_lease
= client
->active_lease
;
3206 client
->active_lease
= dmalloc(sizeof(struct dhc6_lease
), MDL
);
3207 if (client
->active_lease
== NULL
)
3208 log_fatal("Out of memory for v6 lease structure.");
3209 option_state_reference(&client
->active_lease
->options
,
3210 packet
->options
, MDL
);
3212 execute_statements_in_scope(NULL
, (struct packet
*)packet
, NULL
, client
,
3213 client
->active_lease
->options
,
3214 client
->active_lease
->options
,
3215 &global_scope
, client
->config
->on_receipt
,
3218 start_informed(client
);
3221 /* Specific version of init_handler() for rapid-commit.
3224 rapid_commit_handler(struct packet
*packet
, struct client_state
*client
)
3226 struct dhc6_lease
*lease
;
3227 isc_result_t check_status
;
3229 /* On ADVERTISE just fall back to the init_handler().
3231 if (packet
->dhcpv6_msg_type
== DHCPV6_ADVERTISE
) {
3232 init_handler(packet
, client
);
3234 } else if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
3237 /* RFC3315 section 15.10 validation (same as 15.3 since we
3238 * always include a client id).
3240 if (!valid_reply(packet
, client
)) {
3241 log_error("Invalid Reply - rejecting.");
3245 /* A rapid-commit option MUST be here. */
3246 if (lookup_option(&dhcpv6_universe
, packet
->options
,
3247 D6O_RAPID_COMMIT
) == 0) {
3248 log_error("Reply without Rapid-Commit - rejecting.");
3252 lease
= dhc6_leaseify(packet
, client
);
3254 /* Out of memory or corrupt packet condition...hopefully a temporary
3255 * problem. Returning now makes us try to retransmit later.
3260 check_status
= dhc6_check_reply(client
, lease
);
3261 if (check_status
!= ISC_R_SUCCESS
) {
3262 dhc6_lease_destroy(&lease
, MDL
);
3266 /* Jump to the selecting state. */
3267 cancel_timeout(do_init6
, client
);
3268 client
->state
= S_SELECTING
;
3270 /* Merge any bindings in the active lease (if there is one) into
3271 * the new active lease.
3273 dhc6_merge_lease(client
->active_lease
, lease
);
3275 /* Cleanup if a previous attempt to go bound failed. */
3276 if (client
->old_lease
!= NULL
) {
3277 dhc6_lease_destroy(&client
->old_lease
, MDL
);
3278 client
->old_lease
= NULL
;
3281 /* Make this lease active and BIND to it. */
3282 if (client
->active_lease
!= NULL
)
3283 client
->old_lease
= client
->active_lease
;
3284 client
->active_lease
= lease
;
3286 /* We're done with the ADVERTISEd leases, if any. */
3287 while(client
->advertised_leases
!= NULL
) {
3288 lease
= client
->advertised_leases
;
3289 client
->advertised_leases
= lease
->next
;
3291 dhc6_lease_destroy(&lease
, MDL
);
3294 start_bound(client
);
3297 /* Find the 'best' lease in the cache of advertised leases (usually). From
3298 * RFC3315 Section 17.1.3:
3300 * Upon receipt of one or more valid Advertise messages, the client
3301 * selects one or more Advertise messages based upon the following
3304 * - Those Advertise messages with the highest server preference value
3305 * are preferred over all other Advertise messages.
3307 * - Within a group of Advertise messages with the same server
3308 * preference value, a client MAY select those servers whose
3309 * Advertise messages advertise information of interest to the
3310 * client. For example, the client may choose a server that returned
3311 * an advertisement with configuration options of interest to the
3314 * - The client MAY choose a less-preferred server if that server has a
3315 * better set of advertised parameters, such as the available
3316 * addresses advertised in IAs.
3318 * Note that the first and third contradict each other. The third should
3319 * probably be taken to mean that the client should prefer answers that
3320 * offer bindings, even if that violates the preference rule.
3322 * The above also isn't deterministic where there are ties. So the final
3323 * tiebreaker we add, if all other values are equal, is to compare the
3324 * server identifiers and to select the numerically lower one.
3326 static struct dhc6_lease
*
3327 dhc6_best_lease(struct client_state
*client
, struct dhc6_lease
**head
)
3329 struct dhc6_lease
**rpos
, *rval
, **candp
, *cand
;
3332 if (head
== NULL
|| *head
== NULL
)
3337 rscore
= dhc6_score_lease(client
, rval
);
3338 candp
= &rval
->next
;
3341 log_debug("PRC: Considering best lease.");
3342 log_debug("PRC: X-- Initial candidate %s (s: %d, p: %u).",
3343 print_hex_1(rval
->server_id
.len
,
3344 rval
->server_id
.data
, 48),
3345 rscore
, (unsigned)rval
->pref
);
3347 for (; cand
!= NULL
; candp
= &cand
->next
, cand
= *candp
) {
3348 cscore
= dhc6_score_lease(client
, cand
);
3350 log_debug("PRC: X-- Candidate %s (s: %d, p: %u).",
3351 print_hex_1(cand
->server_id
.len
,
3352 cand
->server_id
.data
, 48),
3353 cscore
, (unsigned)cand
->pref
);
3355 /* Above you'll find quoted RFC3315 Section 17.1.3.
3357 * The third clause tells us to give up on leases that
3358 * have no bindings even if their preference is better.
3359 * So where our 'selected' lease's score is less than
3360 * SCORE_MIN (1 ia + 1 addr), choose any candidate >= SCORE_MIN.
3362 * The first clause tells us to make preference the primary
3363 * deciding factor. So if it's lower, reject, if it's
3366 * The second clause tells us where the preference is
3367 * equal, we should use 'our judgement' of what we like
3368 * to see in an advertisement primarily.
3370 * But there can still be a tie. To make this deterministic,
3371 * we compare the server identifiers and select the binary
3374 * Since server id's are unique in this list, there is
3375 * no further tie to break.
3377 if ((rscore
< SCORE_MIN
) && (cscore
>= SCORE_MIN
)) {
3378 log_debug("PRC: | X-- Selected, has bindings.");
3379 } else if (cand
->pref
< rval
->pref
) {
3380 log_debug("PRC: | X-- Rejected, lower preference.");
3382 } else if (cand
->pref
> rval
->pref
) {
3383 log_debug("PRC: | X-- Selected, higher preference.");
3384 } else if (cscore
> rscore
) {
3385 log_debug("PRC: | X-- Selected, equal preference, "
3387 } else if (cscore
< rscore
) {
3388 log_debug("PRC: | X-- Rejected, equal preference, "
3391 } else if ((cand
->server_id
.len
< rval
->server_id
.len
) ||
3392 ((cand
->server_id
.len
== rval
->server_id
.len
) &&
3393 (memcmp(cand
->server_id
.data
,
3394 rval
->server_id
.data
,
3395 cand
->server_id
.len
) < 0))) {
3396 log_debug("PRC: | X-- Selected, equal preference, "
3397 "equal score, binary lesser server ID.");
3399 log_debug("PRC: | X-- Rejected, equal preference, "
3400 "equal score, binary greater server ID.");
3409 /* Remove the selected lease from the chain. */
3415 /* Select a lease out of the advertised leases and setup state to try and
3416 * acquire that lease.
3419 start_selecting6(struct client_state
*client
)
3421 struct dhc6_lease
*lease
;
3423 if (client
->advertised_leases
== NULL
) {
3424 log_error("Can not enter DHCPv6 SELECTING state with no "
3425 "leases to select from!");
3429 log_debug("PRC: Selecting best advertised lease.");
3430 client
->state
= S_SELECTING
;
3432 lease
= dhc6_best_lease(client
, &client
->advertised_leases
);
3435 log_fatal("Impossible error at %s:%d.", MDL
);
3437 client
->selected_lease
= lease
;
3439 /* Set timers per RFC3315 section 18.1.1. */
3440 client
->IRT
= REQ_TIMEOUT
* 100;
3441 client
->MRT
= REQ_MAX_RT
* 100;
3442 client
->MRC
= REQ_MAX_RC
;
3445 dhc6_retrans_init(client
);
3447 client
->v6_handler
= reply_handler
;
3449 /* ("re")transmit the first packet. */
3453 /* Transmit a Request to select a lease offered in Advertisements. In
3454 * the event of failure, either move on to the next-best advertised lease,
3455 * or head back to INIT state if there are none.
3458 do_select6(void *input
)
3460 struct client_state
*client
;
3461 struct dhc6_lease
*lease
;
3462 struct data_string ds
;
3464 int send_ret
, added
;
3468 /* 'lease' is fewer characters to type. */
3469 lease
= client
->selected_lease
;
3470 if (lease
== NULL
|| lease
->bindings
== NULL
) {
3471 log_error("Illegal to attempt selection without selecting "
3476 switch(check_timing6(client
, DHCPV6_REQUEST
, "Request", lease
, &ds
)) {
3477 case CHK_TIM_MRC_EXCEEDED
:
3478 case CHK_TIM_MRD_EXCEEDED
:
3479 log_debug("PRC: Lease %s failed.",
3480 print_hex_1(lease
->server_id
.len
,
3481 lease
->server_id
.data
, 56));
3483 /* Get rid of the lease that timed/counted out. */
3484 dhc6_lease_destroy(&lease
, MDL
);
3485 client
->selected_lease
= NULL
;
3487 /* If there are more leases great. If not, get more. */
3488 if (client
->advertised_leases
!= NULL
)
3489 start_selecting6(client
);
3491 start_init6(client
);
3493 case CHK_TIM_ALLOC_FAILURE
:
3495 case CHK_TIM_SUCCESS
:
3499 /* Now make a packet that looks suspiciously like the one we
3500 * got from the server. But different.
3502 * XXX: I guess IAID is supposed to be something the client
3503 * indicates and uses as a key to its internal state. It is
3504 * kind of odd to ask the server for IA's whose IAID the client
3505 * did not manufacture. We first need a formal dhclient.conf
3506 * construct for the iaid, then we can delve into this matter
3507 * more properly. In the time being, this will work.
3510 /* Fetch any configured 'sent' options (includes DUID) in wire format.
3512 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
,
3513 NULL
, client
->sent_options
, &global_scope
,
3516 /* Now append any IA's, and within them any IAADDR/IAPREFIXs.
3517 * For each type of IA (na, ta, pd) we start with the ones for
3518 * which we already have addresses (dhc6_add_ia_xx) and then
3519 * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
3522 ((dhc6_add_ia_na(client
, &ds
, lease
, DHCPV6_REQUEST
,
3523 wanted_ia_na
, &added
) != ISC_R_SUCCESS
) ||
3524 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_na
- added
,
3525 D6O_IA_NA
) != ISC_R_SUCCESS
))) {
3526 data_string_forget(&ds
, MDL
);
3530 ((dhc6_add_ia_ta(client
, &ds
, lease
, DHCPV6_REQUEST
,
3531 wanted_ia_ta
, &added
) != ISC_R_SUCCESS
) ||
3532 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_ta
- added
,
3533 D6O_IA_TA
) != ISC_R_SUCCESS
))) {
3534 data_string_forget(&ds
, MDL
);
3538 ((dhc6_add_ia_pd(client
, &ds
, lease
, DHCPV6_REQUEST
,
3539 wanted_ia_pd
, &added
) != ISC_R_SUCCESS
) ||
3540 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_pd
- added
,
3541 D6O_IA_PD
) != ISC_R_SUCCESS
))) {
3542 data_string_forget(&ds
, MDL
);
3546 log_info("XMT: Request on %s, interval %ld0ms.",
3547 client
->name
? client
->name
: client
->interface
->name
,
3548 (long int)client
->RT
);
3550 send_ret
= send_packet6(client
->interface
,
3551 ds
.data
, ds
.len
, &DHCPv6DestAddr
);
3552 if (send_ret
!= ds
.len
) {
3553 log_error("dhc6: send_packet6() sent %d of %d bytes",
3557 data_string_forget(&ds
, MDL
);
3560 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
3561 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
3562 if (tv
.tv_usec
>= 1000000) {
3564 tv
.tv_usec
-= 1000000;
3566 add_timeout(&tv
, do_select6
, client
, NULL
, NULL
);
3568 dhc6_retrans_advance(client
);
3573 * \brief Count the number of IAs in the bindings
3575 * \param lease the lease to count
3576 * \param ia_type the type of the IA we wish to count
3578 * \return The number of IAs of the specified type we found
3581 dhc6_count_ia(struct dhc6_lease
*lease
, u_int16_t ia_type
)
3586 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
3587 if (ia
->ia_type
== ia_type
)
3588 /* bump the counter for the correct types */
3597 * \brief Add IA_NA information from the lease to the packet
3600 * Walk through the lease and for each IA_NA in the lease
3601 * and for each address in the IA_NA append that information
3602 * onto the packet-so-far. If wanted is 0 include all IA_NAs
3603 * in the lease if wanted is non-zero include only that many
3604 * IA_NAs (this may occur if sommebody restarts a client with
3605 * arugments for a smaller number of NAs than before).
3607 * \param client = the state of the entire client
3608 * \param packet = the packet we are building and where we
3609 * shall append the IA_NAs we create
3610 * \param lease = the current lease
3611 * \param message = the type of the packet
3612 * \param wanted = the number of IA_NAs to include in the packet
3613 * 0 means include all
3614 * \param added = the number of IA_NAs that were added to the packet
3616 * \return ISC_R_SUCCESS - all is well continue, any other return
3617 * indicates an error (most likely memory issues)
3618 * and the packet should be tossed.
3621 dhc6_add_ia_na(struct client_state
*client
, struct data_string
*packet
,
3622 struct dhc6_lease
*lease
, u_int8_t message
,
3623 int wanted
, int *added
)
3625 struct data_string iads
;
3626 struct data_string addrds
;
3627 struct dhc6_addr
*addr
;
3629 isc_result_t rval
= ISC_R_SUCCESS
;
3634 memset(&iads
, 0, sizeof(iads
));
3635 memset(&addrds
, 0, sizeof(addrds
));
3636 for (ia
= lease
->bindings
, i
= 0;
3637 ia
!= NULL
&& rval
== ISC_R_SUCCESS
&& (wanted
== 0 || i
< wanted
);
3639 if (ia
->ia_type
!= D6O_IA_NA
)
3642 /* Now that we know this is an NA bump the counter */
3645 if (!buffer_allocate(&iads
.buffer
, 12, MDL
)) {
3646 log_error("Unable to allocate memory for IA_NA.");
3647 rval
= ISC_R_NOMEMORY
;
3651 /* Copy the IAID into the packet buffer. */
3652 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
3653 iads
.data
= iads
.buffer
->data
;
3657 case DHCPV6_REQUEST
:
3661 t1
= client
->config
->requested_lease
/ 2;
3663 #if MAX_TIME > 0xffffffff
3664 if (t1
> 0xffffffff)
3666 if (t2
> 0xffffffff)
3669 putULong(iads
.buffer
->data
+ 4, t1
);
3670 putULong(iads
.buffer
->data
+ 8, t2
);
3672 log_debug("XMT: X-- IA_NA %s",
3673 print_hex_1(4, iads
.data
, 59));
3674 log_debug("XMT: | X-- Requested renew +%u",
3676 log_debug("XMT: | X-- Requested rebind +%u",
3680 case DHCPV6_CONFIRM
:
3681 case DHCPV6_RELEASE
:
3682 case DHCPV6_DECLINE
:
3683 /* Set t1 and t2 to zero; server will ignore them */
3684 memset(iads
.buffer
->data
+ 4, 0, 8);
3685 log_debug("XMT: X-- IA_NA %s",
3686 print_hex_1(4, iads
.buffer
->data
, 55));
3691 log_fatal("Impossible condition at %s:%d.", MDL
);
3694 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
3696 * Do not confirm expired addresses, do not request
3697 * expired addresses (but we keep them around for
3700 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
3703 if (addr
->address
.len
!= 16) {
3704 log_error("Illegal IPv6 address length (%d), "
3705 "ignoring. (%s:%d)",
3706 addr
->address
.len
, MDL
);
3710 if (!buffer_allocate(&addrds
.buffer
, 24, MDL
)) {
3711 log_error("Unable to allocate memory for "
3713 rval
= ISC_R_NOMEMORY
;
3717 addrds
.data
= addrds
.buffer
->data
;
3720 /* Copy the address into the packet buffer. */
3721 memcpy(addrds
.buffer
->data
, addr
->address
.iabuf
, 16);
3723 /* Copy in additional information as appropriate */
3725 case DHCPV6_REQUEST
:
3728 t1
= client
->config
->requested_lease
;
3730 putULong(addrds
.buffer
->data
+ 16, t1
);
3731 putULong(addrds
.buffer
->data
+ 20, t2
);
3733 log_debug("XMT: | | X-- IAADDR %s",
3734 piaddr(addr
->address
));
3735 log_debug("XMT: | | | X-- Preferred "
3736 "lifetime +%u", (unsigned)t1
);
3737 log_debug("XMT: | | | X-- Max lifetime +%u",
3742 case DHCPV6_CONFIRM
:
3744 * Set preferred and max life to zero,
3747 memset(addrds
.buffer
->data
+ 16, 0, 8);
3748 log_debug("XMT: | X-- Confirm Address %s",
3749 piaddr(addr
->address
));
3752 case DHCPV6_RELEASE
:
3753 /* Preferred and max life are irrelevant */
3754 memset(addrds
.buffer
->data
+ 16, 0, 8);
3755 log_debug("XMT: | X-- Release Address %s",
3756 piaddr(addr
->address
));
3759 case DHCPV6_DECLINE
:
3760 /* Preferred and max life are irrelevant */
3761 memset(addrds
.buffer
->data
+ 16, 0, 8);
3762 log_debug("XMT: | X-- Decline Address %s",
3763 piaddr(addr
->address
));
3767 log_fatal("Impossible condition at %s:%d.",
3771 append_option(&iads
, &dhcpv6_universe
, iaaddr_option
,
3773 data_string_forget(&addrds
, MDL
);
3777 * It doesn't make sense to make a request without an
3780 if (ia
->addrs
== NULL
) {
3781 log_debug("!!!: V IA_NA has no IAADDRs - removed.");
3782 rval
= ISC_R_FAILURE
;
3783 } else if (rval
== ISC_R_SUCCESS
) {
3784 log_debug("XMT: V IA_NA appended.");
3785 append_option(packet
, &dhcpv6_universe
, ia_na_option
,
3789 data_string_forget(&iads
, MDL
);
3792 if (rval
== ISC_R_SUCCESS
)
3800 * \brief Add IA_TA information from the lease to the packet
3803 * Walk through the lease and for each IA_TA in the lease
3804 * and for each address in the IA_TA append that information
3805 * onto the packet-so-far. If wanted is 0 include all IA_TAs
3806 * in the lease if wanted is non-zero include only that many
3807 * IA_TAs (this may occur if sommebody restarts a client with
3808 * arugments for a smaller number of TAs than before).
3810 * \param client = the state of the entire client
3811 * \param packet = the packet we are building and where we
3812 * shall append the IA_TAs we create
3813 * \param lease = the current lease
3814 * \param message = the type of the packet
3815 * \param wanted = the number of IA_TAs to include in the packet
3816 * 0 means include all
3817 * \param added = the number of IA_TAs that were added to the packet
3819 * \return ISC_R_SUCCESS - all is well continue, any other return
3820 * indicates an error (most likely memory issues)
3821 * and the packet should be tossed.
3824 dhc6_add_ia_ta(struct client_state
*client
, struct data_string
*packet
,
3825 struct dhc6_lease
*lease
, u_int8_t message
,
3826 int wanted
, int *added
)
3828 struct data_string iads
;
3829 struct data_string addrds
;
3830 struct dhc6_addr
*addr
;
3832 isc_result_t rval
= ISC_R_SUCCESS
;
3837 memset(&iads
, 0, sizeof(iads
));
3838 memset(&addrds
, 0, sizeof(addrds
));
3839 for (ia
= lease
->bindings
, i
= 0;
3840 ia
!= NULL
&& rval
== ISC_R_SUCCESS
&& (wanted
== 0 || i
< wanted
);
3842 if (ia
->ia_type
!= D6O_IA_TA
)
3845 /* Now that we know this is an TA bump the counter */
3848 if (!buffer_allocate(&iads
.buffer
, 4, MDL
)) {
3849 log_error("Unable to allocate memory for IA_TA.");
3850 rval
= ISC_R_NOMEMORY
;
3854 /* Copy the IAID into the packet buffer. */
3855 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
3856 iads
.data
= iads
.buffer
->data
;
3859 log_debug("XMT: X-- IA_TA %s",
3860 print_hex_1(4, iads
.buffer
->data
, 55));
3862 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
3864 * Do not confirm expired addresses, do not request
3865 * expired addresses (but we keep them around for
3868 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
3871 if (addr
->address
.len
!= 16) {
3872 log_error("Illegal IPv6 address length (%d), "
3873 "ignoring. (%s:%d)",
3874 addr
->address
.len
, MDL
);
3878 if (!buffer_allocate(&addrds
.buffer
, 24, MDL
)) {
3879 log_error("Unable to allocate memory for "
3881 rval
= ISC_R_NOMEMORY
;
3885 addrds
.data
= addrds
.buffer
->data
;
3888 /* Copy the address into the packet buffer. */
3889 memcpy(addrds
.buffer
->data
, addr
->address
.iabuf
, 16);
3891 /* Copy in additional information as appropriate */
3893 case DHCPV6_REQUEST
:
3896 t1
= client
->config
->requested_lease
;
3898 putULong(addrds
.buffer
->data
+ 16, t1
);
3899 putULong(addrds
.buffer
->data
+ 20, t2
);
3901 log_debug("XMT: | | X-- IAADDR %s",
3902 piaddr(addr
->address
));
3903 log_debug("XMT: | | | X-- Preferred "
3904 "lifetime +%u", (unsigned)t1
);
3905 log_debug("XMT: | | | X-- Max lifetime +%u",
3910 case DHCPV6_CONFIRM
:
3912 * Set preferred and max life to zero,
3915 memset(addrds
.buffer
->data
+ 16, 0, 8);
3916 log_debug("XMT: | X-- Confirm Address %s",
3917 piaddr(addr
->address
));
3920 case DHCPV6_RELEASE
:
3921 /* Preferred and max life are irrelevant */
3922 memset(addrds
.buffer
->data
+ 16, 0, 8);
3923 log_debug("XMT: | X-- Release Address %s",
3924 piaddr(addr
->address
));
3928 log_fatal("Impossible condition at %s:%d.",
3932 append_option(&iads
, &dhcpv6_universe
, iaaddr_option
,
3934 data_string_forget(&addrds
, MDL
);
3938 * It doesn't make sense to make a request without an
3941 if (ia
->addrs
== NULL
) {
3942 log_debug("!!!: V IA_TA has no IAADDRs - removed.");
3943 rval
= ISC_R_FAILURE
;
3944 } else if (rval
== ISC_R_SUCCESS
) {
3945 log_debug("XMT: V IA_TA appended.");
3946 append_option(packet
, &dhcpv6_universe
, ia_ta_option
,
3950 data_string_forget(&iads
, MDL
);
3953 if (rval
== ISC_R_SUCCESS
)
3961 * \brief Add IA_PD information from the lease to the packet
3964 * Walk through the lease and for each IA_PD in the lease
3965 * and for each address in the IA_PD append that information
3966 * onto the packet-so-far. If wanted is 0 include all IA_PDs
3967 * in the lease if wanted is non-zero include only that many
3968 * IA_PDs (this may occur if sommebody restarts a client with
3969 * arugments for a smaller number of PDs than before).
3971 * \param client = the state of the entire client
3972 * \param packet = the packet we are building and where we
3973 * shall append the IA_PDs we create
3974 * \param lease = the current lease
3975 * \param message = the type of the packet
3976 * \param wanted = the number of IA_PDs to include in the packet
3977 * 0 means include all
3978 * \param added = the number of IA_PDs that were added to the packet
3980 * \return ISC_R_SUCCESS - all is well continue, any other return
3981 * indicates an error (most likely memory issues)
3982 * and the packet should be tossed.
3985 dhc6_add_ia_pd(struct client_state
*client
, struct data_string
*packet
,
3986 struct dhc6_lease
*lease
, u_int8_t message
,
3987 int wanted
, int *added
)
3989 struct data_string iads
;
3990 struct data_string prefds
;
3991 struct dhc6_addr
*pref
;
3993 isc_result_t rval
= ISC_R_SUCCESS
;
3998 memset(&iads
, 0, sizeof(iads
));
3999 memset(&prefds
, 0, sizeof(prefds
));
4000 for (ia
= lease
->bindings
, i
= 0;
4001 ia
!= NULL
&& rval
== ISC_R_SUCCESS
&& (wanted
== 0 || i
< wanted
);
4003 if (ia
->ia_type
!= D6O_IA_PD
)
4006 /* Now that we know this is an PD bump the counter */
4009 if (!buffer_allocate(&iads
.buffer
, 12, MDL
)) {
4010 log_error("Unable to allocate memory for IA_PD.");
4011 rval
= ISC_R_NOMEMORY
;
4015 /* Copy the IAID into the packet buffer. */
4016 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
4017 iads
.data
= iads
.buffer
->data
;
4021 case DHCPV6_REQUEST
:
4025 t1
= client
->config
->requested_lease
/ 2;
4027 #if MAX_TIME > 0xffffffff
4028 if (t1
> 0xffffffff)
4030 if (t2
> 0xffffffff)
4033 putULong(iads
.buffer
->data
+ 4, t1
);
4034 putULong(iads
.buffer
->data
+ 8, t2
);
4036 log_debug("XMT: X-- IA_PD %s",
4037 print_hex_1(4, iads
.data
, 59));
4038 log_debug("XMT: | X-- Requested renew +%u",
4040 log_debug("XMT: | X-- Requested rebind +%u",
4044 case DHCPV6_RELEASE
:
4045 /* Set t1 and t2 to zero; server will ignore them */
4046 memset(iads
.buffer
->data
+ 4, 0, 8);
4047 log_debug("XMT: X-- IA_PD %s",
4048 print_hex_1(4, iads
.buffer
->data
, 55));
4053 log_fatal("Impossible condition at %s:%d.", MDL
);
4056 for (pref
= ia
->addrs
; pref
!= NULL
; pref
= pref
->next
) {
4058 * Do not confirm expired prefixes, do not request
4059 * expired prefixes (but we keep them around for
4062 if (pref
->flags
& DHC6_ADDR_EXPIRED
)
4065 if (pref
->address
.len
!= 16) {
4066 log_error("Illegal IPv6 prefix "
4067 "ignoring. (%s:%d)",
4072 if (pref
->plen
== 0) {
4073 log_info("Null IPv6 prefix, "
4074 "ignoring. (%s:%d)",
4078 if (!buffer_allocate(&prefds
.buffer
, 25, MDL
)) {
4079 log_error("Unable to allocate memory for "
4081 rval
= ISC_R_NOMEMORY
;
4085 prefds
.data
= prefds
.buffer
->data
;
4088 /* Copy the prefix into the packet buffer. */
4089 putUChar(prefds
.buffer
->data
+ 8, pref
->plen
);
4090 memcpy(prefds
.buffer
->data
+ 9,
4091 pref
->address
.iabuf
,
4094 /* Copy in additional information as appropriate */
4096 case DHCPV6_REQUEST
:
4099 t1
= client
->config
->requested_lease
;
4101 putULong(prefds
.buffer
->data
, t1
);
4102 putULong(prefds
.buffer
->data
+ 4, t2
);
4104 log_debug("XMT: | | X-- IAPREFIX %s/%u",
4105 piaddr(pref
->address
),
4106 (unsigned) pref
->plen
);
4107 log_debug("XMT: | | | X-- Preferred "
4108 "lifetime +%u", (unsigned)t1
);
4109 log_debug("XMT: | | | X-- Max lifetime +%u",
4114 case DHCPV6_RELEASE
:
4115 /* Preferred and max life are irrelevant */
4116 memset(prefds
.buffer
->data
, 0, 8);
4117 log_debug("XMT: | X-- Release Prefix %s/%u",
4118 piaddr(pref
->address
),
4119 (unsigned) pref
->plen
);
4123 log_fatal("Impossible condition at %s:%d.",
4127 append_option(&iads
, &dhcpv6_universe
,
4128 iaprefix_option
, &prefds
);
4129 data_string_forget(&prefds
, MDL
);
4133 * It doesn't make sense to make a request without an
4136 if (ia
->addrs
== NULL
) {
4137 log_debug("!!!: V IA_PD has no IAPREFIXs - removed.");
4138 rval
= ISC_R_FAILURE
;
4139 } else if (rval
== ISC_R_SUCCESS
) {
4140 log_debug("XMT: V IA_PD appended.");
4141 append_option(packet
, &dhcpv6_universe
,
4142 ia_pd_option
, &iads
);
4145 data_string_forget(&iads
, MDL
);
4148 if (rval
== ISC_R_SUCCESS
)
4154 /* stopping_finished() checks if there is a remaining work to do.
4156 static isc_boolean_t
4157 stopping_finished(void)
4159 struct interface_info
*ip
;
4160 struct client_state
*client
;
4162 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4163 for (client
= ip
-> client
; client
; client
= client
-> next
) {
4164 if (client
->state
!= S_STOPPED
)
4166 if (client
->active_lease
!= NULL
)
4173 /* reply_handler() accepts a Reply while we're attempting Select or Renew or
4174 * Rebind. Basically any Reply packet.
4177 reply_handler(struct packet
*packet
, struct client_state
*client
)
4179 struct dhc6_lease
*lease
;
4180 isc_result_t check_status
;
4182 if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
4185 /* RFC3315 section 15.10 validation (same as 15.3 since we
4186 * always include a client id).
4188 if (!valid_reply(packet
, client
)) {
4189 log_error("Invalid Reply - rejecting.");
4193 lease
= dhc6_leaseify(packet
, client
);
4195 /* Out of memory or corrupt packet condition...hopefully a temporary
4196 * problem. Returning now makes us try to retransmit later.
4201 check_status
= dhc6_check_reply(client
, lease
);
4202 if (check_status
!= ISC_R_SUCCESS
) {
4203 dhc6_lease_destroy(&lease
, MDL
);
4205 /* If no action was taken, but there is an error, then
4206 * we wait for a retransmission.
4208 if (check_status
!= ISC_R_CANCELED
)
4212 /* We're done retransmitting at this point. */
4213 cancel_timeout(do_confirm6
, client
);
4214 cancel_timeout(do_select6
, client
);
4215 cancel_timeout(do_refresh6
, client
);
4216 cancel_timeout(do_release6
, client
);
4218 /* If this is in response to a Release/Decline, clean up and return. */
4219 if (client
->state
== S_STOPPED
) {
4220 if (client
->active_lease
== NULL
)
4223 dhc6_lease_destroy(&client
->active_lease
, MDL
);
4224 client
->active_lease
= NULL
;
4225 /* We should never wait for nothing!? */
4226 if (stopping_finished())
4231 /* Action was taken, so now that we've torn down our scheduled
4232 * retransmissions, return.
4234 if (check_status
== ISC_R_CANCELED
)
4237 if (client
->selected_lease
!= NULL
) {
4238 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
4239 client
->selected_lease
= NULL
;
4242 /* If this is in response to a confirm, we use the lease we've
4243 * already got, not the reply we were sent.
4245 if (client
->state
== S_REBOOTING
) {
4246 if (client
->active_lease
== NULL
)
4247 log_fatal("Impossible condition at %s:%d.", MDL
);
4249 dhc6_lease_destroy(&lease
, MDL
);
4250 start_bound(client
);
4254 /* Merge any bindings in the active lease (if there is one) into
4255 * the new active lease.
4257 dhc6_merge_lease(client
->active_lease
, lease
);
4259 /* Cleanup if a previous attempt to go bound failed. */
4260 if (client
->old_lease
!= NULL
) {
4261 dhc6_lease_destroy(&client
->old_lease
, MDL
);
4262 client
->old_lease
= NULL
;
4265 /* Make this lease active and BIND to it. */
4266 if (client
->active_lease
!= NULL
)
4267 client
->old_lease
= client
->active_lease
;
4268 client
->active_lease
= lease
;
4270 /* We're done with the ADVERTISEd leases, if any. */
4271 while(client
->advertised_leases
!= NULL
) {
4272 lease
= client
->advertised_leases
;
4273 client
->advertised_leases
= lease
->next
;
4275 dhc6_lease_destroy(&lease
, MDL
);
4278 start_bound(client
);
4281 /* DHCPv6 packets are a little sillier than they needed to be - the root
4282 * packet contains options, then IA's which contain options, then within
4283 * that IAADDR's which contain options.
4285 * To sort this out at dhclient-script time (which fetches config parameters
4286 * in environment variables), start_bound() iterates over each IAADDR, and
4287 * calls this function to marshall an environment variable set that includes
4288 * the most-specific option values related to that IAADDR in particular.
4290 * To achieve this, we load environment variables for the root options space,
4291 * then the IA, then the IAADDR. Any duplicate option names will be
4292 * over-written by the later versions.
4295 dhc6_marshall_values(const char *prefix
, struct client_state
*client
,
4296 struct dhc6_lease
*lease
, struct dhc6_ia
*ia
,
4297 struct dhc6_addr
*addr
)
4299 /* Option cache contents, in descending order of
4302 if ((lease
!= NULL
) && (lease
->options
!= NULL
))
4303 script_write_params6(client
, prefix
, lease
->options
);
4304 if ((ia
!= NULL
) && (ia
->options
!= NULL
))
4305 script_write_params6(client
, prefix
, ia
->options
);
4306 if ((addr
!= NULL
) && (addr
->options
!= NULL
))
4307 script_write_params6(client
, prefix
, addr
->options
);
4311 if ((ia
!= NULL
) && (ia
->ia_type
== D6O_IA_PD
)) {
4312 client_envadd(client
, prefix
,
4313 "ip6_prefix", "%s/%u",
4314 piaddr(addr
->address
),
4315 (unsigned) addr
->plen
);
4317 client_envadd(client
, prefix
, "ip6_prefixlen",
4318 "%d", DHCLIENT_DEFAULT_PREFIX_LEN
);
4319 client_envadd(client
, prefix
, "ip6_address",
4320 "%s", piaddr(addr
->address
));
4322 if ((ia
!= NULL
) && (ia
->ia_type
== D6O_IA_TA
)) {
4323 client_envadd(client
, prefix
,
4324 "ip6_type", "temporary");
4326 client_envadd(client
, prefix
, "life_starts", "%d",
4327 (int)(addr
->starts
));
4328 client_envadd(client
, prefix
, "preferred_life", "%u",
4329 addr
->preferred_life
);
4330 client_envadd(client
, prefix
, "max_life", "%u",
4336 client_envadd(client
, prefix
, "iaid", "%s",
4337 print_hex_1(4, ia
->iaid
, 12));
4338 client_envadd(client
, prefix
, "starts", "%d",
4340 client_envadd(client
, prefix
, "renew", "%u", ia
->renew
);
4341 client_envadd(client
, prefix
, "rebind", "%u", ia
->rebind
);
4345 /* Look at where the client's active lease is sitting. If it's looking to
4346 * time out on renew, rebind, depref, or expiration, do those things.
4349 dhc6_check_times(struct client_state
*client
)
4351 struct dhc6_lease
*lease
;
4353 struct dhc6_addr
*addr
;
4354 TIME renew
=MAX_TIME
, rebind
=MAX_TIME
, depref
=MAX_TIME
,
4355 lo_expire
=MAX_TIME
, hi_expire
=0, max_ia_starts
= 0, tmp
;
4356 int has_addrs
= ISC_FALSE
;
4359 lease
= client
->active_lease
;
4361 /* Bit spammy. We should probably keep record of scheduled
4364 cancel_timeout(start_renew6
, client
);
4365 cancel_timeout(start_rebind6
, client
);
4366 cancel_timeout(do_depref
, client
);
4367 cancel_timeout(do_expire
, client
);
4369 for(ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
4370 TIME this_ia_lo_expire
, this_ia_hi_expire
, use_expire
;
4372 this_ia_lo_expire
= MAX_TIME
;
4373 this_ia_hi_expire
= 0;
4375 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
4376 if(!(addr
->flags
& DHC6_ADDR_DEPREFFED
)) {
4377 if (addr
->preferred_life
== 0xffffffff)
4380 tmp
= addr
->starts
+
4381 addr
->preferred_life
;
4387 if (!(addr
->flags
& DHC6_ADDR_EXPIRED
)) {
4388 /* Find EPOCH-relative expiration. */
4389 if (addr
->max_life
== 0xffffffff)
4392 tmp
= addr
->starts
+ addr
->max_life
;
4394 /* Make the times ia->starts relative. */
4397 if (tmp
> this_ia_hi_expire
)
4398 this_ia_hi_expire
= tmp
;
4399 if (tmp
< this_ia_lo_expire
)
4400 this_ia_lo_expire
= tmp
;
4402 has_addrs
= ISC_TRUE
;
4406 /* These times are ia->starts relative. */
4407 if (this_ia_lo_expire
<= (this_ia_hi_expire
/ 2))
4408 use_expire
= this_ia_hi_expire
;
4410 use_expire
= this_ia_lo_expire
;
4413 * If the auto-selected expiration time is "infinite", or
4414 * zero, assert a reasonable default.
4416 if ((use_expire
== MAX_TIME
) || (use_expire
<= 1))
4417 use_expire
= client
->config
->requested_lease
/ 2;
4421 /* Don't renew/rebind temporary addresses. */
4422 /* For NA and PD we find the most recent IA and the smallest
4423 * values for the renew and rebind then base the timer on
4424 * the sum of the them.
4425 * Normally all the IAs will have the same time as they
4426 * are requested and served as a group but in some cases the
4427 * client isn't asking for all of the IAs (for example
4428 * restarted with a different set of arguments) or the server
4429 * isn't updating the client on all of them (probably a
4432 if (ia
->ia_type
!= D6O_IA_TA
) {
4433 if (ia
->starts
> max_ia_starts
)
4434 max_ia_starts
= ia
->starts
;
4436 if (ia
->renew
== 0) {
4438 } else if (ia
->renew
== 0xffffffff)
4446 if (ia
->rebind
== 0) {
4447 /* Set rebind to 3/4 expiration interval. */
4448 tmp
= use_expire
+ (use_expire
/ 2);
4449 } else if (ia
->rebind
== 0xffffffff)
4459 * Return expiration ranges to EPOCH relative for event
4460 * scheduling (add_timeout()).
4462 this_ia_hi_expire
+= ia
->starts
;
4463 this_ia_lo_expire
+= ia
->starts
;
4465 if (this_ia_hi_expire
> hi_expire
)
4466 hi_expire
= this_ia_hi_expire
;
4467 if (this_ia_lo_expire
< lo_expire
)
4468 lo_expire
= this_ia_lo_expire
;
4471 /* If there are no addresses, give up, go to INIT.
4472 * Note that if an address is unexpired with a date in the past,
4473 * we're scheduling an expiration event to ocurr in the past. We
4474 * could probably optimize this to expire now (but then there's
4477 * In the future, we may decide that we're done here, or to
4478 * schedule a future request (using 4-pkt info-request model).
4480 if (has_addrs
== ISC_FALSE
) {
4481 dhc6_lease_destroy(&client
->active_lease
, MDL
);
4482 client
->active_lease
= NULL
;
4484 /* Go back to the beginning. */
4485 start_init6(client
);
4489 /* Second part of calculating the renew and rebind times.
4490 * We have the start time and the desired periods for renew
4491 * and rebind, just add them to get the desired end time.
4493 if (renew
!= MAX_TIME
)
4494 renew
+= max_ia_starts
;
4495 if (rebind
!= MAX_TIME
)
4496 rebind
+= max_ia_starts
;
4498 switch(client
->state
) {
4500 /* We'd like to hit renewing, but if rebinding has already
4501 * passed (time warp), head straight there.
4503 if ((rebind
> cur_time
) && (renew
< rebind
)) {
4504 log_debug("PRC: Renewal event scheduled in %d seconds, "
4505 "to run for %u seconds.",
4506 (int)(renew
- cur_time
),
4507 (unsigned)(rebind
- renew
));
4508 client
->next_MRD
= rebind
;
4511 add_timeout(&tv
, start_renew6
, client
, NULL
, NULL
);
4517 /* While actively renewing, MRD is bounded by the time
4518 * we stop renewing and start rebinding. This helps us
4519 * process the state change on time.
4521 client
->MRD
= rebind
- cur_time
;
4522 if (rebind
!= MAX_TIME
) {
4523 log_debug("PRC: Rebind event scheduled in %d seconds, "
4524 "to run for %d seconds.",
4525 (int)(rebind
- cur_time
),
4526 (int)(hi_expire
- rebind
));
4527 client
->next_MRD
= hi_expire
;
4530 add_timeout(&tv
, start_rebind6
, client
, NULL
, NULL
);
4535 /* For now, we rebind up until the last lease expires. In
4536 * the future, we might want to start SOLICITing when we've
4537 * depreffed an address.
4539 client
->MRD
= hi_expire
- cur_time
;
4543 log_fatal("Impossible condition at %s:%d.", MDL
);
4546 /* Separately, set a time at which we will depref and expire
4547 * leases. This might happen with multiple addresses while we
4548 * keep trying to refresh.
4550 if (depref
!= MAX_TIME
) {
4551 log_debug("PRC: Depreference scheduled in %d seconds.",
4552 (int)(depref
- cur_time
));
4555 add_timeout(&tv
, do_depref
, client
, NULL
, NULL
);
4557 if (lo_expire
!= MAX_TIME
) {
4558 log_debug("PRC: Expiration scheduled in %d seconds.",
4559 (int)(lo_expire
- cur_time
));
4560 tv
.tv_sec
= lo_expire
;
4562 add_timeout(&tv
, do_expire
, client
, NULL
, NULL
);
4566 /* In a given IA chain, find the IA with the same type and 'iaid'. */
4567 static struct dhc6_ia
*
4568 find_ia(struct dhc6_ia
*head
, u_int16_t type
, const char *id
)
4572 for (ia
= head
; ia
!= NULL
; ia
= ia
->next
) {
4573 if (ia
->ia_type
!= type
)
4575 if (memcmp(ia
->iaid
, id
, 4) == 0)
4582 /* In a given address chain, find a matching address. */
4583 static struct dhc6_addr
*
4584 find_addr(struct dhc6_addr
*head
, struct iaddr
*address
)
4586 struct dhc6_addr
*addr
;
4588 for (addr
= head
; addr
!= NULL
; addr
= addr
->next
) {
4589 if ((addr
->address
.len
== address
->len
) &&
4590 (memcmp(addr
->address
.iabuf
, address
->iabuf
,
4591 address
->len
) == 0))
4598 /* In a given prefix chain, find a matching prefix. */
4599 static struct dhc6_addr
*
4600 find_pref(struct dhc6_addr
*head
, struct iaddr
*prefix
, u_int8_t plen
)
4602 struct dhc6_addr
*pref
;
4604 for (pref
= head
; pref
!= NULL
; pref
= pref
->next
) {
4605 if ((pref
->address
.len
== prefix
->len
) &&
4606 (pref
->plen
== plen
) &&
4607 (memcmp(pref
->address
.iabuf
, prefix
->iabuf
,
4617 * \brief Merge the bindings from the source lease into the destination
4618 * lease structure, where they are missing.
4620 * This is used to merge any extra information we have in the current
4621 * (older, src) lease into the lease we have just received. For example
4622 * the src lease might include a binding for an NA that is still usable
4623 * but that we didn't request or that the server is no longer serving.
4624 * We want to keep that information until we toss the binding (expire,
4625 * release) so we move it to the new lease.
4627 * We have to copy the stateful objects rather than move them over,
4628 * because later code needs to be able to compare new versus old if
4629 * they contain any bindings.
4631 * \param src The older lease to copy the objects from
4632 * \param dst The newer lease to copy the objects to
4635 dhc6_merge_lease(struct dhc6_lease
*src
, struct dhc6_lease
*dst
)
4637 struct dhc6_ia
*sia
, *dia
, *tia
, **eia
;
4638 struct dhc6_addr
*saddr
, *daddr
, *taddr
;
4641 if ((dst
== NULL
) || (src
== NULL
))
4644 for (sia
= src
->bindings
; sia
!= NULL
; sia
= sia
->next
) {
4645 dia
= find_ia(dst
->bindings
, sia
->ia_type
, (char *)sia
->iaid
);
4648 tia
= dhc6_dup_ia(sia
, MDL
);
4651 log_fatal("Out of memory merging lease - "
4652 "Unable to continue without losing "
4653 "state! (%s:%d)", MDL
);
4655 /* Put any bindings that aren't in the new lease at the
4656 * end of the list. If the user or server reduces the
4657 * number of IAs the ones in use will be at the front
4658 * and will be used when building the next requests
4659 * We could be more efficient by finding the end
4660 * of the list once but we don't expect to do this
4663 for (eia
= &dst
->bindings
;
4665 eia
= &(*eia
)->next
) {
4666 ; /* no work just find the end */
4671 for (saddr
= sia
->addrs
; saddr
!= NULL
;
4672 saddr
= saddr
->next
) {
4673 if (sia
->ia_type
!= D6O_IA_PD
)
4674 daddr
= find_addr(dia
->addrs
,
4677 daddr
= find_pref(dia
->addrs
,
4681 if (daddr
== NULL
) {
4682 taddr
= dhc6_dup_addr(saddr
, MDL
);
4685 log_fatal("Out of memory "
4687 "Unable to continue "
4692 /* XXX: consider sorting? */
4693 taddr
->next
= dia
->addrs
;
4701 /* If we made changes, reset the score to 0 so it is recalculated. */
4706 /* We've either finished selecting or succeeded in Renew or Rebinding our
4707 * lease. In all cases we got a Reply. Give dhclient-script a tickle
4708 * to inform it about the new values, and then lay in wait for the next
4712 start_bound(struct client_state
*client
)
4714 struct dhc6_ia
*ia
, *oldia
;
4715 struct dhc6_addr
*addr
, *oldaddr
;
4716 struct dhc6_lease
*lease
, *old
;
4718 #if defined (NSUPDATE)
4719 TIME dns_update_offset
= 1;
4722 lease
= client
->active_lease
;
4723 if (lease
== NULL
) {
4724 log_error("Cannot enter bound state unless an active lease "
4728 lease
->released
= ISC_FALSE
;
4729 old
= client
->old_lease
;
4731 client
->v6_handler
= bound_handler
;
4733 switch (client
->state
) {
4735 case S_REBOOTING
: /* Pretend we got bound. */
4748 log_fatal("Impossible condition at %s:%d.", MDL
);
4749 /* Silence compiler warnings. */
4753 log_debug("PRC: Bound to lease %s.",
4754 print_hex_1(client
->active_lease
->server_id
.len
,
4755 client
->active_lease
->server_id
.data
, 55));
4756 client
->state
= S_BOUND
;
4758 write_client6_lease(client
, lease
, 0, 1);
4761 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
4763 oldia
= find_ia(old
->bindings
,
4769 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
4770 /* Don't try to use the address if it's already expired */
4771 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
4774 if (oldia
!= NULL
) {
4775 if (ia
->ia_type
!= D6O_IA_PD
)
4776 oldaddr
= find_addr(oldia
->addrs
,
4779 oldaddr
= find_pref(oldia
->addrs
,
4785 #if defined (NSUPDATE)
4786 if ((oldaddr
== NULL
) && (ia
->ia_type
== D6O_IA_NA
))
4787 dhclient_schedule_updates(client
,
4789 dns_update_offset
++);
4792 /* Shell out to setup the new binding. */
4793 script_init(client
, reason
, NULL
);
4796 dhc6_marshall_values("old_", client
, old
,
4798 dhc6_marshall_values("new_", client
, lease
, ia
, addr
);
4799 script_write_requested6(client
);
4804 /* XXX: maybe we should loop on the old values instead? */
4805 if (ia
->addrs
== NULL
) {
4806 script_init(client
, reason
, NULL
);
4809 dhc6_marshall_values("old_", client
, old
,
4812 oldia
->addrs
: NULL
);
4814 dhc6_marshall_values("new_", client
, lease
, ia
,
4816 script_write_requested6(client
);
4822 /* XXX: maybe we should loop on the old values instead? */
4823 if (lease
->bindings
== NULL
) {
4824 script_init(client
, reason
, NULL
);
4827 dhc6_marshall_values("old_", client
, old
,
4829 (old
->bindings
!= NULL
) ?
4830 old
->bindings
->addrs
: NULL
);
4832 dhc6_marshall_values("new_", client
, lease
, NULL
, NULL
);
4833 script_write_requested6(client
);
4839 if (dhcpv4_over_dhcpv6
)
4845 if (client
->old_lease
!= NULL
) {
4846 dhc6_lease_destroy(&client
->old_lease
, MDL
);
4847 client
->old_lease
= NULL
;
4850 /* Schedule events. */
4851 dhc6_check_times(client
);
4854 /* While bound, ignore packets. In the future we'll want to answer
4855 * Reconfigure-Request messages and the like.
4858 bound_handler(struct packet
*packet
, struct client_state
*client
)
4860 log_debug("RCV: Input packets are ignored once bound.");
4863 /* start_renew6() gets us all ready to go to start transmitting Renew packets.
4864 * Note that client->next_MRD must be set before entering this function -
4865 * it must be set to the time at which the client should start Rebinding.
4868 start_renew6(void *input
)
4870 struct client_state
*client
;
4872 client
= (struct client_state
*)input
;
4874 log_info("PRC: Renewing lease on %s.",
4875 client
->name
? client
->name
: client
->interface
->name
);
4876 client
->state
= S_RENEWING
;
4878 client
->v6_handler
= reply_handler
;
4880 /* Times per RFC3315 section 18.1.3. */
4881 client
->IRT
= REN_TIMEOUT
* 100;
4882 client
->MRT
= REN_MAX_RT
* 100;
4884 /* MRD is special in renew - we need to set it by checking timer
4887 client
->MRD
= client
->next_MRD
- cur_time
;
4889 dhc6_retrans_init(client
);
4891 client
->refresh_type
= DHCPV6_RENEW
;
4892 do_refresh6(client
);
4895 /* do_refresh6() transmits one DHCPv6 packet, be it a Renew or Rebind, and
4896 * gives the retransmission state a bump for the next time. Note that
4897 * client->refresh_type must be set before entering this function.
4900 do_refresh6(void *input
)
4902 struct option_cache
*oc
;
4903 struct sockaddr_in6 unicast
, *dest_addr
= &DHCPv6DestAddr
;
4904 struct data_string ds
;
4905 struct client_state
*client
;
4906 struct dhc6_lease
*lease
;
4907 struct timeval elapsed
, tv
;
4908 int send_ret
, added
;
4910 client
= (struct client_state
*)input
;
4911 memset(&ds
, 0, sizeof(ds
));
4913 lease
= client
->active_lease
;
4914 if (lease
== NULL
) {
4915 log_error("Cannot renew without an active binding.");
4919 /* Ensure we're emitting a valid message type. */
4920 switch (client
->refresh_type
) {
4926 log_fatal("Internal inconsistency (%d) at %s:%d.",
4927 client
->refresh_type
, MDL
);
4931 * Start_time starts at the first transmission.
4933 if (client
->txcount
== 0) {
4934 client
->start_time
.tv_sec
= cur_tv
.tv_sec
;
4935 client
->start_time
.tv_usec
= cur_tv
.tv_usec
;
4938 /* elapsed = cur - start */
4939 elapsed
.tv_sec
= cur_tv
.tv_sec
- client
->start_time
.tv_sec
;
4940 elapsed
.tv_usec
= cur_tv
.tv_usec
- client
->start_time
.tv_usec
;
4941 if (elapsed
.tv_usec
< 0) {
4942 elapsed
.tv_sec
-= 1;
4943 elapsed
.tv_usec
+= 1000000;
4945 if (((client
->MRC
!= 0) && (client
->txcount
> client
->MRC
)) ||
4946 ((client
->MRD
!= 0) && (elapsed
.tv_sec
>= client
->MRD
))) {
4947 /* We're done. Move on to the next phase, if any. */
4948 dhc6_check_times(client
);
4953 * Check whether the server has sent a unicast option; if so, we can
4954 * use the address it specified for RENEWs.
4956 oc
= lookup_option(&dhcpv6_universe
, lease
->options
, D6O_UNICAST
);
4957 if (oc
&& evaluate_option_cache(&ds
, NULL
, NULL
, NULL
,
4958 lease
->options
, NULL
, &global_scope
,
4961 log_error("Invalid unicast option length %d.", ds
.len
);
4963 memset(&unicast
, 0, sizeof(DHCPv6DestAddr
));
4964 unicast
.sin6_family
= AF_INET6
;
4965 unicast
.sin6_port
= remote_port
;
4966 memcpy(&unicast
.sin6_addr
, ds
.data
, 16);
4967 if (client
->refresh_type
== DHCPV6_RENEW
) {
4968 dest_addr
= &unicast
;
4972 data_string_forget(&ds
, MDL
);
4975 /* Commence forming a renew packet. */
4976 memset(&ds
, 0, sizeof(ds
));
4977 if (!buffer_allocate(&ds
.buffer
, 4, MDL
)) {
4978 log_error("Unable to allocate memory for packet.");
4981 ds
.data
= ds
.buffer
->data
;
4984 ds
.buffer
->data
[0] = client
->refresh_type
;
4985 memcpy(ds
.buffer
->data
+ 1, client
->dhcpv6_transaction_id
, 3);
4987 /* Form an elapsed option. */
4988 /* Maximum value is 65535 1/100s coded as 0xffff. */
4989 if ((elapsed
.tv_sec
< 0) || (elapsed
.tv_sec
> 655) ||
4990 ((elapsed
.tv_sec
== 655) && (elapsed
.tv_usec
> 350000))) {
4991 client
->elapsed
= 0xffff;
4993 client
->elapsed
= elapsed
.tv_sec
* 100;
4994 client
->elapsed
+= elapsed
.tv_usec
/ 10000;
4997 if (client
->elapsed
== 0)
4998 log_debug("XMT: Forming %s, 0 ms elapsed.",
4999 dhcpv6_type_names
[client
->refresh_type
]);
5001 log_debug("XMT: Forming %s, %u0 ms elapsed.",
5002 dhcpv6_type_names
[client
->refresh_type
],
5003 (unsigned)client
->elapsed
);
5005 client
->elapsed
= htons(client
->elapsed
);
5007 make_client6_options(client
, &client
->sent_options
, lease
,
5008 client
->refresh_type
);
5010 /* Put in any options from the sent cache. */
5011 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
, NULL
,
5012 client
->sent_options
, &global_scope
,
5015 /* Now append any IA's, and within them any IAADDR/IAPREFIXs.
5016 * For each type of IA (na, ta, pd) we start with the ones for
5017 * which we already have addresses (dhc6_add_ia_xx) and then
5018 * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
5021 ((dhc6_add_ia_na(client
, &ds
, lease
, client
->refresh_type
,
5022 wanted_ia_na
, &added
) != ISC_R_SUCCESS
) ||
5023 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_na
- added
,
5024 D6O_IA_NA
) != ISC_R_SUCCESS
))) {
5025 data_string_forget(&ds
, MDL
);
5029 ((dhc6_add_ia_pd(client
, &ds
, lease
, client
->refresh_type
,
5030 wanted_ia_pd
, &added
) != ISC_R_SUCCESS
) ||
5031 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_pd
- added
,
5032 D6O_IA_PD
) != ISC_R_SUCCESS
))) {
5033 data_string_forget(&ds
, MDL
);
5037 log_info("XMT: %s on %s, interval %ld0ms.",
5038 dhcpv6_type_names
[client
->refresh_type
],
5039 client
->name
? client
->name
: client
->interface
->name
,
5040 (long int)client
->RT
);
5042 send_ret
= send_packet6(client
->interface
, ds
.data
, ds
.len
, dest_addr
);
5044 if (send_ret
!= ds
.len
) {
5045 log_error("dhc6: send_packet6() sent %d of %d bytes",
5049 data_string_forget(&ds
, MDL
);
5052 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
5053 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
5054 if (tv
.tv_usec
>= 1000000) {
5056 tv
.tv_usec
-= 1000000;
5058 add_timeout(&tv
, do_refresh6
, client
, NULL
, NULL
);
5060 dhc6_retrans_advance(client
);
5063 /* start_rebind6() gets us all set up to go and rebind a lease. Note that
5064 * client->next_MRD must be set before entering this function. In this case,
5065 * MRD must be set to the maximum time any address in the packet will
5069 start_rebind6(void *input
)
5071 struct client_state
*client
;
5073 client
= (struct client_state
*)input
;
5075 log_info("PRC: Rebinding lease on %s.",
5076 client
->name
? client
->name
: client
->interface
->name
);
5077 client
->state
= S_REBINDING
;
5079 client
->v6_handler
= reply_handler
;
5081 /* Times per RFC3315 section 18.1.4. */
5082 client
->IRT
= REB_TIMEOUT
* 100;
5083 client
->MRT
= REB_MAX_RT
* 100;
5085 /* MRD is special in rebind - it's determined by the timer
5088 client
->MRD
= client
->next_MRD
- cur_time
;
5090 dhc6_retrans_init(client
);
5092 client
->refresh_type
= DHCPV6_REBIND
;
5093 do_refresh6(client
);
5096 /* do_depref() runs through a given lease's addresses, for each that has
5097 * not yet been depreffed, shells out to the dhclient-script to inform it
5098 * of the status change. The dhclient-script should then do...something...
5099 * to encourage applications to move off the address and onto one of the
5100 * remaining 'preferred' addresses.
5103 do_depref(void *input
)
5105 struct client_state
*client
;
5106 struct dhc6_lease
*lease
;
5108 struct dhc6_addr
*addr
;
5110 client
= (struct client_state
*)input
;
5112 lease
= client
->active_lease
;
5116 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
5117 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
5118 if (addr
->flags
& DHC6_ADDR_DEPREFFED
)
5121 if (addr
->starts
+ addr
->preferred_life
<= cur_time
) {
5122 script_init(client
, "DEPREF6", NULL
);
5123 dhc6_marshall_values("cur_", client
, lease
,
5125 script_write_requested6(client
);
5128 addr
->flags
|= DHC6_ADDR_DEPREFFED
;
5130 if (ia
->ia_type
!= D6O_IA_PD
)
5131 log_info("PRC: Address %s depreferred.",
5132 piaddr(addr
->address
));
5134 log_info("PRC: Prefix %s/%u depreferred.",
5135 piaddr(addr
->address
),
5136 (unsigned) addr
->plen
);
5138 #if defined (NSUPDATE)
5139 /* Remove DDNS bindings at depref time. */
5140 if ((ia
->ia_type
== D6O_IA_NA
) &&
5141 client
->config
->do_forward_update
)
5142 client_dns_remove(client
,
5149 dhc6_check_times(client
);
5152 /* do_expire() searches through all the addresses on a given lease, and
5153 * expires/removes any addresses that are no longer valid.
5156 do_expire(void *input
)
5158 struct client_state
*client
;
5159 struct dhc6_lease
*lease
;
5160 struct dhc6_ia
*ia
, **tia
;
5161 struct dhc6_addr
*addr
;
5162 int has_addrs
= ISC_FALSE
;
5163 int ia_has_addrs
= ISC_FALSE
;
5165 client
= (struct client_state
*)input
;
5167 lease
= client
->active_lease
;
5171 for (ia
= lease
->bindings
, tia
= &lease
->bindings
; ia
!= NULL
; ) {
5172 ia_has_addrs
= ISC_FALSE
;
5173 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
5174 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
5177 if (addr
->starts
+ addr
->max_life
<= cur_time
) {
5178 script_init(client
, "EXPIRE6", NULL
);
5179 dhc6_marshall_values("old_", client
, lease
,
5181 script_write_requested6(client
);
5184 addr
->flags
|= DHC6_ADDR_EXPIRED
;
5186 if (ia
->ia_type
!= D6O_IA_PD
)
5187 log_info("PRC: Address %s expired.",
5188 piaddr(addr
->address
));
5190 log_info("PRC: Prefix %s/%u expired.",
5191 piaddr(addr
->address
),
5192 (unsigned) addr
->plen
);
5194 #if defined (NSUPDATE)
5195 /* We remove DNS records at depref time, but
5196 * it is possible that we might get here
5197 * without depreffing.
5199 if ((ia
->ia_type
== D6O_IA_NA
) &&
5200 client
->config
->do_forward_update
&&
5201 !(addr
->flags
& DHC6_ADDR_DEPREFFED
))
5202 client_dns_remove(client
,
5209 ia_has_addrs
= ISC_TRUE
;
5210 has_addrs
= ISC_TRUE
;
5213 /* Update to the next ia and git rid of this ia
5214 * if it doesn't have any leases.
5216 if (ia_has_addrs
== ISC_TRUE
) {
5217 /* leases, just advance the list pointer */
5218 tia
= &(*tia
)->next
;
5220 /* no leases, update the list pointer
5224 dhc6_ia_destroy(&ia
, MDL
);
5226 /* lastly update the ia pointer to our new ia */
5230 /* Clean up empty leases. */
5231 if (has_addrs
== ISC_FALSE
) {
5232 log_info("PRC: Bound lease is devoid of active addresses."
5233 " Re-initializing.");
5235 dhc6_lease_destroy(&lease
, MDL
);
5236 client
->active_lease
= NULL
;
5238 start_init6(client
);
5242 /* Schedule the next run through. */
5243 dhc6_check_times(client
);
5247 * Run client script to unconfigure interface.
5248 * Called with reason STOP6 when dhclient -x is run, or with reason
5249 * RELEASE6 when server has replied to a Release message.
5250 * Stateless is a special case.
5253 unconfigure6(struct client_state
*client
, const char *reason
)
5256 struct dhc6_addr
*addr
;
5259 script_init(client
, reason
, NULL
);
5260 if (client
->active_lease
!= NULL
)
5261 script_write_params6(client
, "old_",
5262 client
->active_lease
->options
);
5263 script_write_requested6(client
);
5268 if (client
->active_lease
== NULL
)
5271 for (ia
= client
->active_lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
5272 if (ia
->ia_type
== D6O_IA_TA
)
5275 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
5276 script_init(client
, reason
, NULL
);
5277 dhc6_marshall_values("old_", client
,
5278 client
->active_lease
, ia
, addr
);
5279 script_write_requested6(client
);
5282 #if defined (NSUPDATE)
5283 if ((ia
->ia_type
== D6O_IA_NA
) &&
5284 client
->config
->do_forward_update
)
5285 client_dns_remove(client
, &addr
->address
);
5292 refresh_info_request6(void *input
)
5294 struct client_state
*client
;
5296 client
= (struct client_state
*)input
;
5297 start_info_request6(client
);
5300 /* Timeout for Information-Request (using the IRT option).
5303 dhc6_check_irt(struct client_state
*client
)
5305 struct option
**req
;
5306 struct option_cache
*oc
;
5307 TIME expire
= MAX_TIME
;
5310 isc_boolean_t found
= ISC_FALSE
;
5312 cancel_timeout(refresh_info_request6
, client
);
5314 req
= client
->config
->requested_options
;
5315 for (i
= 0; req
[i
] != NULL
; i
++) {
5316 if (req
[i
] == irt_option
) {
5321 /* Simply return gives a endless loop waiting for nothing. */
5324 if (!dhcpv4_over_dhcpv6
)
5329 oc
= lookup_option(&dhcpv6_universe
, client
->active_lease
->options
,
5330 D6O_INFORMATION_REFRESH_TIME
);
5332 struct data_string irt
;
5334 memset(&irt
, 0, sizeof(irt
));
5335 if (!evaluate_option_cache(&irt
, NULL
, NULL
, client
,
5336 client
->active_lease
->options
,
5337 NULL
, &global_scope
, oc
, MDL
) ||
5339 log_error("Can't evaluate IRT.");
5341 expire
= getULong(irt
.data
);
5342 if (expire
< IRT_MINIMUM
)
5343 expire
= IRT_MINIMUM
;
5344 if (expire
== 0xffffffff)
5347 data_string_forget(&irt
, MDL
);
5349 expire
= IRT_DEFAULT
;
5351 if (expire
!= MAX_TIME
) {
5352 log_debug("PRC: Refresh event scheduled in %u seconds.",
5354 tv
.tv_sec
= cur_time
+ expire
;
5356 add_timeout(&tv
, refresh_info_request6
, client
, NULL
, NULL
);
5360 /* We got a Reply. Give dhclient-script a tickle to inform it about
5361 * the new values, and then lay in wait for the next event.
5364 start_informed(struct client_state
*client
)
5366 client
->v6_handler
= informed_handler
;
5368 log_debug("PRC: Done.");
5370 client
->state
= S_BOUND
;
5372 script_init(client
, "RENEW6", NULL
);
5373 if (client
->old_lease
!= NULL
)
5374 script_write_params6(client
, "old_",
5375 client
->old_lease
->options
);
5376 script_write_params6(client
, "new_", client
->active_lease
->options
);
5377 script_write_requested6(client
);
5381 if (dhcpv4_over_dhcpv6
)
5387 if (client
->old_lease
!= NULL
) {
5388 dhc6_lease_destroy(&client
->old_lease
, MDL
);
5389 client
->old_lease
= NULL
;
5392 /* Schedule events. */
5393 dhc6_check_irt(client
);
5396 /* While informed, ignore packets.
5399 informed_handler(struct packet
*packet
, struct client_state
*client
)
5401 log_debug("RCV: Input packets are ignored once bound.");
5404 /* make_client6_options() fetches option caches relevant to the client's
5405 * scope and places them into the sent_options cache. This cache is later
5406 * used to populate DHCPv6 output packets with options.
5409 make_client6_options(struct client_state
*client
, struct option_state
**op
,
5410 struct dhc6_lease
*lease
, u_int8_t message
)
5412 struct option_cache
*oc
;
5413 struct option
**req
;
5414 struct buffer
*buffer
;
5415 int buflen
, i
, oro_len
;
5417 if ((op
== NULL
) || (client
== NULL
))
5421 option_state_dereference(op
, MDL
);
5423 /* Create a cache to carry options to transmission. */
5424 option_state_allocate(op
, MDL
);
5426 /* Create and store an 'elapsed time' option in the cache. */
5428 if (option_cache_allocate(&oc
, MDL
)) {
5429 const unsigned char *cdata
;
5431 cdata
= (unsigned char *)&client
->elapsed
;
5433 if (make_const_data(&oc
->expression
, cdata
, 2, 0, 0, MDL
)) {
5434 option_reference(&oc
->option
, elapsed_option
, MDL
);
5435 save_option(&dhcpv6_universe
, *op
, oc
);
5438 option_cache_dereference(&oc
, MDL
);
5441 /* Bring in any configured options to send. */
5442 if (client
->config
->on_transmission
)
5443 execute_statements_in_scope(NULL
, NULL
, NULL
, client
,
5444 lease
? lease
->options
: NULL
,
5446 client
->config
->on_transmission
,
5449 /* Rapid-commit is only for SOLICITs. */
5450 if (message
!= DHCPV6_SOLICIT
)
5451 delete_option(&dhcpv6_universe
, *op
, D6O_RAPID_COMMIT
);
5453 /* See if the user configured a DUID in a relevant scope. If not,
5454 * introduce our default manufactured id.
5456 if ((oc
= lookup_option(&dhcpv6_universe
, *op
,
5457 D6O_CLIENTID
)) == NULL
) {
5458 if (!option_cache(&oc
, &default_duid
, NULL
, clientid_option
,
5460 log_fatal("Failure assembling a DUID.");
5462 save_option(&dhcpv6_universe
, *op
, oc
);
5463 option_cache_dereference(&oc
, MDL
);
5466 /* In cases where we're responding to a single server, put the
5467 * server's id in the response.
5469 * Note that lease is NULL for SOLICIT or INFO request messages,
5470 * and otherwise MUST be present.
5472 if (lease
== NULL
) {
5473 if ((message
!= DHCPV6_SOLICIT
) &&
5474 (message
!= DHCPV6_INFORMATION_REQUEST
))
5475 log_fatal("Impossible condition at %s:%d.", MDL
);
5476 } else if ((message
!= DHCPV6_REBIND
) &&
5477 (message
!= DHCPV6_CONFIRM
)) {
5478 oc
= lookup_option(&dhcpv6_universe
, lease
->options
,
5481 save_option(&dhcpv6_universe
, *op
, oc
);
5484 /* 'send dhcp6.oro foo;' syntax we used in 4.0.0a1/a2 has been
5485 * deprecated by adjustments to the 'request' syntax also used for
5488 if (lookup_option(&dhcpv6_universe
, *op
, D6O_ORO
) != NULL
)
5489 log_error("'send dhcp6.oro' syntax is deprecated, please "
5490 "use the 'request' syntax (\"man dhclient.conf\").");
5492 /* Construct and store an ORO (Option Request Option). It is a
5493 * fatal error to fail to send an ORO (of at least zero length).
5495 * Discussion: RFC3315 appears to be inconsistent in its statements
5496 * of whether or not the ORO is mandatory. In section 18.1.1
5497 * ("Creation and Transmission of Request Messages"):
5499 * The client MUST include an Option Request option (see section
5500 * 22.7) to indicate the options the client is interested in
5501 * receiving. The client MAY include options with data values as
5502 * hints to the server about parameter values the client would like
5505 * This MUST is missing from the creation/transmission of other
5506 * messages (such as Renew and Rebind), and the section 22.7 ("Option
5507 * Request Option" format and definition):
5509 * A client MAY include an Option Request option in a Solicit,
5510 * Request, Renew, Rebind, Confirm or Information-request message to
5511 * inform the server about options the client wants the server to
5512 * send to the client. A server MAY include an Option Request
5513 * option in a Reconfigure option to indicate which options the
5514 * client should request from the server.
5516 * seems to relax the requirement from MUST to MAY (and still other
5517 * language in RFC3315 supports this).
5519 * In lieu of a clarification of RFC3315, we will conform with the
5520 * MUST. Instead of an absent ORO, we will if there are no options
5521 * to request supply an empty ORO. Theoretically, an absent ORO is
5522 * difficult to interpret (does the client want all options or no
5523 * options?). A zero-length ORO is intuitively clear: requesting
5529 if (!buffer_allocate(&buffer
, buflen
, MDL
))
5530 log_fatal("Out of memory constructing DHCPv6 ORO.");
5531 req
= client
->config
->requested_options
;
5533 for (i
= 0 ; req
[i
] != NULL
; i
++) {
5534 if (buflen
== oro_len
) {
5535 struct buffer
*tmpbuf
= NULL
;
5540 buffer_reference(&tmpbuf
, buffer
, MDL
);
5541 buffer_dereference(&buffer
, MDL
);
5543 if (!buffer_allocate(&buffer
, buflen
, MDL
))
5544 log_fatal("Out of memory resizing "
5545 "DHCPv6 ORO buffer.");
5547 memcpy(buffer
->data
, tmpbuf
->data
, oro_len
);
5549 buffer_dereference(&tmpbuf
, MDL
);
5552 if (req
[i
]->universe
== &dhcpv6_universe
) {
5553 /* Append the code to the ORO. */
5554 putUShort(buffer
->data
+ oro_len
,
5562 if (make_const_option_cache(&oc
, &buffer
, NULL
, oro_len
,
5564 save_option(&dhcpv6_universe
, *op
, oc
);
5566 log_fatal("Unable to create ORO option cache.");
5570 * Note: make_const_option_cache() consumes the buffer, we do not
5571 * need to dereference it (XXX).
5573 option_cache_dereference(&oc
, MDL
);
5576 /* A clone of the DHCPv4 script_write_params() minus the DHCPv4-specific
5577 * filename, server-name, etc specifics.
5579 * Simply, store all values present in all universes of the option state
5580 * (probably derived from a DHCPv6 packet) into environment variables
5581 * named after the option names (and universe names) but with the 'prefix'
5584 * Later, dhclient-script may compare for example "new_time_servers" and
5585 * "old_time_servers" for differences, and only upon detecting a change
5586 * bother to rewrite ntp.conf and restart it. Or something along those
5590 script_write_params6(struct client_state
*client
, const char *prefix
,
5591 struct option_state
*options
)
5593 struct envadd_state es
;
5596 if (options
== NULL
)
5602 for (i
= 0 ; i
< options
->universe_count
; i
++) {
5603 option_space_foreach(NULL
, NULL
, client
, NULL
, options
,
5604 &global_scope
, universes
[i
], &es
,
5605 client_option_envadd
);
5610 * A clone of the DHCPv4 routine.
5611 * Write out the environment variables for the objects that the
5612 * client requested. If the object was requested the variable will be:
5613 * requested_<option_name>=1
5614 * If it wasn't requested there won't be a variable.
5616 static void script_write_requested6(client
)
5617 struct client_state
*client
;
5620 struct option
**req
;
5622 req
= client
->config
->requested_options
;
5627 for (i
= 0 ; req
[i
] != NULL
; i
++) {
5628 if ((req
[i
]->universe
== &dhcpv6_universe
) &&
5629 dhcp_option_ev_name (name
, sizeof(name
), req
[i
])) {
5630 client_envadd(client
, "requested_", name
, "%d", 1);
5636 * Check if there is something not fully defined in the active lease.
5638 static isc_boolean_t
5639 active_prefix(struct client_state
*client
)
5641 struct dhc6_lease
*lease
;
5643 struct dhc6_addr
*pref
;
5646 lease
= client
->active_lease
;
5649 memset(zeros
, 0, 16);
5650 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
5651 if (ia
->ia_type
!= D6O_IA_PD
)
5653 for (pref
= ia
->addrs
; pref
!= NULL
; pref
= pref
->next
) {
5654 if (pref
->plen
== 0)
5656 if (pref
->address
.len
!= 16)
5658 if (memcmp(pref
->address
.iabuf
, zeros
, 16) == 0)