1 /* dhc6.c - DHCPv6 client routines. */
4 * Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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 * Newmarket, NH 03857 USA
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_decline6(struct client_state
*client
);
119 static void do_decline6(void *input
);
120 static void start_informed(struct client_state
*client
);
121 void informed_handler(struct packet
*packet
, struct client_state
*client
);
122 void bound_handler(struct packet
*packet
, struct client_state
*client
);
123 void start_renew6(void *input
);
124 void start_rebind6(void *input
);
125 void do_depref(void *input
);
126 void do_expire(void *input
);
127 static void make_client6_options(struct client_state
*client
,
128 struct option_state
**op
,
129 struct dhc6_lease
*lease
, u_int8_t message
);
130 static void script_write_params6(struct client_state
*client
,
132 struct option_state
*options
);
133 static void script_write_requested6(struct client_state
*client
);
134 static isc_boolean_t
active_prefix(struct client_state
*client
);
136 static int check_timing6(struct client_state
*client
, u_int8_t msg_type
,
137 char *msg_str
, struct dhc6_lease
*lease
,
138 struct data_string
*ds
);
139 static isc_result_t
dhc6_get_status_code(struct option_state
*options
,
141 struct data_string
*msg
);
142 static isc_result_t
dhc6_check_status(isc_result_t rval
,
143 struct option_state
*options
,
146 static int dhc6_score_lease(struct client_state
*client
,
147 struct dhc6_lease
*lease
);
148 static isc_result_t
dhc6_add_ia_na_decline(struct client_state
*client
,
149 struct data_string
*packet
,
150 struct dhc6_lease
*lease
);
151 static int drop_declined_addrs(struct dhc6_lease
*lease
);
152 static isc_boolean_t
unexpired_address_in_lease(struct dhc6_lease
*lease
);
155 extern int stateless
;
156 extern int prefix_len_hint
;
157 extern int address_prefix_len
;
160 * Assign DHCPv6 port numbers as a client.
163 dhcpv6_client_assignments(void)
168 if (path_dhclient_pid
== NULL
)
169 path_dhclient_pid
= _PATH_DHCLIENT6_PID
;
170 if (path_dhclient_db
== NULL
)
171 path_dhclient_db
= _PATH_DHCLIENT6_DB
;
173 if (local_port
== 0) {
174 ent
= getservbyname("dhcpv6-client", "udp");
176 local_port
= htons(546);
178 local_port
= ent
->s_port
;
181 if (remote_port
== 0) {
182 ent
= getservbyname("dhcpv6-server", "udp");
184 remote_port
= htons(547);
186 remote_port
= ent
->s_port
;
189 memset(&DHCPv6DestAddr
, 0, sizeof(DHCPv6DestAddr
));
190 DHCPv6DestAddr
.sin6_family
= AF_INET6
;
191 DHCPv6DestAddr
.sin6_port
= remote_port
;
192 if (inet_pton(AF_INET6
, All_DHCP_Relay_Agents_and_Servers
,
193 &DHCPv6DestAddr
.sin6_addr
) <= 0) {
194 log_fatal("Bad address %s", All_DHCP_Relay_Agents_and_Servers
);
198 if (!option_code_hash_lookup(&clientid_option
,
199 dhcpv6_universe
.code_hash
, &code
, 0, MDL
))
200 log_fatal("Unable to find the CLIENTID option definition.");
202 code
= D6O_ELAPSED_TIME
;
203 if (!option_code_hash_lookup(&elapsed_option
,
204 dhcpv6_universe
.code_hash
, &code
, 0, MDL
))
205 log_fatal("Unable to find the ELAPSED_TIME option definition.");
208 if (!option_code_hash_lookup(&ia_na_option
, dhcpv6_universe
.code_hash
,
210 log_fatal("Unable to find the IA_NA option definition.");
213 if (!option_code_hash_lookup(&ia_ta_option
, dhcpv6_universe
.code_hash
,
215 log_fatal("Unable to find the IA_TA option definition.");
218 if (!option_code_hash_lookup(&ia_pd_option
, dhcpv6_universe
.code_hash
,
220 log_fatal("Unable to find the IA_PD option definition.");
223 if (!option_code_hash_lookup(&iaaddr_option
, dhcpv6_universe
.code_hash
,
225 log_fatal("Unable to find the IAADDR option definition.");
228 if (!option_code_hash_lookup(&iaprefix_option
,
229 dhcpv6_universe
.code_hash
,
231 log_fatal("Unable to find the IAPREFIX option definition.");
234 if (!option_code_hash_lookup(&oro_option
, dhcpv6_universe
.code_hash
,
236 log_fatal("Unable to find the ORO option definition.");
238 code
= D6O_INFORMATION_REFRESH_TIME
;
239 if (!option_code_hash_lookup(&irt_option
, dhcpv6_universe
.code_hash
,
241 log_fatal("Unable to find the IRT option definition.");
243 #ifndef __CYGWIN32__ /* XXX */
249 * Instead of implementing RFC3315 RAND (section 14) as a float "between"
250 * -0.1 and 0.1 non-inclusive, we implement it as an integer.
252 * The result is expected to follow this table:
255 * - ERROR - base <= 0
256 * 0 1 0..0 1 <= base <= 10
257 * 1 3 -1..1 11 <= base <= 20
258 * 2 5 -2..2 21 <= base <= 30
259 * 3 7 -3..3 31 <= base <= 40
262 * XXX: For this to make sense, we really need to do timing on a
263 * XXX: usec scale...we currently can assume zero for any value less than
264 * XXX: 11, which are very common in early stages of transmission for most
275 * A zero or less timeout is a bad thing...we don't want to
279 log_fatal("Impossible condition at %s:%d.", MDL
);
282 * The first thing we do is count how many random integers we want
283 * in either direction (best thought of as the maximum negative
284 * integer, as we will subtract this potentially from a random 0).
286 split
= (base
- 1) / 10;
288 /* Don't bother with the rest of the math if we know we'll get 0. */
293 * Then we count the total number of integers in this set. This
294 * is twice the number of integers in positive and negative
295 * directions, plus zero (-1, 0, 1 is 3, -2..2 adds 2 to 5, so forth).
297 range
= (split
* 2) + 1;
299 /* Take a random number from [0..(range-1)]. */
303 /* Offset it to uncover potential negative values. */
309 /* Initialize message exchange timers (set RT from Initial-RT). */
311 dhc6_retrans_init(struct client_state
*client
)
315 /* Initialize timers. */
317 client
->RT
= client
->IRT
+ dhc6_rand(client
->IRT
);
319 /* Generate a new random 24-bit transaction ID for this exchange. */
321 #if (RAND_MAX >= 0x00ffffff)
323 #elif (RAND_MAX >= 0x0000ffff)
324 xid
= (random() << 16) ^ random();
325 #elif (RAND_MAX >= 0x000000ff)
326 xid
= (random() << 16) ^ (random() << 8) ^ random();
328 # error "Random number generator of less than 8 bits not supported."
331 client
->dhcpv6_transaction_id
[0] = (xid
>> 16) & 0xff;
332 client
->dhcpv6_transaction_id
[1] = (xid
>> 8) & 0xff;
333 client
->dhcpv6_transaction_id
[2] = xid
& 0xff;
336 /* Advance the DHCPv6 retransmission state once. */
338 dhc6_retrans_advance(struct client_state
*client
)
340 struct timeval elapsed
, elapsed_plus_rt
;
342 /* elapsed = cur - start */
343 elapsed
.tv_sec
= cur_tv
.tv_sec
- client
->start_time
.tv_sec
;
344 elapsed
.tv_usec
= cur_tv
.tv_usec
- client
->start_time
.tv_usec
;
345 if (elapsed
.tv_usec
< 0) {
347 elapsed
.tv_usec
+= 1000000;
349 /* retrans_advance is called after consuming client->RT. */
351 elapsed
.tv_sec
+= client
->RT
/ 100;
352 elapsed
.tv_usec
+= (client
->RT
% 100) * 10000;
353 if (elapsed
.tv_usec
>= 1000000) {
355 elapsed
.tv_usec
-= 1000000;
358 * Save what the time will be after the current RT to determine
359 * what the delta to MRD will be.
361 elapsed_plus_rt
.tv_sec
= elapsed
.tv_sec
;
362 elapsed_plus_rt
.tv_usec
= elapsed
.tv_usec
;
365 * RT for each subsequent message transmission is based on the previous
368 * RT = 2*RTprev + RAND*RTprev
370 client
->RT
+= client
->RT
+ dhc6_rand(client
->RT
);
373 * MRT specifies an upper bound on the value of RT (disregarding the
374 * randomization added by the use of RAND). If MRT has a value of 0,
375 * there is no upper limit on the value of RT. Otherwise:
378 * RT = MRT + RAND*MRT
380 if ((client
->MRT
!= 0) && (client
->RT
> client
->MRT
))
381 client
->RT
= client
->MRT
+ dhc6_rand(client
->MRT
);
384 * Further, if there's an MRD, we should wake up upon reaching
385 * the MRD rather than at some point after it.
387 if (client
->MRD
== 0) {
392 /* elapsed += client->RT */
393 elapsed
.tv_sec
+= client
->RT
/ 100;
394 elapsed
.tv_usec
+= (client
->RT
% 100) * 10000;
395 if (elapsed
.tv_usec
>= 1000000) {
397 elapsed
.tv_usec
-= 1000000;
399 if (elapsed
.tv_sec
>= client
->MRD
) {
401 * The desired RT is the time that will be remaining in MRD
402 * when the current timeout finishes. We then have
403 * desired RT = MRD - (elapsed time + previous RT); or
404 * desired RT = MRD - elapsed_plut_rt;
406 client
->RT
= client
->MRD
- elapsed_plus_rt
.tv_sec
;
407 client
->RT
= (client
->RT
* 100) -
408 (elapsed_plus_rt
.tv_usec
/ 10000);
415 /* Quick validation of DHCPv6 ADVERTISE packet contents. */
417 valid_reply(struct packet
*packet
, struct client_state
*client
)
419 struct data_string sid
, cid
;
420 struct option_cache
*oc
;
423 memset(&sid
, 0, sizeof(sid
));
424 memset(&cid
, 0, sizeof(cid
));
426 if (!lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
)) {
427 log_error("Response without a server identifier received.");
431 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_CLIENTID
);
433 !evaluate_option_cache(&sid
, packet
, NULL
, client
, packet
->options
,
434 client
->sent_options
, &global_scope
, oc
,
436 log_error("Response without a client identifier.");
440 oc
= lookup_option(&dhcpv6_universe
, client
->sent_options
,
443 !evaluate_option_cache(&cid
, packet
, NULL
, client
,
444 client
->sent_options
, NULL
, &global_scope
,
446 log_error("Local client identifier is missing!");
451 sid
.len
!= cid
.len
||
452 memcmp(sid
.data
, cid
.data
, sid
.len
)) {
453 log_error("Advertise with matching transaction ID, but "
454 "mismatching client id.");
458 /* clean up pointers to the strings */
459 if (sid
.data
!= NULL
)
460 data_string_forget(&sid
, MDL
);
461 if (cid
.data
!= NULL
)
462 data_string_forget(&cid
, MDL
);
468 * Create a complete copy of a DHCPv6 lease structure.
470 static struct dhc6_lease
*
471 dhc6_dup_lease(struct dhc6_lease
*lease
, const char *file
, int line
)
473 struct dhc6_lease
*copy
;
474 struct dhc6_ia
**insert_ia
, *ia
;
476 copy
= dmalloc(sizeof(*copy
), file
, line
);
478 log_error("Out of memory for v6 lease structure.");
482 data_string_copy(©
->server_id
, &lease
->server_id
, file
, line
);
483 copy
->pref
= lease
->pref
;
485 memcpy(copy
->dhcpv6_transaction_id
, lease
->dhcpv6_transaction_id
,
486 sizeof(copy
->dhcpv6_transaction_id
));
488 option_state_reference(©
->options
, lease
->options
, file
, line
);
490 insert_ia
= ©
->bindings
;
491 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
492 *insert_ia
= dhc6_dup_ia(ia
, file
, line
);
494 if (*insert_ia
== NULL
) {
495 dhc6_lease_destroy(©
, file
, line
);
499 insert_ia
= &(*insert_ia
)->next
;
506 * Duplicate an IA structure.
508 static struct dhc6_ia
*
509 dhc6_dup_ia(struct dhc6_ia
*ia
, const char *file
, int line
)
511 struct dhc6_ia
*copy
;
512 struct dhc6_addr
**insert_addr
, *addr
;
514 copy
= dmalloc(sizeof(*ia
), file
, line
);
516 log_error("Out of memory for v6 duplicate IA structure.");
520 memcpy(copy
->iaid
, ia
->iaid
, sizeof(copy
->iaid
));
522 copy
->ia_type
= ia
->ia_type
;
523 copy
->starts
= ia
->starts
;
524 copy
->renew
= ia
->renew
;
525 copy
->rebind
= ia
->rebind
;
527 insert_addr
= ©
->addrs
;
528 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
529 *insert_addr
= dhc6_dup_addr(addr
, file
, line
);
531 if (*insert_addr
== NULL
) {
532 dhc6_ia_destroy(©
, file
, line
);
536 insert_addr
= &(*insert_addr
)->next
;
539 if (ia
->options
!= NULL
)
540 option_state_reference(©
->options
, ia
->options
,
547 * Duplicate an IAADDR or IAPREFIX structure.
549 static struct dhc6_addr
*
550 dhc6_dup_addr(struct dhc6_addr
*addr
, const char *file
, int line
)
552 struct dhc6_addr
*copy
;
554 copy
= dmalloc(sizeof(*addr
), file
, line
);
559 memcpy(©
->address
, &addr
->address
, sizeof(copy
->address
));
561 copy
->plen
= addr
->plen
;
562 copy
->flags
= addr
->flags
;
563 copy
->starts
= addr
->starts
;
564 copy
->preferred_life
= addr
->preferred_life
;
565 copy
->max_life
= addr
->max_life
;
567 if (addr
->options
!= NULL
)
568 option_state_reference(©
->options
, addr
->options
,
575 * Form a DHCPv6 lease structure based upon packet contents. Creates and
576 * populates IA's and any IAADDR/IAPREFIX's they contain.
577 * Parsed options are deleted in order to not save them in the lease file.
579 * If we get a status code of NoAddrs or NoPrefix we toss the affected
580 * IAs. If it as at the top level we toss all IAs of that type. If it
581 * is in an IA we only toss that one. According to the spec we shouldn't
582 * get a NoPrefix status at the top level but we will allow it.
585 static struct dhc6_lease
*
586 dhc6_leaseify(struct packet
*packet
, struct client_state
* client
)
588 struct data_string ds
;
589 struct dhc6_lease
*lease
;
590 struct option_cache
*oc
;
593 lease
= dmalloc(sizeof(*lease
), MDL
);
595 log_error("Out of memory for v6 lease structure.");
599 memcpy(lease
->dhcpv6_transaction_id
, packet
->dhcpv6_transaction_id
, 3);
600 option_state_reference(&lease
->options
, packet
->options
, MDL
);
602 memset(&ds
, 0, sizeof(ds
));
604 /* Determine preference (default zero). */
605 oc
= lookup_option(&dhcpv6_universe
, lease
->options
, D6O_PREFERENCE
);
607 evaluate_option_cache(&ds
, packet
, NULL
, NULL
, lease
->options
,
608 NULL
, &global_scope
, oc
, MDL
)) {
610 log_error("Invalid length of DHCPv6 Preference option "
611 "(%d != 1)", ds
.len
);
612 data_string_forget(&ds
, MDL
);
613 dhc6_lease_destroy(&lease
, MDL
);
616 lease
->pref
= ds
.data
[0];
617 log_debug("RCV: X-- Preference %u.",
618 (unsigned)lease
->pref
);
621 data_string_forget(&ds
, MDL
);
623 delete_option(&dhcpv6_universe
, lease
->options
, D6O_PREFERENCE
);
625 /* Get the top level status code. If the code is NoAddrsAvail
626 * or NoPrefixAvail strip it from the options as we don't
627 * want it to show up in check_[advertise reply]. We
628 * pass it along to the parse_ia_xx routines and they
629 * will drop the affected IAs for NoAddrs or NoPrefix,
630 * other status codes will be ignored and handled by
631 * the check_[advertise reply] routines.
633 code
= STATUS_Success
;
634 if ((dhc6_get_status_code(lease
->options
, &code
, NULL
) == ISC_R_SUCCESS
)
636 ((code
== STATUS_NoAddrsAvail
) || (code
== STATUS_NoPrefixAvail
))) {
637 delete_option(&dhcpv6_universe
, lease
->options
,
642 * Dig into recursive DHCPv6 pockets for IA_NA and contained IAADDR
645 if (dhc6_parse_ia_na(&lease
->bindings
, packet
,
646 lease
->options
, code
) != ISC_R_SUCCESS
) {
647 /* Error conditions are logged by the caller. */
648 dhc6_lease_destroy(&lease
, MDL
);
652 * Dig into recursive DHCPv6 pockets for IA_TA and contained IAADDR
655 if (dhc6_parse_ia_ta(&lease
->bindings
, packet
,
656 lease
->options
, code
) != ISC_R_SUCCESS
) {
657 /* Error conditions are logged by the caller. */
658 dhc6_lease_destroy(&lease
, MDL
);
662 * Dig into recursive DHCPv6 pockets for IA_PD and contained IAPREFIX
665 if (dhc6_parse_ia_pd(&lease
->bindings
, packet
,
666 lease
->options
, code
) != ISC_R_SUCCESS
) {
667 /* Error conditions are logged by the caller. */
668 dhc6_lease_destroy(&lease
, MDL
);
673 * This is last because in the future we may want to make a different
674 * key based upon additional information from the packet (we may need
675 * to allow multiple leases in one client state per server, but we're
676 * not sure based on what additional keys now).
678 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
680 !evaluate_option_cache(&lease
->server_id
, packet
, NULL
, NULL
,
681 lease
->options
, NULL
, &global_scope
,
683 lease
->server_id
.len
== 0) {
684 /* This should be impossible due to validation checks earlier.
686 log_error("Invalid SERVERID option cache.");
687 dhc6_lease_destroy(&lease
, MDL
);
690 log_debug("RCV: X-- Server ID: %s",
691 print_hex_1(lease
->server_id
.len
,
692 lease
->server_id
.data
, 52));
695 execute_statements_in_scope(NULL
, (struct packet
*)packet
, NULL
,
696 client
, lease
->options
, lease
->options
,
697 &global_scope
, client
->config
->on_receipt
,
704 dhc6_parse_ia_na(struct dhc6_ia
**pia
, struct packet
*packet
,
705 struct option_state
*options
, unsigned code
)
707 struct data_string ds
;
709 struct option_cache
*oc
;
713 memset(&ds
, 0, sizeof(ds
));
715 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IA_NA
);
716 for ( ; oc
!= NULL
; oc
= oc
->next
) {
717 ia
= dmalloc(sizeof(*ia
), MDL
);
719 log_error("Out of memory allocating IA_NA structure.");
720 return ISC_R_NOMEMORY
;
721 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
723 &global_scope
, oc
, MDL
) &&
725 memcpy(ia
->iaid
, ds
.data
, 4);
726 ia
->ia_type
= D6O_IA_NA
;
727 ia
->starts
= cur_time
;
728 ia
->renew
= getULong(ds
.data
+ 4);
729 ia
->rebind
= getULong(ds
.data
+ 8);
731 log_debug("RCV: X-- IA_NA %s",
732 print_hex_1(4, ia
->iaid
, 59));
733 /* XXX: This should be the printed time I think. */
734 log_debug("RCV: | X-- starts %u",
735 (unsigned)ia
->starts
);
736 log_debug("RCV: | X-- t1 - renew +%u", ia
->renew
);
737 log_debug("RCV: | X-- t2 - rebind +%u", ia
->rebind
);
740 * RFC3315 section 22.4, discard IA_NA's that
741 * have t1 greater than t2, and both not zero.
742 * Since RFC3315 defines this behaviour, it is not
743 * an error - just normal operation.
745 * Note that RFC3315 says we MUST honor these values
746 * if they are not zero. So insane values are
749 if ((ia
->renew
> 0) && (ia
->rebind
> 0) &&
750 (ia
->renew
> ia
->rebind
)) {
751 log_debug("RCV: | !-- INVALID renew/rebind "
752 "times, IA_NA discarded.");
754 data_string_forget(&ds
, MDL
);
759 log_debug("RCV: | X-- [Options]");
761 if (!option_state_allocate(&ia
->options
,
763 log_error("Out of memory allocating "
764 "IA_NA option state.");
766 data_string_forget(&ds
, MDL
);
767 return ISC_R_NOMEMORY
;
770 if (!parse_option_buffer(ia
->options
,
774 log_error("Corrupt IA_NA options.");
775 option_state_dereference(&ia
->options
,
778 data_string_forget(&ds
, MDL
);
779 return DHCP_R_BADPARSE
;
782 data_string_forget(&ds
, MDL
);
784 if (ia
->options
!= NULL
) {
785 result
= dhc6_parse_addrs(&ia
->addrs
, packet
,
787 if (result
!= ISC_R_SUCCESS
) {
788 option_state_dereference(&ia
->options
,
795 /* If we have no addresses or the top level status code
796 * or the status code in this IA indicate no addresses
799 ia_code
= STATUS_Success
;
800 if ((ia
->addrs
== NULL
) ||
801 (code
== STATUS_NoAddrsAvail
) ||
802 ((ia
->options
!= NULL
) &&
803 (dhc6_get_status_code(ia
->options
, &ia_code
, NULL
)
805 (ia_code
== STATUS_NoAddrsAvail
))) {
806 log_debug("RCV: | !-- Status code of "
807 "no addrs, IA_NA discarded.");
808 dhc6_ia_destroy(&ia
, MDL
);
817 log_error("Invalid IA_NA option cache.");
819 data_string_forget(&ds
, MDL
);
820 return ISC_R_UNEXPECTED
;
823 delete_option(&dhcpv6_universe
, options
, D6O_IA_NA
);
825 return ISC_R_SUCCESS
;
829 dhc6_parse_ia_ta(struct dhc6_ia
**pia
, struct packet
*packet
,
830 struct option_state
*options
, unsigned code
)
832 struct data_string ds
;
834 struct option_cache
*oc
;
838 memset(&ds
, 0, sizeof(ds
));
840 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IA_TA
);
841 for ( ; oc
!= NULL
; oc
= oc
->next
) {
842 ia
= dmalloc(sizeof(*ia
), MDL
);
844 log_error("Out of memory allocating IA_TA structure.");
845 return ISC_R_NOMEMORY
;
846 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
848 &global_scope
, oc
, MDL
) &&
850 memcpy(ia
->iaid
, ds
.data
, 4);
851 ia
->ia_type
= D6O_IA_TA
;
852 ia
->starts
= cur_time
;
854 log_debug("RCV: X-- IA_TA %s",
855 print_hex_1(4, ia
->iaid
, 59));
856 /* XXX: This should be the printed time I think. */
857 log_debug("RCV: | X-- starts %u",
858 (unsigned)ia
->starts
);
861 log_debug("RCV: | X-- [Options]");
863 if (!option_state_allocate(&ia
->options
,
865 log_error("Out of memory allocating "
866 "IA_TA option state.");
868 data_string_forget(&ds
, MDL
);
869 return ISC_R_NOMEMORY
;
872 if (!parse_option_buffer(ia
->options
,
876 log_error("Corrupt IA_TA options.");
877 option_state_dereference(&ia
->options
,
880 data_string_forget(&ds
, MDL
);
881 return DHCP_R_BADPARSE
;
884 data_string_forget(&ds
, MDL
);
886 if (ia
->options
!= NULL
) {
887 result
= dhc6_parse_addrs(&ia
->addrs
, packet
,
889 if (result
!= ISC_R_SUCCESS
) {
890 option_state_dereference(&ia
->options
,
897 /* If we have no addresses or the top level status code
898 * or the status code in this IA indicate no addresses
901 ia_code
= STATUS_Success
;
902 if ((ia
->addrs
== NULL
) ||
903 (code
== STATUS_NoAddrsAvail
) ||
904 ((ia
->options
!= NULL
) &&
905 (dhc6_get_status_code(ia
->options
, &ia_code
, NULL
)
907 (ia_code
== STATUS_NoAddrsAvail
))) {
908 log_debug("RCV: | !-- Status code of "
909 "no addrs, IA_TA discarded.");
910 dhc6_ia_destroy(&ia
, MDL
);
919 log_error("Invalid IA_TA option cache.");
921 data_string_forget(&ds
, MDL
);
922 return ISC_R_UNEXPECTED
;
925 delete_option(&dhcpv6_universe
, options
, D6O_IA_TA
);
927 return ISC_R_SUCCESS
;
931 dhc6_parse_ia_pd(struct dhc6_ia
**pia
, struct packet
*packet
,
932 struct option_state
*options
, unsigned code
)
934 struct data_string ds
;
936 struct option_cache
*oc
;
940 memset(&ds
, 0, sizeof(ds
));
942 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IA_PD
);
943 for ( ; oc
!= NULL
; oc
= oc
->next
) {
944 ia
= dmalloc(sizeof(*ia
), MDL
);
946 log_error("Out of memory allocating IA_PD structure.");
947 return ISC_R_NOMEMORY
;
948 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
950 &global_scope
, oc
, MDL
) &&
952 memcpy(ia
->iaid
, ds
.data
, 4);
953 ia
->ia_type
= D6O_IA_PD
;
954 ia
->starts
= cur_time
;
955 ia
->renew
= getULong(ds
.data
+ 4);
956 ia
->rebind
= getULong(ds
.data
+ 8);
958 log_debug("RCV: X-- IA_PD %s",
959 print_hex_1(4, ia
->iaid
, 59));
960 /* XXX: This should be the printed time I think. */
961 log_debug("RCV: | X-- starts %u",
962 (unsigned)ia
->starts
);
963 log_debug("RCV: | X-- t1 - renew +%u", ia
->renew
);
964 log_debug("RCV: | X-- t2 - rebind +%u", ia
->rebind
);
967 * RFC3633 section 9, discard IA_PD's that
968 * have t1 greater than t2, and both not zero.
969 * Since RFC3633 defines this behaviour, it is not
970 * an error - just normal operation.
972 if ((ia
->renew
> 0) && (ia
->rebind
> 0) &&
973 (ia
->renew
> ia
->rebind
)) {
974 log_debug("RCV: | !-- INVALID renew/rebind "
975 "times, IA_PD discarded.");
977 data_string_forget(&ds
, MDL
);
982 log_debug("RCV: | X-- [Options]");
984 if (!option_state_allocate(&ia
->options
,
986 log_error("Out of memory allocating "
987 "IA_PD option state.");
989 data_string_forget(&ds
, MDL
);
990 return ISC_R_NOMEMORY
;
993 if (!parse_option_buffer(ia
->options
,
997 log_error("Corrupt IA_PD options.");
998 option_state_dereference(&ia
->options
,
1001 data_string_forget(&ds
, MDL
);
1002 return DHCP_R_BADPARSE
;
1005 data_string_forget(&ds
, MDL
);
1007 if (ia
->options
!= NULL
) {
1008 result
= dhc6_parse_prefixes(&ia
->addrs
,
1011 if (result
!= ISC_R_SUCCESS
) {
1012 option_state_dereference(&ia
->options
,
1019 /* If we have no prefixes or the top level status code
1020 * or the status code in this IA indicate no prefixes
1023 ia_code
= STATUS_Success
;
1024 if ((ia
->addrs
== NULL
) ||
1025 (code
== STATUS_NoPrefixAvail
) ||
1026 ((ia
->options
!= NULL
) &&
1027 (dhc6_get_status_code(ia
->options
, &ia_code
, NULL
)
1028 == ISC_R_SUCCESS
) &&
1029 (ia_code
== STATUS_NoPrefixAvail
))) {
1030 log_debug("RCV: | !-- Status code of "
1031 "no prefix, IA_PD discarded.");
1032 dhc6_ia_destroy(&ia
, MDL
);
1036 while (*pia
!= NULL
)
1037 pia
= &(*pia
)->next
;
1041 log_error("Invalid IA_PD option cache.");
1043 data_string_forget(&ds
, MDL
);
1044 return ISC_R_UNEXPECTED
;
1047 delete_option(&dhcpv6_universe
, options
, D6O_IA_PD
);
1049 return ISC_R_SUCCESS
;
1054 dhc6_parse_addrs(struct dhc6_addr
**paddr
, struct packet
*packet
,
1055 struct option_state
*options
)
1057 struct data_string ds
;
1058 struct option_cache
*oc
;
1059 struct dhc6_addr
*addr
;
1060 isc_result_t rval
= ISC_R_SUCCESS
;
1063 memset(&ds
, 0, sizeof(ds
));
1065 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IAADDR
);
1066 for ( ; oc
!= NULL
; oc
= oc
->next
) {
1067 addr
= dmalloc(sizeof(*addr
), MDL
);
1069 log_error("Out of memory allocating "
1070 "address structure.");
1071 return ISC_R_NOMEMORY
;
1072 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
1073 options
, NULL
, &global_scope
,
1077 addr
->address
.len
= 16;
1078 memcpy(addr
->address
.iabuf
, ds
.data
, 16);
1079 addr
->starts
= cur_time
;
1080 addr
->preferred_life
= getULong(ds
.data
+ 16);
1081 addr
->max_life
= getULong(ds
.data
+ 20);
1083 log_debug("RCV: | | X-- IAADDR %s",
1084 piaddr(addr
->address
));
1085 log_debug("RCV: | | | X-- Preferred lifetime %u.",
1086 addr
->preferred_life
);
1087 log_debug("RCV: | | | X-- Max lifetime %u.",
1091 * RFC 3315 section 22.6 says we must discard
1092 * addresses whose pref is later than valid.
1094 if ((addr
->preferred_life
> addr
->max_life
)) {
1095 log_debug("RCV: | | | !-- INVALID lifetimes, "
1096 "IAADDR discarded. Check your "
1097 "server configuration.");
1099 data_string_forget(&ds
, MDL
);
1104 * Fortunately this is the last recursion in the
1108 if (!option_state_allocate(&addr
->options
,
1110 log_error("Out of memory allocating "
1111 "IAADDR option state.");
1113 data_string_forget(&ds
, MDL
);
1114 return ISC_R_NOMEMORY
;
1117 if (!parse_option_buffer(addr
->options
,
1120 &dhcpv6_universe
)) {
1121 log_error("Corrupt IAADDR options.");
1122 option_state_dereference(&addr
->options
,
1125 data_string_forget(&ds
, MDL
);
1126 return DHCP_R_BADPARSE
;
1130 data_string_forget(&ds
, MDL
);
1132 if (addr
->options
!= NULL
) {
1133 log_debug("RCV: | | | X-- [Options]");
1135 /* Get the status code if the return value
1136 * indicates an error or the status code
1137 * indicates no address toss the address
1139 code
= STATUS_Success
;
1140 rval
= dhc6_check_status(ISC_R_SUCCESS
,
1143 if (rval
!= ISC_R_SUCCESS
) {
1144 log_debug("RCV: | | | X-- Status code"
1145 " issue, IAADDR discarded.");
1146 option_state_dereference(&addr
->options
,
1154 paddr
= &addr
->next
;
1156 log_error("Invalid IAADDR option cache.");
1158 data_string_forget(&ds
, MDL
);
1159 return ISC_R_UNEXPECTED
;
1162 delete_option(&dhcpv6_universe
, options
, D6O_IAADDR
);
1164 return ISC_R_SUCCESS
;
1168 dhc6_parse_prefixes(struct dhc6_addr
**ppfx
, struct packet
*packet
,
1169 struct option_state
*options
)
1171 struct data_string ds
;
1172 struct option_cache
*oc
;
1173 struct dhc6_addr
*pfx
;
1174 isc_result_t rval
= ISC_R_SUCCESS
;
1177 memset(&ds
, 0, sizeof(ds
));
1179 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IAPREFIX
);
1180 for ( ; oc
!= NULL
; oc
= oc
->next
) {
1181 pfx
= dmalloc(sizeof(*pfx
), MDL
);
1183 log_error("Out of memory allocating "
1184 "prefix structure.");
1185 return ISC_R_NOMEMORY
;
1186 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
1187 options
, NULL
, &global_scope
,
1191 pfx
->preferred_life
= getULong(ds
.data
);
1192 pfx
->max_life
= getULong(ds
.data
+ 4);
1193 pfx
->plen
= getUChar(ds
.data
+ 8);
1194 pfx
->address
.len
= 16;
1195 memcpy(pfx
->address
.iabuf
, ds
.data
+ 9, 16);
1196 pfx
->starts
= cur_time
;
1198 log_debug("RCV: | | X-- IAPREFIX %s/%d",
1199 piaddr(pfx
->address
), (int)pfx
->plen
);
1200 log_debug("RCV: | | | X-- Preferred lifetime %u.",
1201 pfx
->preferred_life
);
1202 log_debug("RCV: | | | X-- Max lifetime %u.",
1205 /* Sanity check over the prefix length */
1206 if ((pfx
->plen
< 4) || (pfx
->plen
> 128)) {
1207 log_debug("RCV: | | | !-- INVALID prefix "
1208 "length, IAPREFIX discarded. "
1209 "Check your server configuration.");
1211 data_string_forget(&ds
, MDL
);
1215 * RFC 3633 section 10 says we must discard
1216 * prefixes whose pref is later than valid.
1218 if ((pfx
->preferred_life
> pfx
->max_life
)) {
1219 log_debug("RCV: | | | !-- INVALID lifetimes, "
1220 "IAPREFIX discarded. Check your "
1221 "server configuration.");
1223 data_string_forget(&ds
, MDL
);
1228 * Fortunately this is the last recursion in the
1232 if (!option_state_allocate(&pfx
->options
,
1234 log_error("Out of memory allocating "
1235 "IAPREFIX option state.");
1237 data_string_forget(&ds
, MDL
);
1238 return ISC_R_NOMEMORY
;
1241 if (!parse_option_buffer(pfx
->options
,
1244 &dhcpv6_universe
)) {
1245 log_error("Corrupt IAPREFIX options.");
1246 option_state_dereference(&pfx
->options
,
1249 data_string_forget(&ds
, MDL
);
1250 return DHCP_R_BADPARSE
;
1254 data_string_forget(&ds
, MDL
);
1256 if (pfx
->options
!= NULL
) {
1257 log_debug("RCV: | | | X-- [Options]");
1259 /* Get the status code if the return value
1260 * indicates an error or the status code
1261 * indicates no prefix toss the prefix
1263 code
= STATUS_Success
;
1264 rval
= dhc6_check_status(ISC_R_SUCCESS
,
1267 if (rval
!= ISC_R_SUCCESS
) {
1268 log_debug("RCV: | | | X-- Status code"
1269 " issue IAPREFIX discarded.");
1270 option_state_dereference(&pfx
->options
,
1280 log_error("Invalid IAPREFIX option cache.");
1282 data_string_forget(&ds
, MDL
);
1283 return ISC_R_UNEXPECTED
;
1286 delete_option(&dhcpv6_universe
, options
, D6O_IAPREFIX
);
1288 return ISC_R_SUCCESS
;
1291 /* Clean up a lease object, deallocate all its parts, and set it to NULL. */
1293 dhc6_lease_destroy(struct dhc6_lease
**src
, const char *file
, int line
)
1295 struct dhc6_ia
*ia
, *nia
;
1296 struct dhc6_lease
*lease
;
1298 if (src
== NULL
|| *src
== NULL
) {
1299 log_error("Attempt to destroy null lease.");
1304 data_string_forget(&lease
->server_id
, file
, line
);
1305 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= nia
) {
1308 dhc6_ia_destroy(&ia
, file
, line
);
1311 if (lease
->options
!= NULL
)
1312 option_state_dereference(&lease
->options
, file
, line
);
1314 dfree(lease
, file
, line
);
1319 * Traverse the addresses list, and destroy their contents, and NULL the
1323 dhc6_ia_destroy(struct dhc6_ia
**src
, const char *file
, int line
)
1325 struct dhc6_addr
*addr
, *naddr
;
1328 if (src
== NULL
|| *src
== NULL
) {
1329 log_error("Attempt to destroy null IA.");
1334 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= naddr
) {
1337 if (addr
->options
!= NULL
)
1338 option_state_dereference(&addr
->options
, file
, line
);
1340 dfree(addr
, file
, line
);
1343 if (ia
->options
!= NULL
)
1344 option_state_dereference(&ia
->options
, file
, line
);
1346 dfree(ia
, file
, line
);
1351 * For a given lease, insert it into the tail of the lease list. Upon
1352 * finding a duplicate by server id, remove it and take over its position.
1355 insert_lease(struct dhc6_lease
**head
, struct dhc6_lease
*new)
1357 while (*head
!= NULL
) {
1358 if ((*head
)->server_id
.len
== new->server_id
.len
&&
1359 memcmp((*head
)->server_id
.data
, new->server_id
.data
,
1360 new->server_id
.len
) == 0) {
1361 new->next
= (*head
)->next
;
1362 dhc6_lease_destroy(head
, MDL
);
1366 head
= &(*head
)->next
;
1375 * \brief Determine a score for a lease. We use this to
1376 * compare and choose leases if we receive multiple candidates.
1378 * We originally started with scores of 50 for a binding and 100 for
1379 * an address. This would select multiple adresses over multiple
1380 * bindings. As part of the 7550 work I've changed this to be
1381 * 10000 for a binding, 100 for an address and 1 for an option.
1382 * This will cause us to choose a lease with more bindings over
1383 * a lease with less bindings but more addresses which seems
1384 * to be the best selection criteria to me.
1385 * In theory we could end up with a lease with enough addresses
1386 * or options being better but at 100 to 1 I don't think it's likely.
1388 * \param client = the state of the entire client
1389 * \param lease = the lease to score.
1391 * \retrun the score of the lease
1394 /* The scores for individual items. */
1395 #ifdef USE_ORIGINAL_CLIENT_LEASE_WEIGHTS
1396 #define SCORE_BINDING 50
1397 #define SCORE_ADDRESS 100
1399 #define SCORE_BINDING 10000
1400 #define SCORE_ADDRESS 100
1403 #define SCORE_OPTION 1
1404 /* We need a lease with at least 1 binding and 1 address */
1405 #define SCORE_MIN (SCORE_BINDING + SCORE_ADDRESS)
1408 dhc6_score_lease(struct client_state
*client
, struct dhc6_lease
*lease
)
1411 struct dhc6_addr
*addr
;
1412 struct option
**req
;
1416 return lease
->score
;
1418 lease
->score
= SCORE_OPTION
;
1420 /* If this lease lacks a required option, dump it. */
1421 /* XXX: we should be able to cache the failure... */
1422 req
= client
->config
->required_options
;
1424 for (i
= 0 ; req
[i
] != NULL
; i
++) {
1425 if (lookup_option(&dhcpv6_universe
, lease
->options
,
1426 req
[i
]->code
) == NULL
) {
1428 return lease
->score
;
1433 /* If this lease contains a requested option, improve its score. */
1434 req
= client
->config
->requested_options
;
1436 for (i
= 0 ; req
[i
] != NULL
; i
++) {
1437 if (lookup_option(&dhcpv6_universe
, lease
->options
,
1438 req
[i
]->code
) != NULL
)
1439 lease
->score
+= SCORE_OPTION
;
1443 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
1444 lease
->score
+= SCORE_BINDING
;
1446 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
1447 lease
->score
+= SCORE_ADDRESS
;
1451 return lease
->score
;
1455 * start_init6() kicks off the process, transmitting a packet and
1456 * scheduling a retransmission event.
1459 start_init6(struct client_state
*client
)
1463 log_debug("PRC: Soliciting for leases (INIT).");
1464 client
->state
= S_INIT
;
1466 /* Initialize timers, RFC3315 section 17.1.2. */
1467 client
->IRT
= SOL_TIMEOUT
* 100;
1468 client
->MRT
= SOL_MAX_RT
* 100;
1470 /* Default is 0 (no max) but -1 changes this. */
1474 client
->MRD
= client
->config
->timeout
;
1476 dhc6_retrans_init(client
);
1479 * RFC3315 section 17.1.2 goes out of its way:
1480 * Also, the first RT MUST be selected to be strictly greater than IRT
1481 * by choosing RAND to be strictly greater than 0.
1483 /* if RAND < 0 then RAND = -RAND */
1484 if (client
->RT
<= client
->IRT
)
1485 client
->RT
= client
->IRT
+ (client
->IRT
- client
->RT
);
1486 /* if RAND == 0 then RAND = 1 */
1487 if (client
->RT
<= client
->IRT
)
1488 client
->RT
= client
->IRT
+ 1;
1490 client
->v6_handler
= init_handler
;
1493 * RFC3315 section 17.1.2 says we MUST start the first packet
1494 * between 0 and SOL_MAX_DELAY seconds. The good news is
1495 * SOL_MAX_DELAY is 1.
1497 tv
.tv_sec
= cur_tv
.tv_sec
;
1498 tv
.tv_usec
= cur_tv
.tv_usec
;
1499 tv
.tv_usec
+= (random() % (SOL_MAX_DELAY
* 100)) * 10000;
1500 if (tv
.tv_usec
>= 1000000) {
1502 tv
.tv_usec
-= 1000000;
1504 add_timeout(&tv
, do_init6
, client
, NULL
, NULL
);
1511 * start_info_request6() kicks off the process, transmitting an info
1512 * request packet and scheduling a retransmission event.
1515 start_info_request6(struct client_state
*client
)
1519 log_debug("PRC: Requesting information (INIT).");
1520 client
->state
= S_INIT
;
1522 /* Initialize timers, RFC3315 section 18.1.5. */
1523 client
->IRT
= INF_TIMEOUT
* 100;
1524 client
->MRT
= INF_MAX_RT
* 100;
1526 /* Default is 0 (no max) but -1 changes this. */
1530 client
->MRD
= client
->config
->timeout
;
1532 dhc6_retrans_init(client
);
1534 client
->v6_handler
= info_request_handler
;
1537 * RFC3315 section 18.1.5 says we MUST start the first packet
1538 * between 0 and INF_MAX_DELAY seconds. The good news is
1539 * INF_MAX_DELAY is 1.
1541 tv
.tv_sec
= cur_tv
.tv_sec
;
1542 tv
.tv_usec
= cur_tv
.tv_usec
;
1543 tv
.tv_usec
+= (random() % (INF_MAX_DELAY
* 100)) * 10000;
1544 if (tv
.tv_usec
>= 1000000) {
1546 tv
.tv_usec
-= 1000000;
1548 add_timeout(&tv
, do_info_request6
, client
, NULL
, NULL
);
1555 * start_confirm6() kicks off an "init-reboot" version of the process, at
1556 * startup to find out if old bindings are 'fair' and at runtime whenever
1557 * a link cycles state we'll eventually want to do this.
1560 start_confirm6(struct client_state
*client
)
1564 /* If there is no active lease, there is nothing to check. */
1565 if ((client
->active_lease
== NULL
) ||
1566 !active_prefix(client
) ||
1567 client
->active_lease
->released
||
1568 !unexpired_address_in_lease(client
->active_lease
)) {
1569 dhc6_lease_destroy(&client
->active_lease
, MDL
);
1570 start_init6(client
);
1574 log_debug("PRC: Confirming active lease (INIT-REBOOT).");
1575 client
->state
= S_REBOOTING
;
1577 /* Initialize timers, RFC3315 section 17.1.3. */
1578 client
->IRT
= CNF_TIMEOUT
* 100;
1579 client
->MRT
= CNF_MAX_RT
* 100;
1581 client
->MRD
= CNF_MAX_RD
;
1583 dhc6_retrans_init(client
);
1585 client
->v6_handler
= reply_handler
;
1588 * RFC3315 section 18.1.2 says we MUST start the first packet
1589 * between 0 and CNF_MAX_DELAY seconds. The good news is
1590 * CNF_MAX_DELAY is 1.
1592 tv
.tv_sec
= cur_tv
.tv_sec
;
1593 tv
.tv_usec
= cur_tv
.tv_usec
;
1594 tv
.tv_usec
+= (random() % (CNF_MAX_DELAY
* 100)) * 10000;
1595 if (tv
.tv_usec
>= 1000000) {
1597 tv
.tv_usec
-= 1000000;
1600 /* We do a rebind instead of a confirm if the user
1601 * is requesting PDs or previously requesed PDs or
1602 * increased the number of NAs or TAs they want
1603 * Confirms don't tell us if PDs are still on-link and
1604 * we won't add new IAs on a confirm.
1607 if ((wanted_ia_pd
!= 0) ||
1608 (dhc6_count_ia(client
->active_lease
, D6O_IA_PD
) != 0) ||
1609 (dhc6_count_ia(client
->active_lease
, D6O_IA_NA
) < wanted_ia_na
) ||
1610 (dhc6_count_ia(client
->active_lease
, D6O_IA_TA
) < wanted_ia_ta
)) {
1611 client
->state
= S_REBINDING
;
1612 client
->refresh_type
= DHCPV6_REBIND
;
1613 add_timeout(&tv
, do_refresh6
, client
, NULL
, NULL
);
1615 add_timeout(&tv
, do_confirm6
, client
, NULL
, NULL
);
1619 * check_timing6() check on the timing for sending a v6 message
1620 * and then do the basic initialization for a v6 message.
1622 #define CHK_TIM_SUCCESS 0
1623 #define CHK_TIM_MRC_EXCEEDED 1
1624 #define CHK_TIM_MRD_EXCEEDED 2
1625 #define CHK_TIM_ALLOC_FAILURE 3
1628 check_timing6 (struct client_state
*client
, u_int8_t msg_type
,
1629 char *msg_str
, struct dhc6_lease
*lease
,
1630 struct data_string
*ds
)
1632 struct timeval elapsed
;
1635 * Start_time starts at the first transmission.
1637 if (client
->txcount
== 0) {
1638 client
->start_time
.tv_sec
= cur_tv
.tv_sec
;
1639 client
->start_time
.tv_usec
= cur_tv
.tv_usec
;
1640 } else if ((client
->MRC
!= 0) && (client
->txcount
> client
->MRC
)) {
1641 log_info("Max retransmission count exceeded.");
1642 return(CHK_TIM_MRC_EXCEEDED
);
1645 /* elapsed = cur - start */
1646 elapsed
.tv_sec
= cur_tv
.tv_sec
- client
->start_time
.tv_sec
;
1647 elapsed
.tv_usec
= cur_tv
.tv_usec
- client
->start_time
.tv_usec
;
1648 if (elapsed
.tv_usec
< 0) {
1649 elapsed
.tv_sec
-= 1;
1650 elapsed
.tv_usec
+= 1000000;
1653 /* Check if finished (-1 argument). */
1654 if ((client
->MRD
!= 0) && (elapsed
.tv_sec
>= client
->MRD
)) {
1655 log_info("Max retransmission duration exceeded.");
1656 return(CHK_TIM_MRD_EXCEEDED
);
1659 memset(ds
, 0, sizeof(*ds
));
1660 if (!buffer_allocate(&(ds
->buffer
), 4, MDL
)) {
1661 log_error("Unable to allocate memory for %s.", msg_str
);
1662 return(CHK_TIM_ALLOC_FAILURE
);
1664 ds
->data
= ds
->buffer
->data
;
1667 ds
->buffer
->data
[0] = msg_type
;
1668 memcpy(ds
->buffer
->data
+ 1, client
->dhcpv6_transaction_id
, 3);
1670 /* Form an elapsed option. */
1671 /* Maximum value is 65535 1/100s coded as 0xffff. */
1672 if ((elapsed
.tv_sec
< 0) || (elapsed
.tv_sec
> 655) ||
1673 ((elapsed
.tv_sec
== 655) && (elapsed
.tv_usec
> 350000))) {
1674 client
->elapsed
= 0xffff;
1676 client
->elapsed
= elapsed
.tv_sec
* 100;
1677 client
->elapsed
+= elapsed
.tv_usec
/ 10000;
1680 if (client
->elapsed
== 0)
1681 log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str
);
1683 log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str
,
1684 (unsigned)client
->elapsed
);
1686 client
->elapsed
= htons(client
->elapsed
);
1688 make_client6_options(client
, &client
->sent_options
, lease
, msg_type
);
1690 return(CHK_TIM_SUCCESS
);
1695 * \brief Create an iaid from information from the client.
1697 * \param client = the state of the entire client
1698 * \param ia = the ia to fill in
1699 * \param idx = index of the ia in case we are doing multiples
1700 * \param len = length of the base IA (4 for TA, 12 for NA & PD)
1702 * \return ISC_R_SUCCESS - all is well continue, any other return indicates
1703 * an error and the packet should be tossed
1707 dhc6_create_iaid(struct client_state
*client
,
1708 struct data_string
*ia
,
1712 int start_idx
, copy_len
;
1714 memset(ia
, 0, sizeof(*ia
));
1715 if (!buffer_allocate(&ia
->buffer
, len
, MDL
)) {
1716 return (ISC_R_NOMEMORY
);
1718 ia
->data
= ia
->buffer
->data
;
1722 * A simple IAID is the last 4 bytes
1723 * of the hardware address.
1725 if (client
->interface
->hw_address
.hlen
> 4) {
1726 start_idx
= client
->interface
->hw_address
.hlen
- 4;
1730 copy_len
= client
->interface
->hw_address
.hlen
;
1732 memcpy(ia
->buffer
->data
,
1733 client
->interface
->hw_address
.hbuf
+ start_idx
,
1736 ia
->buffer
->data
[3] += idx
;
1738 return (ISC_R_SUCCESS
);
1743 * \brief Add bare IA_NAs, IA_TAs or IA_PDs to the packet we are building.
1745 * Attempt to add the number of bare IAs indicated by wanted to
1746 * the packet. As we have already added a number of IAs based
1747 * on what is in the current lease after we create an IAID we check
1748 * it against the current lease and skip any that are already in use.
1750 * \param client = the state of the entire client
1751 * \param packet = the packet we are building and where we
1752 * shall append the IA_NA, IA_TA or IA_PDs we create
1753 * \param wanted = the number of IA_NA, IA_TA or IA_PDs we want to create
1754 * \param ia_type = the type of the IAs we want to create: NA, TA or PD.
1756 * \return ISC_R_SUCCESS - all is well continue, any other return indicates
1757 * an error and the packet should be tossed
1760 dhc6_bare_ia_xx(struct client_state
*client
,
1761 struct data_string
*packet
,
1765 struct dhc6_ia
*old_ia
;
1766 struct data_string ia
;
1771 struct option
*type_option
;
1773 /* figure out what type of option we are working with */
1776 type_string
= "IA_NA";
1777 type_option
= ia_na_option
;
1781 type_string
= "IA_TA";
1782 type_option
= ia_ta_option
;
1786 type_string
= "IA_PD";
1787 type_option
= ia_pd_option
;
1789 if (prefix_len_hint
> 0) {
1790 len
+= IASUBOPT_PD_LEN
;
1795 return (ISC_R_FAILURE
);
1798 for (i
= 0; wanted
!= 0; i
++) {
1799 rval
= dhc6_create_iaid(client
, &ia
, i
, len
);
1800 if (rval
!= ISC_R_SUCCESS
) {
1801 log_error("Unable to allocate memory for %s.",
1806 /* If we are already using this IAID, skip it and try again */
1807 if ((client
->active_lease
!= NULL
) &&
1808 ((old_ia
= find_ia(client
->active_lease
->bindings
,
1810 (char *)ia
.buffer
->data
)) != NULL
)) {
1811 data_string_forget(&ia
, MDL
);
1815 /* We have a good IAID, log it */
1816 log_debug("XMT: X-- %s %s",
1817 type_string
, print_hex_1(4, ia
.buffer
->data
, 55));
1819 /* If we are requesting an NA or a PD we also want to add
1820 * the renew and rebind times we are requesting.
1822 if (ia_type
!= D6O_IA_TA
) {
1823 t1
= client
->config
->requested_lease
/ 2;
1825 putULong(ia
.buffer
->data
+ 4, t1
);
1826 putULong(ia
.buffer
->data
+ 8, t2
);
1828 log_debug("XMT: | X-- Request renew in +%u",
1830 log_debug("XMT: | X-- Request rebind in +%u",
1834 if (ia_type
== D6O_IA_PD
&& prefix_len_hint
> 0) {
1835 unsigned char *ptr
= ia
.buffer
->data
+ IA_NA_OFFSET
;
1836 putUShort(ptr
, D6O_IAPREFIX
);
1838 putUShort(ptr
, IASUBOPT_PD_LEN
);
1840 putUChar(ptr
+ IASUBOPT_PD_PREFLEN_OFFSET
,
1842 log_debug("XMT: | | X-- Request prefix ::/%u.",
1846 /* and append it to the packet */
1847 append_option(packet
, &dhcpv6_universe
, type_option
, &ia
);
1848 data_string_forget(&ia
, MDL
);
1850 /* decrement the number of IAs we want */
1854 return (ISC_R_SUCCESS
);
1858 * do_init6() marshals and transmits a solicit.
1861 do_init6(void *input
)
1863 struct client_state
*client
;
1864 struct dhc6_ia
*old_ia
;
1865 struct dhc6_addr
*old_addr
;
1866 struct data_string ds
;
1867 struct data_string ia
;
1868 struct data_string addr
;
1876 * In RFC3315 section 17.1.2, the retransmission timer is
1877 * used as the selecting timer.
1879 if (client
->advertised_leases
!= NULL
) {
1880 start_selecting6(client
);
1884 switch(check_timing6(client
, DHCPV6_SOLICIT
, "Solicit", NULL
, &ds
)) {
1885 case CHK_TIM_MRC_EXCEEDED
:
1886 case CHK_TIM_ALLOC_FAILURE
:
1888 case CHK_TIM_MRD_EXCEEDED
:
1889 client
->state
= S_STOPPED
;
1890 if (client
->active_lease
!= NULL
) {
1891 dhc6_lease_destroy(&client
->active_lease
, MDL
);
1892 client
->active_lease
= NULL
;
1894 /* Stop if and only if this is the last client. */
1895 if (stopping_finished())
1901 * Fetch any configured 'sent' options (includes DUID) in wire format.
1903 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
,
1904 NULL
, client
->sent_options
, &global_scope
,
1907 /* Use a specific handler with rapid-commit. */
1908 if (lookup_option(&dhcpv6_universe
, client
->sent_options
,
1909 D6O_RAPID_COMMIT
) != NULL
) {
1910 client
->v6_handler
= rapid_commit_handler
;
1914 for (i
= 0; i
< wanted_ia_na
; i
++) {
1916 * XXX: maybe the IA_NA('s) should be put into the sent_options
1917 * cache. They'd have to be pulled down as they also contain
1918 * different option caches in the same universe...
1920 if (dhc6_create_iaid(client
, &ia
, i
, 12) != ISC_R_SUCCESS
) {
1921 log_error("Unable to allocate memory for IA_NA.");
1922 data_string_forget(&ds
, MDL
);
1926 t1
= client
->config
->requested_lease
/ 2;
1928 putULong(ia
.buffer
->data
+ 4, t1
);
1929 putULong(ia
.buffer
->data
+ 8, t2
);
1931 log_debug("XMT: X-- IA_NA %s",
1932 print_hex_1(4, ia
.buffer
->data
, 55));
1933 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1
);
1934 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2
);
1936 if ((client
->active_lease
!= NULL
) &&
1937 ((old_ia
= find_ia(client
->active_lease
->bindings
,
1939 (char *)ia
.buffer
->data
)) != NULL
)) {
1941 * For each address in the old IA_NA,
1942 * request a binding.
1944 memset(&addr
, 0, sizeof(addr
));
1945 for (old_addr
= old_ia
->addrs
; old_addr
!= NULL
;
1946 old_addr
= old_addr
->next
) {
1947 if (old_addr
->address
.len
!= 16) {
1948 log_error("Invalid IPv6 address "
1950 "Ignoring. (%s:%d)",
1951 old_addr
->address
.len
,
1956 if (!buffer_allocate(&addr
.buffer
, 24, MDL
)) {
1957 log_error("Unable to allocate memory "
1959 data_string_forget(&ia
, MDL
);
1960 data_string_forget(&ds
, MDL
);
1963 addr
.data
= addr
.buffer
->data
;
1966 memcpy(addr
.buffer
->data
,
1967 old_addr
->address
.iabuf
,
1970 t1
= client
->config
->requested_lease
;
1972 putULong(addr
.buffer
->data
+ 16, t1
);
1973 putULong(addr
.buffer
->data
+ 20, t2
);
1975 log_debug("XMT: | X-- Request address %s.",
1976 piaddr(old_addr
->address
));
1977 log_debug("XMT: | | X-- Request "
1980 log_debug("XMT: | | X-- Request valid "
1984 append_option(&ia
, &dhcpv6_universe
,
1988 data_string_forget(&addr
, MDL
);
1992 append_option(&ds
, &dhcpv6_universe
, ia_na_option
, &ia
);
1993 data_string_forget(&ia
, MDL
);
1997 for (i
= 0; i
< wanted_ia_ta
; i
++) {
1999 * XXX: maybe the IA_TA('s) should be put into the sent_options
2000 * cache. They'd have to be pulled down as they also contain
2001 * different option caches in the same universe...
2003 if (dhc6_create_iaid(client
, &ia
, i
, 4) != ISC_R_SUCCESS
) {
2004 log_error("Unable to allocate memory for IA_TA.");
2005 data_string_forget(&ds
, MDL
);
2009 log_debug("XMT: X-- IA_TA %s",
2010 print_hex_1(4, ia
.buffer
->data
, 55));
2012 if ((client
->active_lease
!= NULL
) &&
2013 ((old_ia
= find_ia(client
->active_lease
->bindings
,
2015 (char *)ia
.buffer
->data
)) != NULL
)) {
2017 * For each address in the old IA_TA,
2018 * request a binding.
2020 memset(&addr
, 0, sizeof(addr
));
2021 for (old_addr
= old_ia
->addrs
; old_addr
!= NULL
;
2022 old_addr
= old_addr
->next
) {
2023 if (old_addr
->address
.len
!= 16) {
2024 log_error("Invalid IPv6 address "
2026 "Ignoring. (%s:%d)",
2027 old_addr
->address
.len
,
2032 if (!buffer_allocate(&addr
.buffer
, 24, MDL
)) {
2033 log_error("Unable to allocate memory "
2035 data_string_forget(&ia
, MDL
);
2036 data_string_forget(&ds
, MDL
);
2039 addr
.data
= addr
.buffer
->data
;
2042 memcpy(addr
.buffer
->data
,
2043 old_addr
->address
.iabuf
,
2046 t1
= client
->config
->requested_lease
;
2048 putULong(addr
.buffer
->data
+ 16, t1
);
2049 putULong(addr
.buffer
->data
+ 20, t2
);
2051 log_debug("XMT: | X-- Request address %s.",
2052 piaddr(old_addr
->address
));
2053 log_debug("XMT: | | X-- Request "
2056 log_debug("XMT: | | X-- Request valid "
2060 append_option(&ia
, &dhcpv6_universe
,
2064 data_string_forget(&addr
, MDL
);
2068 append_option(&ds
, &dhcpv6_universe
, ia_ta_option
, &ia
);
2069 data_string_forget(&ia
, MDL
);
2073 for (i
= 0; i
< wanted_ia_pd
; i
++) {
2075 * XXX: maybe the IA_PD('s) should be put into the sent_options
2076 * cache. They'd have to be pulled down as they also contain
2077 * different option caches in the same universe...
2079 memset(&ia
, 0, sizeof(ia
));
2080 if (dhc6_create_iaid(client
, &ia
, i
, 12) != ISC_R_SUCCESS
) {
2081 log_error("Unable to allocate memory for IA_PD.");
2082 data_string_forget(&ds
, MDL
);
2086 t1
= client
->config
->requested_lease
/ 2;
2088 putULong(ia
.buffer
->data
+ 4, t1
);
2089 putULong(ia
.buffer
->data
+ 8, t2
);
2091 log_debug("XMT: X-- IA_PD %s",
2092 print_hex_1(4, ia
.buffer
->data
, 55));
2093 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1
);
2094 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2
);
2096 if ((client
->active_lease
!= NULL
) &&
2097 ((old_ia
= find_ia(client
->active_lease
->bindings
,
2099 (char *)ia
.buffer
->data
)) != NULL
)) {
2101 * For each prefix in the old IA_PD,
2102 * request a binding.
2104 memset(&addr
, 0, sizeof(addr
));
2105 for (old_addr
= old_ia
->addrs
; old_addr
!= NULL
;
2106 old_addr
= old_addr
->next
) {
2107 if (old_addr
->address
.len
!= 16) {
2108 log_error("Invalid IPv6 prefix, "
2109 "Ignoring. (%s:%d)",
2114 if (!buffer_allocate(&addr
.buffer
, 25, MDL
)) {
2115 log_error("Unable to allocate memory "
2117 data_string_forget(&ia
, MDL
);
2118 data_string_forget(&ds
, MDL
);
2121 addr
.data
= addr
.buffer
->data
;
2124 t1
= client
->config
->requested_lease
;
2126 putULong(addr
.buffer
->data
, t1
);
2127 putULong(addr
.buffer
->data
+ 4, t2
);
2129 putUChar(addr
.buffer
->data
+ 8,
2131 memcpy(addr
.buffer
->data
+ 9,
2132 old_addr
->address
.iabuf
,
2135 log_debug("XMT: | X-- Request prefix %s/%u.",
2136 piaddr(old_addr
->address
),
2137 (unsigned) old_addr
->plen
);
2138 log_debug("XMT: | | X-- Request "
2141 log_debug("XMT: | | X-- Request valid "
2145 append_option(&ia
, &dhcpv6_universe
,
2149 data_string_forget(&addr
, MDL
);
2151 } else if (prefix_len_hint
> 0) {
2152 memset(&addr
, 0, sizeof(addr
));
2153 if (!buffer_allocate(&addr
.buffer
, 25, MDL
)) {
2154 log_error("Unable to allocate memory "
2156 data_string_forget(&ia
, MDL
);
2157 data_string_forget(&ds
, MDL
);
2161 addr
.data
= addr
.buffer
->data
;
2164 putUChar(addr
.buffer
->data
+ 8, prefix_len_hint
);
2165 log_debug("XMT: | | X-- Request prefix ::/%u.",
2167 append_option(&ia
, &dhcpv6_universe
, iaprefix_option
,
2169 data_string_forget(&addr
, MDL
);
2172 append_option(&ds
, &dhcpv6_universe
, ia_pd_option
, &ia
);
2173 data_string_forget(&ia
, MDL
);
2176 /* Transmit and wait. */
2178 log_info("XMT: Solicit on %s, interval %ld0ms.",
2179 client
->name
? client
->name
: client
->interface
->name
,
2180 (long int)client
->RT
);
2182 send_ret
= send_packet6(client
->interface
,
2183 ds
.data
, ds
.len
, &DHCPv6DestAddr
);
2184 if (send_ret
!= ds
.len
) {
2185 log_error("dhc6: send_packet6() sent %d of %d bytes",
2189 data_string_forget(&ds
, MDL
);
2192 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2193 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2194 if (tv
.tv_usec
>= 1000000) {
2196 tv
.tv_usec
-= 1000000;
2198 add_timeout(&tv
, do_init6
, client
, NULL
, NULL
);
2200 dhc6_retrans_advance(client
);
2203 /* do_info_request6() marshals and transmits an information-request. */
2205 do_info_request6(void *input
)
2207 struct client_state
*client
;
2208 struct data_string ds
;
2214 switch(check_timing6(client
, DHCPV6_INFORMATION_REQUEST
,
2215 "Info-Request", NULL
, &ds
)) {
2216 case CHK_TIM_MRC_EXCEEDED
:
2217 case CHK_TIM_ALLOC_FAILURE
:
2219 case CHK_TIM_MRD_EXCEEDED
:
2221 case CHK_TIM_SUCCESS
:
2225 /* Fetch any configured 'sent' options (includes DUID) in wire format.
2227 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
,
2228 NULL
, client
->sent_options
, &global_scope
,
2231 /* Transmit and wait. */
2233 log_info("XMT: Info-Request on %s, interval %ld0ms.",
2234 client
->name
? client
->name
: client
->interface
->name
,
2235 (long int)client
->RT
);
2237 send_ret
= send_packet6(client
->interface
,
2238 ds
.data
, ds
.len
, &DHCPv6DestAddr
);
2239 if (send_ret
!= ds
.len
) {
2240 log_error("dhc6: send_packet6() sent %d of %d bytes",
2244 data_string_forget(&ds
, MDL
);
2247 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2248 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2249 if (tv
.tv_usec
>= 1000000) {
2251 tv
.tv_usec
-= 1000000;
2253 add_timeout(&tv
, do_info_request6
, client
, NULL
, NULL
);
2255 dhc6_retrans_advance(client
);
2258 /* do_confirm6() creates a Confirm packet and transmits it. This function
2259 * is called on every timeout to (re)transmit.
2262 do_confirm6(void *input
)
2264 struct client_state
*client
;
2265 struct data_string ds
;
2266 int send_ret
, added
;
2271 if (client
->active_lease
== NULL
)
2272 log_fatal("Impossible condition at %s:%d.", MDL
);
2274 /* In section 17.1.3, it is said:
2276 * If the client receives no responses before the message
2277 * transmission process terminates, as described in section 14,
2278 * the client SHOULD continue to use any IP addresses, using the
2279 * last known lifetimes for those addresses, and SHOULD continue
2280 * to use any other previously obtained configuration parameters.
2282 * So if confirm times out, we go active.
2284 * XXX: Should we reduce all IA's t1 to 0, so that we renew and
2285 * stick there until we get a reply?
2288 switch(check_timing6(client
, DHCPV6_CONFIRM
, "Confirm",
2289 client
->active_lease
, &ds
)) {
2290 case CHK_TIM_MRC_EXCEEDED
:
2291 case CHK_TIM_MRD_EXCEEDED
:
2292 start_bound(client
);
2294 case CHK_TIM_ALLOC_FAILURE
:
2296 case CHK_TIM_SUCCESS
:
2300 /* Fetch any configured 'sent' options (includes DUID') in wire format.
2302 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
, NULL
,
2303 client
->sent_options
, &global_scope
,
2308 dhc6_add_ia_na(client
, &ds
, client
->active_lease
,
2309 DHCPV6_CONFIRM
, 0, &added
) != ISC_R_SUCCESS
) {
2310 data_string_forget(&ds
, MDL
);
2314 dhc6_add_ia_ta(client
, &ds
, client
->active_lease
,
2315 DHCPV6_CONFIRM
, 0, &added
) != ISC_R_SUCCESS
) {
2316 data_string_forget(&ds
, MDL
);
2320 /* Transmit and wait. */
2322 log_info("XMT: Confirm on %s, interval %ld0ms.",
2323 client
->name
? client
->name
: client
->interface
->name
,
2324 (long int)client
->RT
);
2326 send_ret
= send_packet6(client
->interface
, ds
.data
, ds
.len
,
2328 if (send_ret
!= ds
.len
) {
2329 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2333 data_string_forget(&ds
, MDL
);
2336 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2337 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2338 if (tv
.tv_usec
>= 1000000) {
2340 tv
.tv_usec
-= 1000000;
2342 add_timeout(&tv
, do_confirm6
, client
, NULL
, NULL
);
2344 dhc6_retrans_advance(client
);
2348 * Release addresses.
2351 start_release6(struct client_state
*client
)
2353 /* Cancel any pending transmissions */
2354 cancel_timeout(do_confirm6
, client
);
2355 cancel_timeout(do_select6
, client
);
2356 cancel_timeout(do_refresh6
, client
);
2357 cancel_timeout(do_release6
, client
);
2358 cancel_timeout(do_decline6
, client
);
2359 client
->state
= S_STOPPED
;
2362 * It is written: "The client MUST NOT use any of the addresses it
2363 * is releasing as the source address in the Release message or in
2364 * any subsequently transmitted message." So unconfigure now.
2366 unconfigure6(client
, "RELEASE6");
2368 /* Note this in the lease file. */
2369 if (client
->active_lease
== NULL
)
2371 client
->active_lease
->released
= ISC_TRUE
;
2372 write_client6_lease(client
, client
->active_lease
, 0, 1);
2374 /* Set timers per RFC3315 section 18.1.6. */
2375 client
->IRT
= REL_TIMEOUT
* 100;
2377 client
->MRC
= REL_MAX_RC
;
2380 dhc6_retrans_init(client
);
2381 client
->v6_handler
= reply_handler
;
2383 do_release6(client
);
2386 * do_release6() creates a Release packet and transmits it.
2389 do_release6(void *input
)
2391 struct client_state
*client
;
2392 struct data_string ds
;
2393 int send_ret
, added
;
2398 if ((client
->active_lease
== NULL
) || !active_prefix(client
))
2401 switch(check_timing6(client
, DHCPV6_RELEASE
, "Release",
2402 client
->active_lease
, &ds
)) {
2403 case CHK_TIM_MRC_EXCEEDED
:
2404 case CHK_TIM_ALLOC_FAILURE
:
2405 case CHK_TIM_MRD_EXCEEDED
:
2407 case CHK_TIM_SUCCESS
:
2412 * Don't use unicast as we don't know if we still have an
2413 * available address with enough scope.
2416 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
, NULL
,
2417 client
->sent_options
, &global_scope
,
2420 /* Append IA's (but don't release temporary addresses). */
2422 dhc6_add_ia_na(client
, &ds
, client
->active_lease
,
2423 DHCPV6_RELEASE
, 0, &added
) != ISC_R_SUCCESS
) {
2424 data_string_forget(&ds
, MDL
);
2428 dhc6_add_ia_pd(client
, &ds
, client
->active_lease
,
2429 DHCPV6_RELEASE
, 0, &added
) != ISC_R_SUCCESS
) {
2430 data_string_forget(&ds
, MDL
);
2434 /* Transmit and wait. */
2435 log_info("XMT: Release on %s, interval %ld0ms.",
2436 client
->name
? client
->name
: client
->interface
->name
,
2437 (long int)client
->RT
);
2439 send_ret
= send_packet6(client
->interface
, ds
.data
, ds
.len
,
2441 if (send_ret
!= ds
.len
) {
2442 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2446 data_string_forget(&ds
, MDL
);
2449 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2450 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2451 if (tv
.tv_usec
>= 1000000) {
2453 tv
.tv_usec
-= 1000000;
2455 add_timeout(&tv
, do_release6
, client
, NULL
, NULL
);
2456 dhc6_retrans_advance(client
);
2460 dhc6_lease_destroy(&client
->active_lease
, MDL
);
2461 client
->active_lease
= NULL
;
2462 if (stopping_finished())
2466 /* status_log() just puts a status code into displayable form and logs it
2470 status_log(int code
, const char *scope
, const char *additional
, int len
)
2472 const char *msg
= NULL
;
2475 case STATUS_Success
:
2479 case STATUS_UnspecFail
:
2483 case STATUS_NoAddrsAvail
:
2484 msg
= "NoAddrsAvail";
2487 case STATUS_NoBinding
:
2491 case STATUS_NotOnLink
:
2495 case STATUS_UseMulticast
:
2496 msg
= "UseMulticast";
2499 case STATUS_NoPrefixAvail
:
2500 msg
= "NoPrefixAvail";
2509 log_info("%s status code %s: %s", scope
, msg
,
2511 (const unsigned char *)additional
, 50));
2513 log_info("%s status code %s.", scope
, msg
);
2516 /* Acquire a status code.
2519 dhc6_get_status_code(struct option_state
*options
, unsigned *code
,
2520 struct data_string
*msg
)
2522 struct option_cache
*oc
;
2523 struct data_string ds
;
2524 isc_result_t rval
= ISC_R_SUCCESS
;
2526 if ((options
== NULL
) || (code
== NULL
))
2527 return DHCP_R_INVALIDARG
;
2529 if ((msg
!= NULL
) && (msg
->len
!= 0))
2530 return DHCP_R_INVALIDARG
;
2532 memset(&ds
, 0, sizeof(ds
));
2534 /* Assume success if there is no option. */
2535 *code
= STATUS_Success
;
2537 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_STATUS_CODE
);
2539 evaluate_option_cache(&ds
, NULL
, NULL
, NULL
, options
,
2540 NULL
, &global_scope
, oc
, MDL
)) {
2542 log_error("Invalid status code length %d.", ds
.len
);
2543 rval
= DHCP_R_FORMERR
;
2545 *code
= getUShort(ds
.data
);
2547 if ((msg
!= NULL
) && (ds
.len
> 2)) {
2548 data_string_copy(msg
, &ds
, MDL
);
2553 data_string_forget(&ds
, MDL
);
2557 return ISC_R_NOTFOUND
;
2560 /* Look at status codes in an advertise, and reform the return value.
2563 dhc6_check_status(isc_result_t rval
, struct option_state
*options
,
2564 const char *scope
, unsigned *code
)
2566 struct data_string msg
;
2567 isc_result_t status
;
2569 if ((scope
== NULL
) || (code
== NULL
))
2570 return DHCP_R_INVALIDARG
;
2572 /* If we don't find a code, we assume success. */
2573 *code
= STATUS_Success
;
2575 /* If there is no options cache, then there is no code. */
2576 if (options
!= NULL
) {
2577 memset(&msg
, 0, sizeof(msg
));
2578 status
= dhc6_get_status_code(options
, code
, &msg
);
2580 if (status
== ISC_R_SUCCESS
) {
2581 status_log(*code
, scope
, (char *)msg
.data
, msg
.len
);
2582 data_string_forget(&msg
, MDL
);
2584 if (*code
!= STATUS_Success
)
2585 rval
= ISC_R_FAILURE
;
2587 } else if (status
!= ISC_R_NOTFOUND
)
2594 /* Determine if this packet could provide usable information.
2595 * We check the status codes at the top level and at the IA level,
2596 * IAADDRS have already been checked in the leaseify step and any with
2597 * a bad format or status code that wasn't success have been dropped.
2599 * leaseify has also already removed any IAs for which the top level status
2600 * code or the IA status code indicated no addresses or prefixes were
2604 dhc6_check_advertise(struct dhc6_lease
*lease
)
2607 isc_result_t rval
= ISC_R_SUCCESS
;
2608 int have_addrs
= ISC_FALSE
;
2611 int got_na
= 0, got_ta
= 0, got_pd
= 0;
2613 rval
= dhc6_check_status(rval
, lease
->options
, "message", &code
);
2615 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
2616 switch (ia
->ia_type
) {
2630 log_error("dhc6_check_advertise: no type.");
2631 return ISC_R_FAILURE
;
2633 /* Currently we toss packets if we have an error getting a
2634 * status code or if the status code isn't success, so
2635 * no need to loop through the addresses */
2636 rval
= dhc6_check_status(rval
, ia
->options
, scope
, &code
);
2637 if (rval
!= ISC_R_SUCCESS
)
2640 /* We don't need to check status on IAADDRS here as we already
2641 * did it as part of the leaseify step and tossed bad IAADDRS.
2642 * We are just checking to see if we have any addrs.
2643 * Should we check the addr itself for usability?
2645 if (ia
->addrs
!= NULL
) {
2646 have_addrs
= ISC_TRUE
;
2650 /* If we didn't get some addrs or the user required us to
2651 * get all of the requested IAs and we didn't return an error
2653 if ((have_addrs
!= ISC_TRUE
) ||
2654 ((require_all_ias
!= 0) &&
2655 ((got_na
< wanted_ia_na
) ||
2656 (got_ta
< wanted_ia_ta
) ||
2657 (got_pd
< wanted_ia_pd
))))
2658 rval
= ISC_R_ADDRNOTAVAIL
;
2663 /* status code <-> action matrix for the client in INIT state
2664 * (rapid/commit). Returns always false as no action is defined.
2666 static isc_boolean_t
2667 dhc6_init_action(struct client_state
*client
, isc_result_t
*rvalp
,
2671 log_fatal("Impossible condition at %s:%d.", MDL
);
2673 if (client
== NULL
) {
2674 *rvalp
= DHCP_R_INVALIDARG
;
2678 if (*rvalp
== ISC_R_SUCCESS
)
2681 /* No possible action in any case... */
2685 /* status code <-> action matrix for the client in SELECT state
2686 * (request/reply). Returns true if action was taken (and the
2687 * packet should be ignored), or false if no action was taken.
2689 static isc_boolean_t
2690 dhc6_select_action(struct client_state
*client
, isc_result_t
*rvalp
,
2693 struct dhc6_lease
*lease
;
2697 log_fatal("Impossible condition at %s:%d.", MDL
);
2699 if (client
== NULL
) {
2700 *rvalp
= DHCP_R_INVALIDARG
;
2705 if (rval
== ISC_R_SUCCESS
)
2709 /* We may have an earlier failure status code (so no
2710 * success rval), and a success code now. This
2711 * doesn't upgrade the rval to success, but it does
2712 * mean we take no action here.
2714 case STATUS_Success
:
2715 /* Gimpy server, or possibly an attacker. */
2716 case STATUS_NoBinding
:
2717 case STATUS_UseMulticast
:
2718 /* Take no action. */
2721 /* If the server can't deal with us, either try the
2722 * next advertised server, or continue retrying if there
2726 case STATUS_UnspecFail
:
2727 if (client
->advertised_leases
!= NULL
) {
2728 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
2729 client
->selected_lease
= NULL
;
2731 start_selecting6(client
);
2734 } else /* Take no action - continue to retry. */
2737 /* If the server has no addresses, try other servers if
2738 * we got some, otherwise go to INIT to hope for more
2741 case STATUS_NoAddrsAvail
:
2742 case STATUS_NoPrefixAvail
:
2743 if (client
->state
== S_REBOOTING
)
2746 if (client
->selected_lease
== NULL
)
2747 log_fatal("Impossible case at %s:%d.", MDL
);
2749 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
2750 client
->selected_lease
= NULL
;
2752 if (client
->advertised_leases
!= NULL
)
2753 start_selecting6(client
);
2755 start_init6(client
);
2759 /* If we got a NotOnLink from a Confirm, then we're not
2760 * on link. Kill the old-active binding and start over.
2762 * If we got a NotOnLink from our Request, something weird
2763 * happened. Start over from scratch anyway.
2765 case STATUS_NotOnLink
:
2766 if (client
->state
== S_REBOOTING
) {
2767 if (client
->active_lease
== NULL
)
2768 log_fatal("Impossible case at %s:%d.", MDL
);
2770 dhc6_lease_destroy(&client
->active_lease
, MDL
);
2772 if (client
->selected_lease
== NULL
)
2773 log_fatal("Impossible case at %s:%d.", MDL
);
2775 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
2776 client
->selected_lease
= NULL
;
2778 while (client
->advertised_leases
!= NULL
) {
2779 lease
= client
->advertised_leases
;
2780 client
->advertised_leases
= lease
->next
;
2782 dhc6_lease_destroy(&lease
, MDL
);
2786 start_init6(client
);
2794 dhc6_withdraw_lease(struct client_state
*client
)
2797 struct dhc6_addr
*addr
;
2799 if ((client
== NULL
) || (client
->active_lease
== NULL
))
2802 for (ia
= client
->active_lease
->bindings
; ia
!= NULL
;
2804 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
2805 addr
->max_life
= addr
->preferred_life
= 0;
2809 /* Perform expiry. */
2813 /* status code <-> action matrix for the client in BOUND state
2814 * (request/reply). Returns true if action was taken (and the
2815 * packet should be ignored), or false if no action was taken.
2817 static isc_boolean_t
2818 dhc6_reply_action(struct client_state
*client
, isc_result_t
*rvalp
,
2824 log_fatal("Impossible condition at %s:%d.", MDL
);
2826 if (client
== NULL
) {
2827 *rvalp
= DHCP_R_INVALIDARG
;
2832 if (rval
== ISC_R_SUCCESS
)
2836 /* It's possible an earlier status code set rval to a failure
2837 * code, and we've encountered a later success.
2839 case STATUS_Success
:
2840 /* In "refreshes" (where we get replies), we probably
2841 * still have a valid lease. So "take no action" and
2842 * the upper levels will keep retrying until the lease
2843 * expires (or we rebind).
2845 case STATUS_UnspecFail
:
2846 /* For unknown codes...it's a soft (retryable) error. */
2850 /* The server is telling us to use a multicast address, so
2851 * we have to delete the unicast option from the active
2852 * lease, then allow retransmission to occur normally.
2853 * (XXX: It might be preferable in this case to retransmit
2854 * sooner than the current interval, but for now we don't.)
2856 case STATUS_UseMulticast
:
2857 if (client
->active_lease
!= NULL
)
2858 delete_option(&dhcp_universe
,
2859 client
->active_lease
->options
,
2863 /* "When the client receives a NotOnLink status from the
2864 * server in response to a Request, the client can either
2865 * re-issue the Request without specifying any addresses
2866 * or restart the DHCP server discovery process."
2868 * This is strange. If competing server evaluation is
2869 * useful (and therefore in the protocol), then why would
2870 * a client's first reaction be to request from the same
2871 * server on a different link? Surely you'd want to
2872 * re-evaluate your server selection.
2874 * Well, I guess that's the answer.
2876 case STATUS_NotOnLink
:
2877 /* In this case, we need to rescind all current active
2878 * bindings (just 'expire' them all normally, if early).
2879 * They're no use to us on the wrong link. Then head back
2880 * to init, redo server selection and get new addresses.
2882 dhc6_withdraw_lease(client
);
2885 /* "If the status code is NoAddrsAvail, the client has
2886 * received no usable addresses in the IA and may choose
2887 * to try obtaining addresses for the IA from another
2890 case STATUS_NoAddrsAvail
:
2891 case STATUS_NoPrefixAvail
:
2892 /* Head back to init, keeping any active bindings (!). */
2893 start_init6(client
);
2896 /* - sends a Request message if the IA contained a Status
2897 * Code option with the NoBinding status (and does not
2898 * send any additional Renew/Rebind messages)
2900 case STATUS_NoBinding
:
2901 if (client
->advertised_leases
!= NULL
)
2902 log_fatal("Impossible condition at %s:%d.", MDL
);
2904 client
->advertised_leases
=
2905 dhc6_dup_lease(client
->active_lease
, MDL
);
2906 start_selecting6(client
);
2913 /* status code <-> action matrix for the client in STOPPED state
2914 * (release/decline). Returns true if action was taken (and the
2915 * packet should be ignored), or false if no action was taken.
2916 * NoBinding is translated into Success.
2918 static isc_boolean_t
2919 dhc6_stop_action(struct client_state
*client
, isc_result_t
*rvalp
,
2925 log_fatal("Impossible condition at %s:%d.", MDL
);
2927 if (client
== NULL
) {
2928 *rvalp
= DHCP_R_INVALIDARG
;
2933 if (rval
== ISC_R_SUCCESS
)
2937 /* It's possible an earlier status code set rval to a failure
2938 * code, and we've encountered a later success.
2940 case STATUS_Success
:
2941 /* For unknown codes...it's a soft (retryable) error. */
2942 case STATUS_UnspecFail
:
2946 /* NoBinding is not an error */
2947 case STATUS_NoBinding
:
2948 if (rval
== ISC_R_FAILURE
)
2949 *rvalp
= ISC_R_SUCCESS
;
2952 /* Should not happen */
2953 case STATUS_NoAddrsAvail
:
2954 case STATUS_NoPrefixAvail
:
2958 case STATUS_NotOnLink
:
2961 /* The server is telling us to use a multicast address, so
2962 * we have to delete the unicast option from the active
2963 * lease, then allow retransmission to occur normally.
2964 * (XXX: It might be preferable in this case to retransmit
2965 * sooner than the current interval, but for now we don't.)
2967 case STATUS_UseMulticast
:
2968 if (client
->active_lease
!= NULL
)
2969 delete_option(&dhcp_universe
,
2970 client
->active_lease
->options
,
2978 static isc_boolean_t
2979 dhc6_decline_action(struct client_state
*client
, isc_result_t
*rvalp
,
2985 log_fatal("Impossible condition at %s:%d.", MDL
);
2987 if (client
== NULL
) {
2988 *rvalp
= DHCP_R_INVALIDARG
;
2993 if (rval
== ISC_R_SUCCESS
) {
2998 case STATUS_UseMulticast
:
2999 /* The server is telling us to use a multicast address, so
3000 * we have to delete the unicast option from the active
3001 * lease, then allow retransmission to occur normally.
3002 * (XXX: It might be preferable in this case to retransmit
3003 * sooner than the current interval, but for now we don't.)
3005 if (client
->active_lease
!= NULL
)
3006 delete_option(&dhcp_universe
,
3007 client
->active_lease
->options
,
3011 /* Anything else is basically meaningless */
3019 /* Look at a new and old lease, and make sure the new information is not
3020 * losing us any state.
3023 dhc6_check_reply(struct client_state
*client
, struct dhc6_lease
*new)
3025 isc_boolean_t (*action
)(struct client_state
*,
3026 isc_result_t
*, unsigned);
3028 isc_result_t rval
= ISC_R_SUCCESS
;
3032 int have_addrs
= ISC_FALSE
;
3033 int got_na
= 0, got_ta
= 0, got_pd
= 0;
3035 if ((client
== NULL
) || (new == NULL
))
3036 return DHCP_R_INVALIDARG
;
3038 switch (client
->state
) {
3040 action
= dhc6_init_action
;
3045 action
= dhc6_select_action
;
3050 action
= dhc6_reply_action
;
3054 action
= dhc6_stop_action
;
3058 action
= dhc6_decline_action
;
3062 log_fatal("Impossible condition at %s:%d.", MDL
);
3063 return ISC_R_CANCELED
;
3066 /* If there is a code to extract, and if there is some
3067 * action to take based on that code, then take the action
3068 * and do not continue.
3070 rval
= dhc6_check_status(rval
, new->options
, "message", &code
);
3071 if (action(client
, &rval
, code
))
3072 return ISC_R_CANCELED
;
3074 for (ia
= new->bindings
; ia
!= NULL
; ia
= ia
->next
) {
3075 switch (ia
->ia_type
) {
3089 log_error("dhc6_check_reply: no type.");
3090 return DHCP_R_INVALIDARG
;
3092 rval
= dhc6_check_status(rval
, ia
->options
, scope
, &code
);
3094 if (action(client
, &rval
, code
))
3095 return ISC_R_CANCELED
;
3097 if (ia
->addrs
!= NULL
) {
3098 have_addrs
= ISC_TRUE
;
3102 /* A Confirm->Reply is unsuitable for comparison to the old lease. */
3103 if (client
->state
== S_REBOOTING
)
3106 /* We expect the lease to have at least one address and if
3107 * required all of the requested IAs if not flag it as
3108 * NoAddrs and call the action routine to try again.
3110 * Currently we don't completely handle TAs in all cases
3111 * so we don't check them for requires. I've left the
3112 * check in and commented it as I eventually do want
3113 * us to check for TAs as well. SAR
3115 if ((have_addrs
!= ISC_TRUE
) ||
3116 ((require_all_ias
!= 0) &&
3117 ((got_na
< wanted_ia_na
) ||
3118 /*(got_ta < wanted_ia_ta) ||*/
3119 (got_pd
< wanted_ia_pd
)))) {
3120 rval
= ISC_R_FAILURE
;
3121 if (action(client
, &rval
, STATUS_NoAddrsAvail
) == ISC_TRUE
) {
3122 return ISC_R_CANCELED
;
3126 /* No old lease in rapid-commit. */
3127 if (client
->state
== S_INIT
)
3130 switch (client
->state
) {
3132 /* Compare the new lease with the selected lease to make
3133 * sure there is no risky business.
3135 nscore
= dhc6_score_lease(client
, new);
3136 sscore
= dhc6_score_lease(client
, client
->selected_lease
);
3137 if ((client
->advertised_leases
!= NULL
) &&
3138 (nscore
< (sscore
/ 2))) {
3139 /* XXX: An attacker might reply this way to make
3140 * XXX: sure we latch onto their configuration.
3141 * XXX: We might want to ignore the packet and
3142 * XXX: schedule re-selection at the next timeout?
3144 log_error("PRC: BAIT AND SWITCH detected. Score of "
3145 "supplied lease (%d) is substantially "
3146 "smaller than the advertised score (%d). "
3147 "Trying other servers.",
3150 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
3151 client
->selected_lease
= NULL
;
3153 start_selecting6(client
);
3155 return ISC_R_CANCELED
;
3161 /* This leaves one RFC3315 status check unimplemented:
3163 * - sends a Renew/Rebind if the IA is not in the Reply
3166 * We rely on the scheduling system to note that the IA has
3167 * not left Renewal/Rebinding/whatever since it still carries
3168 * old times from the last successful binding. So this is
3169 * implemented actually, just not explicitly.
3175 /* Nothing critical to do at this stage. */
3179 log_fatal("REALLY impossible condition at %s:%d.", MDL
);
3180 return ISC_R_CANCELED
;
3186 /* While in init state, we only collect advertisements. If there happens
3187 * to be an advertisement with a preference option of 255, that's an
3188 * automatic exit. Otherwise, we collect advertisements until our timeout
3189 * expires (client->RT).
3192 init_handler(struct packet
*packet
, struct client_state
*client
)
3194 struct dhc6_lease
*lease
;
3196 /* In INIT state, we send solicits, we only expect to get
3197 * advertises (rapid commit has its own handler).
3199 if (packet
->dhcpv6_msg_type
!= DHCPV6_ADVERTISE
)
3202 /* RFC3315 section 15.3 validation (same as 15.10 since we
3203 * always include a client id).
3205 if (!valid_reply(packet
, client
)) {
3206 log_error("Invalid Advertise - rejecting.");
3210 lease
= dhc6_leaseify(packet
, client
);
3212 /* Out of memory or corrupt packet condition...hopefully a temporary
3213 * problem. Returning now makes us try to retransmit later.
3218 if (dhc6_check_advertise(lease
) != ISC_R_SUCCESS
) {
3219 log_debug("PRC: Lease failed to satisfy.");
3220 dhc6_lease_destroy(&lease
, MDL
);
3224 int lease_score
= dhc6_score_lease(client
, lease
);
3225 #ifdef ENFORCE_DHCPV6_CLIENT_REQUIRE
3226 if (lease_score
== 0) {
3227 log_debug("RCV:Advertised lease scored 0, toss it.");
3228 dhc6_lease_destroy(&lease
, MDL
);
3233 insert_lease(&client
->advertised_leases
, lease
);
3235 /* According to RFC3315 section 17.1.2, the client MUST wait for
3236 * the first RT before selecting a lease. But on the 400th RT,
3237 * we dont' want to wait the full timeout if we finally get an
3238 * advertise. We could probably wait a second, but ohwell,
3239 * RFC3315 doesn't say so.
3241 * If the lease is highest possible preference, 255, RFC3315 claims
3242 * we should continue immediately even on the first RT. We probably
3243 * should not if the advertise contains less than one IA and address.
3245 if ((client
->txcount
> 1) ||
3246 ((lease
->pref
== 255) && (lease_score
> SCORE_MIN
))) {
3247 log_debug("RCV: Advertisement immediately selected.");
3248 cancel_timeout(do_init6
, client
);
3249 start_selecting6(client
);
3251 log_debug("RCV: Advertisement recorded.");
3254 /* info_request_handler() accepts a Reply to an Info-request.
3257 info_request_handler(struct packet
*packet
, struct client_state
*client
)
3259 isc_result_t check_status
;
3262 if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
3265 /* RFC3315 section 15.10 validation (same as 15.3 since we
3266 * always include a client id).
3268 if (!valid_reply(packet
, client
)) {
3269 log_error("Invalid Reply - rejecting.");
3273 check_status
= dhc6_check_status(ISC_R_SUCCESS
, packet
->options
,
3276 if (check_status
!= ISC_R_SUCCESS
) {
3277 /* If no action was taken, but there is an error, then
3278 * we wait for a retransmission.
3280 if (check_status
!= ISC_R_CANCELED
)
3284 /* We're done retransmitting at this point. */
3285 cancel_timeout(do_info_request6
, client
);
3287 /* Action was taken, so now that we've torn down our scheduled
3288 * retransmissions, return.
3290 if (check_status
== ISC_R_CANCELED
)
3293 /* Cleanup if a previous attempt to go bound failed. */
3294 if (client
->old_lease
!= NULL
) {
3295 dhc6_lease_destroy(&client
->old_lease
, MDL
);
3296 client
->old_lease
= NULL
;
3299 /* Cache options in the active_lease. */
3300 if (client
->active_lease
!= NULL
)
3301 client
->old_lease
= client
->active_lease
;
3302 client
->active_lease
= dmalloc(sizeof(struct dhc6_lease
), MDL
);
3303 if (client
->active_lease
== NULL
)
3304 log_fatal("Out of memory for v6 lease structure.");
3305 option_state_reference(&client
->active_lease
->options
,
3306 packet
->options
, MDL
);
3308 execute_statements_in_scope(NULL
, (struct packet
*)packet
, NULL
, client
,
3309 client
->active_lease
->options
,
3310 client
->active_lease
->options
,
3311 &global_scope
, client
->config
->on_receipt
,
3314 start_informed(client
);
3317 /* Specific version of init_handler() for rapid-commit.
3320 rapid_commit_handler(struct packet
*packet
, struct client_state
*client
)
3322 struct dhc6_lease
*lease
;
3323 isc_result_t check_status
;
3325 /* On ADVERTISE just fall back to the init_handler().
3327 if (packet
->dhcpv6_msg_type
== DHCPV6_ADVERTISE
) {
3328 init_handler(packet
, client
);
3330 } else if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
3333 /* RFC3315 section 15.10 validation (same as 15.3 since we
3334 * always include a client id).
3336 if (!valid_reply(packet
, client
)) {
3337 log_error("Invalid Reply - rejecting.");
3341 /* A rapid-commit option MUST be here. */
3342 if (lookup_option(&dhcpv6_universe
, packet
->options
,
3343 D6O_RAPID_COMMIT
) == 0) {
3344 log_error("Reply without Rapid-Commit - rejecting.");
3348 lease
= dhc6_leaseify(packet
, client
);
3350 /* Out of memory or corrupt packet condition...hopefully a temporary
3351 * problem. Returning now makes us try to retransmit later.
3356 check_status
= dhc6_check_reply(client
, lease
);
3357 if (check_status
!= ISC_R_SUCCESS
) {
3358 dhc6_lease_destroy(&lease
, MDL
);
3362 /* Jump to the selecting state. */
3363 cancel_timeout(do_init6
, client
);
3364 client
->state
= S_SELECTING
;
3366 /* Merge any bindings in the active lease (if there is one) into
3367 * the new active lease.
3369 dhc6_merge_lease(client
->active_lease
, lease
);
3371 /* Cleanup if a previous attempt to go bound failed. */
3372 if (client
->old_lease
!= NULL
) {
3373 dhc6_lease_destroy(&client
->old_lease
, MDL
);
3374 client
->old_lease
= NULL
;
3377 /* Make this lease active and BIND to it. */
3378 if (client
->active_lease
!= NULL
)
3379 client
->old_lease
= client
->active_lease
;
3380 client
->active_lease
= lease
;
3382 /* We're done with the ADVERTISEd leases, if any. */
3383 while(client
->advertised_leases
!= NULL
) {
3384 lease
= client
->advertised_leases
;
3385 client
->advertised_leases
= lease
->next
;
3387 dhc6_lease_destroy(&lease
, MDL
);
3390 start_bound(client
);
3393 /* Find the 'best' lease in the cache of advertised leases (usually). From
3394 * RFC3315 Section 17.1.3:
3396 * Upon receipt of one or more valid Advertise messages, the client
3397 * selects one or more Advertise messages based upon the following
3400 * - Those Advertise messages with the highest server preference value
3401 * are preferred over all other Advertise messages.
3403 * - Within a group of Advertise messages with the same server
3404 * preference value, a client MAY select those servers whose
3405 * Advertise messages advertise information of interest to the
3406 * client. For example, the client may choose a server that returned
3407 * an advertisement with configuration options of interest to the
3410 * - The client MAY choose a less-preferred server if that server has a
3411 * better set of advertised parameters, such as the available
3412 * addresses advertised in IAs.
3414 * Note that the first and third contradict each other. The third should
3415 * probably be taken to mean that the client should prefer answers that
3416 * offer bindings, even if that violates the preference rule.
3418 * The above also isn't deterministic where there are ties. So the final
3419 * tiebreaker we add, if all other values are equal, is to compare the
3420 * server identifiers and to select the numerically lower one.
3422 static struct dhc6_lease
*
3423 dhc6_best_lease(struct client_state
*client
, struct dhc6_lease
**head
)
3425 struct dhc6_lease
**rpos
, *rval
, **candp
, *cand
;
3428 if (head
== NULL
|| *head
== NULL
)
3433 rscore
= dhc6_score_lease(client
, rval
);
3434 candp
= &rval
->next
;
3437 log_debug("PRC: Considering best lease.");
3438 log_debug("PRC: X-- Initial candidate %s (s: %d, p: %u).",
3439 print_hex_1(rval
->server_id
.len
,
3440 rval
->server_id
.data
, 48),
3441 rscore
, (unsigned)rval
->pref
);
3443 for (; cand
!= NULL
; candp
= &cand
->next
, cand
= *candp
) {
3444 cscore
= dhc6_score_lease(client
, cand
);
3446 log_debug("PRC: X-- Candidate %s (s: %d, p: %u).",
3447 print_hex_1(cand
->server_id
.len
,
3448 cand
->server_id
.data
, 48),
3449 cscore
, (unsigned)cand
->pref
);
3451 /* Above you'll find quoted RFC3315 Section 17.1.3.
3453 * The third clause tells us to give up on leases that
3454 * have no bindings even if their preference is better.
3455 * So where our 'selected' lease's score is less than
3456 * SCORE_MIN (1 ia + 1 addr), choose any candidate >= SCORE_MIN.
3458 * The first clause tells us to make preference the primary
3459 * deciding factor. So if it's lower, reject, if it's
3462 * The second clause tells us where the preference is
3463 * equal, we should use 'our judgement' of what we like
3464 * to see in an advertisement primarily.
3466 * But there can still be a tie. To make this deterministic,
3467 * we compare the server identifiers and select the binary
3470 * Since server id's are unique in this list, there is
3471 * no further tie to break.
3473 if ((rscore
< SCORE_MIN
) && (cscore
>= SCORE_MIN
)) {
3474 log_debug("PRC: | X-- Selected, has bindings.");
3475 } else if (cand
->pref
< rval
->pref
) {
3476 log_debug("PRC: | X-- Rejected, lower preference.");
3478 } else if (cand
->pref
> rval
->pref
) {
3479 log_debug("PRC: | X-- Selected, higher preference.");
3480 } else if (cscore
> rscore
) {
3481 log_debug("PRC: | X-- Selected, equal preference, "
3483 } else if (cscore
< rscore
) {
3484 log_debug("PRC: | X-- Rejected, equal preference, "
3487 } else if ((cand
->server_id
.len
< rval
->server_id
.len
) ||
3488 ((cand
->server_id
.len
== rval
->server_id
.len
) &&
3489 (memcmp(cand
->server_id
.data
,
3490 rval
->server_id
.data
,
3491 cand
->server_id
.len
) < 0))) {
3492 log_debug("PRC: | X-- Selected, equal preference, "
3493 "equal score, binary lesser server ID.");
3495 log_debug("PRC: | X-- Rejected, equal preference, "
3496 "equal score, binary greater server ID.");
3505 /* Remove the selected lease from the chain. */
3511 /* Select a lease out of the advertised leases and setup state to try and
3512 * acquire that lease.
3515 start_selecting6(struct client_state
*client
)
3517 struct dhc6_lease
*lease
;
3519 if (client
->advertised_leases
== NULL
) {
3520 log_error("Can not enter DHCPv6 SELECTING state with no "
3521 "leases to select from!");
3525 log_debug("PRC: Selecting best advertised lease.");
3526 client
->state
= S_SELECTING
;
3528 lease
= dhc6_best_lease(client
, &client
->advertised_leases
);
3531 log_fatal("Impossible error at %s:%d.", MDL
);
3533 client
->selected_lease
= lease
;
3535 /* Set timers per RFC3315 section 18.1.1. */
3536 client
->IRT
= REQ_TIMEOUT
* 100;
3537 client
->MRT
= REQ_MAX_RT
* 100;
3538 client
->MRC
= REQ_MAX_RC
;
3541 dhc6_retrans_init(client
);
3543 client
->v6_handler
= reply_handler
;
3545 /* ("re")transmit the first packet. */
3549 /* Transmit a Request to select a lease offered in Advertisements. In
3550 * the event of failure, either move on to the next-best advertised lease,
3551 * or head back to INIT state if there are none.
3554 do_select6(void *input
)
3556 struct client_state
*client
;
3557 struct dhc6_lease
*lease
;
3558 struct data_string ds
;
3560 int send_ret
, added
;
3564 /* 'lease' is fewer characters to type. */
3565 lease
= client
->selected_lease
;
3566 if (lease
== NULL
|| lease
->bindings
== NULL
) {
3567 log_error("Illegal to attempt selection without selecting "
3572 switch(check_timing6(client
, DHCPV6_REQUEST
, "Request", lease
, &ds
)) {
3573 case CHK_TIM_MRC_EXCEEDED
:
3574 case CHK_TIM_MRD_EXCEEDED
:
3575 log_debug("PRC: Lease %s failed.",
3576 print_hex_1(lease
->server_id
.len
,
3577 lease
->server_id
.data
, 56));
3579 /* Get rid of the lease that timed/counted out. */
3580 dhc6_lease_destroy(&lease
, MDL
);
3581 client
->selected_lease
= NULL
;
3583 /* If there are more leases great. If not, get more. */
3584 if (client
->advertised_leases
!= NULL
)
3585 start_selecting6(client
);
3587 start_init6(client
);
3589 case CHK_TIM_ALLOC_FAILURE
:
3591 case CHK_TIM_SUCCESS
:
3595 /* Now make a packet that looks suspiciously like the one we
3596 * got from the server. But different.
3598 * XXX: I guess IAID is supposed to be something the client
3599 * indicates and uses as a key to its internal state. It is
3600 * kind of odd to ask the server for IA's whose IAID the client
3601 * did not manufacture. We first need a formal dhclient.conf
3602 * construct for the iaid, then we can delve into this matter
3603 * more properly. In the time being, this will work.
3606 /* Fetch any configured 'sent' options (includes DUID) in wire format.
3608 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
,
3609 NULL
, client
->sent_options
, &global_scope
,
3612 /* Now append any IA's, and within them any IAADDR/IAPREFIXs.
3613 * For each type of IA (na, ta, pd) we start with the ones for
3614 * which we already have addresses (dhc6_add_ia_xx) and then
3615 * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
3618 ((dhc6_add_ia_na(client
, &ds
, lease
, DHCPV6_REQUEST
,
3619 wanted_ia_na
, &added
) != ISC_R_SUCCESS
) ||
3620 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_na
- added
,
3621 D6O_IA_NA
) != ISC_R_SUCCESS
))) {
3622 data_string_forget(&ds
, MDL
);
3626 ((dhc6_add_ia_ta(client
, &ds
, lease
, DHCPV6_REQUEST
,
3627 wanted_ia_ta
, &added
) != ISC_R_SUCCESS
) ||
3628 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_ta
- added
,
3629 D6O_IA_TA
) != ISC_R_SUCCESS
))) {
3630 data_string_forget(&ds
, MDL
);
3634 ((dhc6_add_ia_pd(client
, &ds
, lease
, DHCPV6_REQUEST
,
3635 wanted_ia_pd
, &added
) != ISC_R_SUCCESS
) ||
3636 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_pd
- added
,
3637 D6O_IA_PD
) != ISC_R_SUCCESS
))) {
3638 data_string_forget(&ds
, MDL
);
3642 log_info("XMT: Request on %s, interval %ld0ms.",
3643 client
->name
? client
->name
: client
->interface
->name
,
3644 (long int)client
->RT
);
3646 send_ret
= send_packet6(client
->interface
,
3647 ds
.data
, ds
.len
, &DHCPv6DestAddr
);
3648 if (send_ret
!= ds
.len
) {
3649 log_error("dhc6: send_packet6() sent %d of %d bytes",
3653 data_string_forget(&ds
, MDL
);
3656 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
3657 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
3658 if (tv
.tv_usec
>= 1000000) {
3660 tv
.tv_usec
-= 1000000;
3662 add_timeout(&tv
, do_select6
, client
, NULL
, NULL
);
3664 dhc6_retrans_advance(client
);
3669 * \brief Count the number of IAs in the bindings
3671 * \param lease the lease to count
3672 * \param ia_type the type of the IA we wish to count
3674 * \return The number of IAs of the specified type we found
3677 dhc6_count_ia(struct dhc6_lease
*lease
, u_int16_t ia_type
)
3682 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
3683 if (ia
->ia_type
== ia_type
)
3684 /* bump the counter for the correct types */
3693 * \brief Add IA_NA information from the lease to the packet
3696 * Walk through the lease and for each IA_NA in the lease
3697 * and for each address in the IA_NA append that information
3698 * onto the packet-so-far. If wanted is 0 include all IA_NAs
3699 * in the lease if wanted is non-zero include only that many
3700 * IA_NAs (this may occur if sommebody restarts a client with
3701 * arugments for a smaller number of NAs than before).
3703 * \param client = the state of the entire client
3704 * \param packet = the packet we are building and where we
3705 * shall append the IA_NAs we create
3706 * \param lease = the current lease
3707 * \param message = the type of the packet
3708 * \param wanted = the number of IA_NAs to include in the packet
3709 * 0 means include all
3710 * \param added = the number of IA_NAs that were added to the packet
3712 * \return ISC_R_SUCCESS - all is well continue, any other return
3713 * indicates an error (most likely memory issues)
3714 * and the packet should be tossed.
3717 dhc6_add_ia_na(struct client_state
*client
, struct data_string
*packet
,
3718 struct dhc6_lease
*lease
, u_int8_t message
,
3719 int wanted
, int *added
)
3721 struct data_string iads
;
3722 struct data_string addrds
;
3723 struct dhc6_addr
*addr
;
3725 isc_result_t rval
= ISC_R_SUCCESS
;
3730 memset(&iads
, 0, sizeof(iads
));
3731 memset(&addrds
, 0, sizeof(addrds
));
3732 for (ia
= lease
->bindings
, i
= 0;
3733 ia
!= NULL
&& rval
== ISC_R_SUCCESS
&& (wanted
== 0 || i
< wanted
);
3735 if (ia
->ia_type
!= D6O_IA_NA
)
3738 /* Now that we know this is an NA bump the counter */
3741 if (!buffer_allocate(&iads
.buffer
, 12, MDL
)) {
3742 log_error("Unable to allocate memory for IA_NA.");
3743 rval
= ISC_R_NOMEMORY
;
3747 /* Copy the IAID into the packet buffer. */
3748 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
3749 iads
.data
= iads
.buffer
->data
;
3753 case DHCPV6_REQUEST
:
3757 t1
= client
->config
->requested_lease
/ 2;
3759 #if MAX_TIME > 0xffffffff
3760 if (t1
> 0xffffffff)
3762 if (t2
> 0xffffffff)
3765 putULong(iads
.buffer
->data
+ 4, t1
);
3766 putULong(iads
.buffer
->data
+ 8, t2
);
3768 log_debug("XMT: X-- IA_NA %s",
3769 print_hex_1(4, iads
.data
, 59));
3770 log_debug("XMT: | X-- Requested renew +%u",
3772 log_debug("XMT: | X-- Requested rebind +%u",
3776 case DHCPV6_CONFIRM
:
3777 case DHCPV6_RELEASE
:
3778 case DHCPV6_DECLINE
:
3779 /* Set t1 and t2 to zero; server will ignore them */
3780 memset(iads
.buffer
->data
+ 4, 0, 8);
3781 log_debug("XMT: X-- IA_NA %s",
3782 print_hex_1(4, iads
.buffer
->data
, 55));
3787 log_fatal("Impossible condition at %s:%d.", MDL
);
3790 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
3792 * Do not confirm expired addresses, do not request
3793 * expired addresses (but we keep them around for
3796 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
3799 if (addr
->address
.len
!= 16) {
3800 log_error("Illegal IPv6 address length (%d), "
3801 "ignoring. (%s:%d)",
3802 addr
->address
.len
, MDL
);
3806 if (!buffer_allocate(&addrds
.buffer
, 24, MDL
)) {
3807 log_error("Unable to allocate memory for "
3809 rval
= ISC_R_NOMEMORY
;
3813 addrds
.data
= addrds
.buffer
->data
;
3816 /* Copy the address into the packet buffer. */
3817 memcpy(addrds
.buffer
->data
, addr
->address
.iabuf
, 16);
3819 /* Copy in additional information as appropriate */
3821 case DHCPV6_REQUEST
:
3824 t1
= client
->config
->requested_lease
;
3826 putULong(addrds
.buffer
->data
+ 16, t1
);
3827 putULong(addrds
.buffer
->data
+ 20, t2
);
3829 log_debug("XMT: | | X-- IAADDR %s",
3830 piaddr(addr
->address
));
3831 log_debug("XMT: | | | X-- Preferred "
3832 "lifetime +%u", (unsigned)t1
);
3833 log_debug("XMT: | | | X-- Max lifetime +%u",
3838 case DHCPV6_CONFIRM
:
3840 * Set preferred and max life to zero,
3843 memset(addrds
.buffer
->data
+ 16, 0, 8);
3844 log_debug("XMT: | X-- Confirm Address %s",
3845 piaddr(addr
->address
));
3848 case DHCPV6_RELEASE
:
3849 /* Preferred and max life are irrelevant */
3850 memset(addrds
.buffer
->data
+ 16, 0, 8);
3851 log_debug("XMT: | X-- Release Address %s",
3852 piaddr(addr
->address
));
3855 case DHCPV6_DECLINE
:
3856 /* Preferred and max life are irrelevant */
3857 memset(addrds
.buffer
->data
+ 16, 0, 8);
3858 log_debug("XMT: | X-- Decline Address %s",
3859 piaddr(addr
->address
));
3863 log_fatal("Impossible condition at %s:%d.",
3867 append_option(&iads
, &dhcpv6_universe
, iaaddr_option
,
3869 data_string_forget(&addrds
, MDL
);
3873 * It doesn't make sense to make a request without an
3876 if (ia
->addrs
== NULL
) {
3877 log_debug("!!!: V IA_NA has no IAADDRs - removed.");
3878 rval
= ISC_R_FAILURE
;
3879 } else if (rval
== ISC_R_SUCCESS
) {
3880 log_debug("XMT: V IA_NA appended.");
3881 append_option(packet
, &dhcpv6_universe
, ia_na_option
,
3885 data_string_forget(&iads
, MDL
);
3888 if (rval
== ISC_R_SUCCESS
)
3896 * \brief Add IA_TA information from the lease to the packet
3899 * Walk through the lease and for each IA_TA in the lease
3900 * and for each address in the IA_TA append that information
3901 * onto the packet-so-far. If wanted is 0 include all IA_TAs
3902 * in the lease if wanted is non-zero include only that many
3903 * IA_TAs (this may occur if sommebody restarts a client with
3904 * arugments for a smaller number of TAs than before).
3906 * \param client = the state of the entire client
3907 * \param packet = the packet we are building and where we
3908 * shall append the IA_TAs we create
3909 * \param lease = the current lease
3910 * \param message = the type of the packet
3911 * \param wanted = the number of IA_TAs to include in the packet
3912 * 0 means include all
3913 * \param added = the number of IA_TAs that were added to the packet
3915 * \return ISC_R_SUCCESS - all is well continue, any other return
3916 * indicates an error (most likely memory issues)
3917 * and the packet should be tossed.
3920 dhc6_add_ia_ta(struct client_state
*client
, struct data_string
*packet
,
3921 struct dhc6_lease
*lease
, u_int8_t message
,
3922 int wanted
, int *added
)
3924 struct data_string iads
;
3925 struct data_string addrds
;
3926 struct dhc6_addr
*addr
;
3928 isc_result_t rval
= ISC_R_SUCCESS
;
3933 memset(&iads
, 0, sizeof(iads
));
3934 memset(&addrds
, 0, sizeof(addrds
));
3935 for (ia
= lease
->bindings
, i
= 0;
3936 ia
!= NULL
&& rval
== ISC_R_SUCCESS
&& (wanted
== 0 || i
< wanted
);
3938 if (ia
->ia_type
!= D6O_IA_TA
)
3941 /* Now that we know this is an TA bump the counter */
3944 if (!buffer_allocate(&iads
.buffer
, 4, MDL
)) {
3945 log_error("Unable to allocate memory for IA_TA.");
3946 rval
= ISC_R_NOMEMORY
;
3950 /* Copy the IAID into the packet buffer. */
3951 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
3952 iads
.data
= iads
.buffer
->data
;
3955 log_debug("XMT: X-- IA_TA %s",
3956 print_hex_1(4, iads
.buffer
->data
, 55));
3958 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
3960 * Do not confirm expired addresses, do not request
3961 * expired addresses (but we keep them around for
3964 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
3967 if (addr
->address
.len
!= 16) {
3968 log_error("Illegal IPv6 address length (%d), "
3969 "ignoring. (%s:%d)",
3970 addr
->address
.len
, MDL
);
3974 if (!buffer_allocate(&addrds
.buffer
, 24, MDL
)) {
3975 log_error("Unable to allocate memory for "
3977 rval
= ISC_R_NOMEMORY
;
3981 addrds
.data
= addrds
.buffer
->data
;
3984 /* Copy the address into the packet buffer. */
3985 memcpy(addrds
.buffer
->data
, addr
->address
.iabuf
, 16);
3987 /* Copy in additional information as appropriate */
3989 case DHCPV6_REQUEST
:
3992 t1
= client
->config
->requested_lease
;
3994 putULong(addrds
.buffer
->data
+ 16, t1
);
3995 putULong(addrds
.buffer
->data
+ 20, t2
);
3997 log_debug("XMT: | | X-- IAADDR %s",
3998 piaddr(addr
->address
));
3999 log_debug("XMT: | | | X-- Preferred "
4000 "lifetime +%u", (unsigned)t1
);
4001 log_debug("XMT: | | | X-- Max lifetime +%u",
4006 case DHCPV6_CONFIRM
:
4008 * Set preferred and max life to zero,
4011 memset(addrds
.buffer
->data
+ 16, 0, 8);
4012 log_debug("XMT: | X-- Confirm Address %s",
4013 piaddr(addr
->address
));
4016 case DHCPV6_RELEASE
:
4017 /* Preferred and max life are irrelevant */
4018 memset(addrds
.buffer
->data
+ 16, 0, 8);
4019 log_debug("XMT: | X-- Release Address %s",
4020 piaddr(addr
->address
));
4024 log_fatal("Impossible condition at %s:%d.",
4028 append_option(&iads
, &dhcpv6_universe
, iaaddr_option
,
4030 data_string_forget(&addrds
, MDL
);
4034 * It doesn't make sense to make a request without an
4037 if (ia
->addrs
== NULL
) {
4038 log_debug("!!!: V IA_TA has no IAADDRs - removed.");
4039 rval
= ISC_R_FAILURE
;
4040 } else if (rval
== ISC_R_SUCCESS
) {
4041 log_debug("XMT: V IA_TA appended.");
4042 append_option(packet
, &dhcpv6_universe
, ia_ta_option
,
4046 data_string_forget(&iads
, MDL
);
4049 if (rval
== ISC_R_SUCCESS
)
4057 * \brief Add IA_PD information from the lease to the packet
4060 * Walk through the lease and for each IA_PD in the lease
4061 * and for each address in the IA_PD append that information
4062 * onto the packet-so-far. If wanted is 0 include all IA_PDs
4063 * in the lease if wanted is non-zero include only that many
4064 * IA_PDs (this may occur if sommebody restarts a client with
4065 * arugments for a smaller number of PDs than before).
4067 * \param client = the state of the entire client
4068 * \param packet = the packet we are building and where we
4069 * shall append the IA_PDs we create
4070 * \param lease = the current lease
4071 * \param message = the type of the packet
4072 * \param wanted = the number of IA_PDs to include in the packet
4073 * 0 means include all
4074 * \param added = the number of IA_PDs that were added to the packet
4076 * \return ISC_R_SUCCESS - all is well continue, any other return
4077 * indicates an error (most likely memory issues)
4078 * and the packet should be tossed.
4081 dhc6_add_ia_pd(struct client_state
*client
, struct data_string
*packet
,
4082 struct dhc6_lease
*lease
, u_int8_t message
,
4083 int wanted
, int *added
)
4085 struct data_string iads
;
4086 struct data_string prefds
;
4087 struct dhc6_addr
*pref
;
4089 isc_result_t rval
= ISC_R_SUCCESS
;
4094 memset(&iads
, 0, sizeof(iads
));
4095 memset(&prefds
, 0, sizeof(prefds
));
4096 for (ia
= lease
->bindings
, i
= 0;
4097 ia
!= NULL
&& rval
== ISC_R_SUCCESS
&& (wanted
== 0 || i
< wanted
);
4099 if (ia
->ia_type
!= D6O_IA_PD
)
4102 /* Now that we know this is an PD bump the counter */
4105 if (!buffer_allocate(&iads
.buffer
, 12, MDL
)) {
4106 log_error("Unable to allocate memory for IA_PD.");
4107 rval
= ISC_R_NOMEMORY
;
4111 /* Copy the IAID into the packet buffer. */
4112 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
4113 iads
.data
= iads
.buffer
->data
;
4117 case DHCPV6_REQUEST
:
4121 t1
= client
->config
->requested_lease
/ 2;
4123 #if MAX_TIME > 0xffffffff
4124 if (t1
> 0xffffffff)
4126 if (t2
> 0xffffffff)
4129 putULong(iads
.buffer
->data
+ 4, t1
);
4130 putULong(iads
.buffer
->data
+ 8, t2
);
4132 log_debug("XMT: X-- IA_PD %s",
4133 print_hex_1(4, iads
.data
, 59));
4134 log_debug("XMT: | X-- Requested renew +%u",
4136 log_debug("XMT: | X-- Requested rebind +%u",
4140 case DHCPV6_RELEASE
:
4141 /* Set t1 and t2 to zero; server will ignore them */
4142 memset(iads
.buffer
->data
+ 4, 0, 8);
4143 log_debug("XMT: X-- IA_PD %s",
4144 print_hex_1(4, iads
.buffer
->data
, 55));
4149 log_fatal("Impossible condition at %s:%d.", MDL
);
4152 for (pref
= ia
->addrs
; pref
!= NULL
; pref
= pref
->next
) {
4154 * Do not confirm expired prefixes, do not request
4155 * expired prefixes (but we keep them around for
4158 if (pref
->flags
& DHC6_ADDR_EXPIRED
)
4161 if (pref
->address
.len
!= 16) {
4162 log_error("Illegal IPv6 prefix "
4163 "ignoring. (%s:%d)",
4168 if (pref
->plen
== 0) {
4169 log_info("Null IPv6 prefix, "
4170 "ignoring. (%s:%d)",
4174 if (!buffer_allocate(&prefds
.buffer
, 25, MDL
)) {
4175 log_error("Unable to allocate memory for "
4177 rval
= ISC_R_NOMEMORY
;
4181 prefds
.data
= prefds
.buffer
->data
;
4184 /* Copy the prefix into the packet buffer. */
4185 putUChar(prefds
.buffer
->data
+ 8, pref
->plen
);
4186 memcpy(prefds
.buffer
->data
+ 9,
4187 pref
->address
.iabuf
,
4190 /* Copy in additional information as appropriate */
4192 case DHCPV6_REQUEST
:
4195 t1
= client
->config
->requested_lease
;
4197 putULong(prefds
.buffer
->data
, t1
);
4198 putULong(prefds
.buffer
->data
+ 4, t2
);
4200 log_debug("XMT: | | X-- IAPREFIX %s/%u",
4201 piaddr(pref
->address
),
4202 (unsigned) pref
->plen
);
4203 log_debug("XMT: | | | X-- Preferred "
4204 "lifetime +%u", (unsigned)t1
);
4205 log_debug("XMT: | | | X-- Max lifetime +%u",
4210 case DHCPV6_RELEASE
:
4211 /* Preferred and max life are irrelevant */
4212 memset(prefds
.buffer
->data
, 0, 8);
4213 log_debug("XMT: | X-- Release Prefix %s/%u",
4214 piaddr(pref
->address
),
4215 (unsigned) pref
->plen
);
4219 log_fatal("Impossible condition at %s:%d.",
4223 append_option(&iads
, &dhcpv6_universe
,
4224 iaprefix_option
, &prefds
);
4225 data_string_forget(&prefds
, MDL
);
4229 * It doesn't make sense to make a request without an
4232 if (ia
->addrs
== NULL
) {
4233 log_debug("!!!: V IA_PD has no IAPREFIXs - removed.");
4234 rval
= ISC_R_FAILURE
;
4235 } else if (rval
== ISC_R_SUCCESS
) {
4236 log_debug("XMT: V IA_PD appended.");
4237 append_option(packet
, &dhcpv6_universe
,
4238 ia_pd_option
, &iads
);
4241 data_string_forget(&iads
, MDL
);
4244 if (rval
== ISC_R_SUCCESS
)
4250 /* stopping_finished() checks if there is a remaining work to do.
4252 static isc_boolean_t
4253 stopping_finished(void)
4255 struct interface_info
*ip
;
4256 struct client_state
*client
;
4258 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4259 for (client
= ip
-> client
; client
; client
= client
-> next
) {
4260 if (client
->state
!= S_STOPPED
)
4262 if (client
->active_lease
!= NULL
)
4269 /* reply_handler() accepts a Reply while we're attempting Select or Renew or
4270 * Rebind. Basically any Reply packet.
4273 reply_handler(struct packet
*packet
, struct client_state
*client
)
4275 struct dhc6_lease
*lease
;
4276 isc_result_t check_status
;
4278 if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
4281 /* RFC3315 section 15.10 validation (same as 15.3 since we
4282 * always include a client id).
4284 if (!valid_reply(packet
, client
)) {
4285 log_error("Invalid Reply - rejecting.");
4289 lease
= dhc6_leaseify(packet
, client
);
4291 /* Out of memory or corrupt packet condition...hopefully a temporary
4292 * problem. Returning now makes us try to retransmit later.
4297 check_status
= dhc6_check_reply(client
, lease
);
4298 if (check_status
!= ISC_R_SUCCESS
) {
4299 dhc6_lease_destroy(&lease
, MDL
);
4301 /* If no action was taken, but there is an error, then
4302 * we wait for a retransmission.
4304 if (check_status
!= ISC_R_CANCELED
)
4308 /* We're done retransmitting at this point. */
4309 cancel_timeout(do_confirm6
, client
);
4310 cancel_timeout(do_select6
, client
);
4311 cancel_timeout(do_refresh6
, client
);
4312 cancel_timeout(do_release6
, client
);
4313 cancel_timeout(do_decline6
, client
);
4315 /* If this is in response to a Release, clean up and return. */
4316 if (client
->state
== S_STOPPED
) {
4317 if (client
->active_lease
!= NULL
) {
4318 dhc6_lease_destroy(&client
->active_lease
, MDL
);
4319 client
->active_lease
= NULL
;
4320 /* We should never wait for nothing!? */
4321 if (stopping_finished()) {
4329 if (client
->state
== S_DECLINING
) {
4330 /* Weed thru the lease and delete all declined addresses.
4331 * Toss the lease if there aren't any addresses left */
4332 int live_cnt
= drop_declined_addrs(client
->active_lease
);
4333 if (live_cnt
== 0) {
4334 dhc6_lease_destroy(&client
->active_lease
, MDL
);
4335 client
->active_lease
= NULL
;
4338 /* Solicit with any live addresses we have so far, and
4339 * add additional empty NA iasubopts for those we had
4341 start_init6(client
);
4345 /* Action was taken, so now that we've torn down our scheduled
4346 * retransmissions, return.
4348 if (check_status
== ISC_R_CANCELED
)
4351 if (client
->selected_lease
!= NULL
) {
4352 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
4353 client
->selected_lease
= NULL
;
4356 /* If this is in response to a confirm, we use the lease we've
4357 * already got, not the reply we were sent.
4359 if (client
->state
== S_REBOOTING
) {
4360 if (client
->active_lease
== NULL
)
4361 log_fatal("Impossible condition at %s:%d.", MDL
);
4363 dhc6_lease_destroy(&lease
, MDL
);
4364 start_bound(client
);
4368 /* Merge any bindings in the active lease (if there is one) into
4369 * the new active lease.
4371 dhc6_merge_lease(client
->active_lease
, lease
);
4373 /* Cleanup if a previous attempt to go bound failed. */
4374 if (client
->old_lease
!= NULL
) {
4375 dhc6_lease_destroy(&client
->old_lease
, MDL
);
4376 client
->old_lease
= NULL
;
4379 /* Make this lease active and BIND to it. */
4380 if (client
->active_lease
!= NULL
)
4381 client
->old_lease
= client
->active_lease
;
4382 client
->active_lease
= lease
;
4384 /* We're done with the ADVERTISEd leases, if any. */
4385 while(client
->advertised_leases
!= NULL
) {
4386 lease
= client
->advertised_leases
;
4387 client
->advertised_leases
= lease
->next
;
4389 dhc6_lease_destroy(&lease
, MDL
);
4392 start_bound(client
);
4395 /* DHCPv6 packets are a little sillier than they needed to be - the root
4396 * packet contains options, then IA's which contain options, then within
4397 * that IAADDR's which contain options.
4399 * To sort this out at dhclient-script time (which fetches config parameters
4400 * in environment variables), start_bound() iterates over each IAADDR, and
4401 * calls this function to marshall an environment variable set that includes
4402 * the most-specific option values related to that IAADDR in particular.
4404 * To achieve this, we load environment variables for the root options space,
4405 * then the IA, then the IAADDR. Any duplicate option names will be
4406 * over-written by the later versions.
4409 dhc6_marshall_values(const char *prefix
, struct client_state
*client
,
4410 struct dhc6_lease
*lease
, struct dhc6_ia
*ia
,
4411 struct dhc6_addr
*addr
)
4413 /* Option cache contents, in descending order of
4416 if ((lease
!= NULL
) && (lease
->options
!= NULL
))
4417 script_write_params6(client
, prefix
, lease
->options
);
4418 if ((ia
!= NULL
) && (ia
->options
!= NULL
))
4419 script_write_params6(client
, prefix
, ia
->options
);
4420 if ((addr
!= NULL
) && (addr
->options
!= NULL
))
4421 script_write_params6(client
, prefix
, addr
->options
);
4425 if ((ia
!= NULL
) && (ia
->ia_type
== D6O_IA_PD
)) {
4426 client_envadd(client
, prefix
,
4427 "ip6_prefix", "%s/%u",
4428 piaddr(addr
->address
),
4429 (unsigned) addr
->plen
);
4431 client_envadd(client
, prefix
, "ip6_prefixlen",
4432 "%d", address_prefix_len
);
4433 client_envadd(client
, prefix
, "ip6_address",
4434 "%s", piaddr(addr
->address
));
4436 if ((ia
!= NULL
) && (ia
->ia_type
== D6O_IA_TA
)) {
4437 client_envadd(client
, prefix
,
4438 "ip6_type", "temporary");
4440 client_envadd(client
, prefix
, "life_starts", "%d",
4441 (int)(addr
->starts
));
4442 client_envadd(client
, prefix
, "preferred_life", "%u",
4443 addr
->preferred_life
);
4444 client_envadd(client
, prefix
, "max_life", "%u",
4450 client_envadd(client
, prefix
, "iaid", "%s",
4451 print_hex_1(4, ia
->iaid
, 12));
4452 client_envadd(client
, prefix
, "starts", "%d",
4454 client_envadd(client
, prefix
, "renew", "%u", ia
->renew
);
4455 client_envadd(client
, prefix
, "rebind", "%u", ia
->rebind
);
4459 /* Look at where the client's active lease is sitting. If it's looking to
4460 * time out on renew, rebind, depref, or expiration, do those things.
4463 dhc6_check_times(struct client_state
*client
)
4465 struct dhc6_lease
*lease
;
4467 struct dhc6_addr
*addr
;
4468 TIME renew
=MAX_TIME
, rebind
=MAX_TIME
, depref
=MAX_TIME
,
4469 lo_expire
=MAX_TIME
, hi_expire
=0, max_ia_starts
= 0, tmp
;
4470 int has_addrs
= ISC_FALSE
;
4471 int has_preferred_addrs
= ISC_FALSE
;
4474 lease
= client
->active_lease
;
4476 /* Bit spammy. We should probably keep record of scheduled
4479 cancel_timeout(start_renew6
, client
);
4480 cancel_timeout(start_rebind6
, client
);
4481 cancel_timeout(do_depref
, client
);
4482 cancel_timeout(do_expire
, client
);
4484 for(ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
4485 TIME this_ia_lo_expire
, this_ia_hi_expire
, use_expire
;
4487 this_ia_lo_expire
= MAX_TIME
;
4488 this_ia_hi_expire
= 0;
4490 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
4491 if(!(addr
->flags
& DHC6_ADDR_DEPREFFED
)) {
4492 if (addr
->preferred_life
== 0xffffffff)
4495 tmp
= addr
->starts
+
4496 addr
->preferred_life
;
4501 if (!(addr
->flags
& DHC6_ADDR_EXPIRED
)) {
4502 has_preferred_addrs
= ISC_TRUE
;
4506 if (!(addr
->flags
& DHC6_ADDR_EXPIRED
)) {
4507 /* Find EPOCH-relative expiration. */
4508 if (addr
->max_life
== 0xffffffff)
4511 tmp
= addr
->starts
+ addr
->max_life
;
4513 /* Make the times ia->starts relative. */
4516 if (tmp
> this_ia_hi_expire
)
4517 this_ia_hi_expire
= tmp
;
4518 if (tmp
< this_ia_lo_expire
)
4519 this_ia_lo_expire
= tmp
;
4521 has_addrs
= ISC_TRUE
;
4525 /* These times are ia->starts relative. */
4526 if (this_ia_lo_expire
<= (this_ia_hi_expire
/ 2))
4527 use_expire
= this_ia_hi_expire
;
4529 use_expire
= this_ia_lo_expire
;
4532 * If the auto-selected expiration time is "infinite", or
4533 * zero, assert a reasonable default.
4535 if ((use_expire
== MAX_TIME
) || (use_expire
<= 1))
4536 use_expire
= client
->config
->requested_lease
/ 2;
4540 /* Don't renew/rebind temporary addresses. */
4541 /* For NA and PD we find the most recent IA and the smallest
4542 * values for the renew and rebind then base the timer on
4543 * the sum of the them.
4544 * Normally all the IAs will have the same time as they
4545 * are requested and served as a group but in some cases the
4546 * client isn't asking for all of the IAs (for example
4547 * restarted with a different set of arguments) or the server
4548 * isn't updating the client on all of them (probably a
4551 if (ia
->ia_type
!= D6O_IA_TA
) {
4552 if (ia
->starts
> max_ia_starts
)
4553 max_ia_starts
= ia
->starts
;
4555 if (ia
->renew
== 0) {
4557 } else if (ia
->renew
== 0xffffffff)
4565 if (ia
->rebind
== 0) {
4566 /* Set rebind to 3/4 expiration interval. */
4567 tmp
= use_expire
+ (use_expire
/ 2);
4568 } else if (ia
->rebind
== 0xffffffff)
4578 * Return expiration ranges to EPOCH relative for event
4579 * scheduling (add_timeout()).
4581 this_ia_hi_expire
+= ia
->starts
;
4582 this_ia_lo_expire
+= ia
->starts
;
4584 if (this_ia_hi_expire
> hi_expire
)
4585 hi_expire
= this_ia_hi_expire
;
4586 if (this_ia_lo_expire
< lo_expire
)
4587 lo_expire
= this_ia_lo_expire
;
4590 /* If there are no addresses, give up, go to INIT.
4591 * Note that if an address is unexpired with a date in the past,
4592 * we're scheduling an expiration event to ocurr in the past. We
4593 * could probably optimize this to expire now (but then there's
4596 * In the future, we may decide that we're done here, or to
4597 * schedule a future request (using 4-pkt info-request model).
4599 if (has_addrs
== ISC_FALSE
) {
4600 dhc6_lease_destroy(&client
->active_lease
, MDL
);
4601 client
->active_lease
= NULL
;
4603 /* Go back to the beginning. */
4604 start_init6(client
);
4608 /* Second part of calculating the renew and rebind times.
4609 * We have the start time and the desired periods for renew
4610 * and rebind, just add them to get the desired end time.
4612 if (renew
!= MAX_TIME
)
4613 renew
+= max_ia_starts
;
4614 if (rebind
!= MAX_TIME
)
4615 rebind
+= max_ia_starts
;
4617 switch(client
->state
) {
4619 /* We'd like to hit renewing, but if rebinding has already
4620 * passed (time warp), head straight there.
4622 if ((rebind
> cur_time
) && (renew
< rebind
)) {
4623 log_debug("PRC: Renewal event scheduled in %d seconds, "
4624 "to run for %u seconds.",
4625 (int)(renew
- cur_time
),
4626 (unsigned)(rebind
- renew
));
4627 client
->next_MRD
= rebind
;
4630 add_timeout(&tv
, start_renew6
, client
, NULL
, NULL
);
4636 /* While actively renewing, MRD is bounded by the time
4637 * we stop renewing and start rebinding. This helps us
4638 * process the state change on time.
4640 client
->MRD
= rebind
- cur_time
;
4641 if (rebind
!= MAX_TIME
) {
4642 log_debug("PRC: Rebind event scheduled in %d seconds, "
4643 "to run for %d seconds.",
4644 (int)(rebind
- cur_time
),
4645 (int)(hi_expire
- rebind
));
4646 client
->next_MRD
= hi_expire
;
4649 add_timeout(&tv
, start_rebind6
, client
, NULL
, NULL
);
4654 /* For now, we rebind up until the last lease expires. In
4655 * the future, we might want to start SOLICITing when we've
4656 * depreffed an address.
4658 client
->MRD
= hi_expire
- cur_time
;
4662 if (has_preferred_addrs
) {
4663 log_fatal("Impossible condition, state %d at %s:%d.",
4664 client
->state
, MDL
);
4668 /* Separately, set a time at which we will depref and expire
4669 * leases. This might happen with multiple addresses while we
4670 * keep trying to refresh.
4672 if (depref
!= MAX_TIME
) {
4673 log_debug("PRC: Depreference scheduled in %d seconds.",
4674 (int)(depref
- cur_time
));
4677 add_timeout(&tv
, do_depref
, client
, NULL
, NULL
);
4679 if (lo_expire
!= MAX_TIME
) {
4680 log_debug("PRC: Expiration scheduled in %d seconds.",
4681 (int)(lo_expire
- cur_time
));
4682 tv
.tv_sec
= lo_expire
;
4684 add_timeout(&tv
, do_expire
, client
, NULL
, NULL
);
4688 /* In a given IA chain, find the IA with the same type and 'iaid'. */
4689 static struct dhc6_ia
*
4690 find_ia(struct dhc6_ia
*head
, u_int16_t type
, const char *id
)
4694 for (ia
= head
; ia
!= NULL
; ia
= ia
->next
) {
4695 if (ia
->ia_type
!= type
)
4697 if (memcmp(ia
->iaid
, id
, 4) == 0)
4704 /* In a given address chain, find a matching address. */
4705 static struct dhc6_addr
*
4706 find_addr(struct dhc6_addr
*head
, struct iaddr
*address
)
4708 struct dhc6_addr
*addr
;
4710 for (addr
= head
; addr
!= NULL
; addr
= addr
->next
) {
4711 if ((addr
->address
.len
== address
->len
) &&
4712 (memcmp(addr
->address
.iabuf
, address
->iabuf
,
4713 address
->len
) == 0))
4720 /* In a given prefix chain, find a matching prefix. */
4721 static struct dhc6_addr
*
4722 find_pref(struct dhc6_addr
*head
, struct iaddr
*prefix
, u_int8_t plen
)
4724 struct dhc6_addr
*pref
;
4726 for (pref
= head
; pref
!= NULL
; pref
= pref
->next
) {
4727 if ((pref
->address
.len
== prefix
->len
) &&
4728 (pref
->plen
== plen
) &&
4729 (memcmp(pref
->address
.iabuf
, prefix
->iabuf
,
4739 * \brief Merge the bindings from the source lease into the destination
4740 * lease structure, where they are missing.
4742 * This is used to merge any extra information we have in the current
4743 * (older, src) lease into the lease we have just received. For example
4744 * the src lease might include a binding for an NA that is still usable
4745 * but that we didn't request or that the server is no longer serving.
4746 * We want to keep that information until we toss the binding (expire,
4747 * release) so we move it to the new lease.
4749 * We have to copy the stateful objects rather than move them over,
4750 * because later code needs to be able to compare new versus old if
4751 * they contain any bindings.
4753 * \param src The older lease to copy the objects from
4754 * \param dst The newer lease to copy the objects to
4757 dhc6_merge_lease(struct dhc6_lease
*src
, struct dhc6_lease
*dst
)
4759 struct dhc6_ia
*sia
, *dia
, *tia
, **eia
;
4760 struct dhc6_addr
*saddr
, *daddr
, *taddr
;
4763 if ((dst
== NULL
) || (src
== NULL
))
4766 for (sia
= src
->bindings
; sia
!= NULL
; sia
= sia
->next
) {
4767 dia
= find_ia(dst
->bindings
, sia
->ia_type
, (char *)sia
->iaid
);
4770 tia
= dhc6_dup_ia(sia
, MDL
);
4773 log_fatal("Out of memory merging lease - "
4774 "Unable to continue without losing "
4775 "state! (%s:%d)", MDL
);
4777 /* Put any bindings that aren't in the new lease at the
4778 * end of the list. If the user or server reduces the
4779 * number of IAs the ones in use will be at the front
4780 * and will be used when building the next requests
4781 * We could be more efficient by finding the end
4782 * of the list once but we don't expect to do this
4785 for (eia
= &dst
->bindings
;
4787 eia
= &(*eia
)->next
) {
4788 ; /* no work just find the end */
4793 for (saddr
= sia
->addrs
; saddr
!= NULL
;
4794 saddr
= saddr
->next
) {
4795 if (sia
->ia_type
!= D6O_IA_PD
)
4796 daddr
= find_addr(dia
->addrs
,
4799 daddr
= find_pref(dia
->addrs
,
4803 if (daddr
== NULL
) {
4804 taddr
= dhc6_dup_addr(saddr
, MDL
);
4807 log_fatal("Out of memory "
4809 "Unable to continue "
4814 /* XXX: consider sorting? */
4815 taddr
->next
= dia
->addrs
;
4823 /* If we made changes, reset the score to 0 so it is recalculated. */
4828 /* We've either finished selecting or succeeded in Renew or Rebinding our
4829 * lease. In all cases we got a Reply. Give dhclient-script a tickle
4830 * to inform it about the new values, and then lay in wait for the next
4834 start_bound(struct client_state
*client
)
4836 struct dhc6_ia
*ia
, *oldia
;
4837 struct dhc6_addr
*addr
, *oldaddr
;
4838 struct dhc6_lease
*lease
, *old
;
4840 int decline_cnt
= 0;
4841 #if defined (NSUPDATE)
4842 TIME dns_update_offset
= 1;
4845 lease
= client
->active_lease
;
4846 if (lease
== NULL
) {
4847 log_error("Cannot enter bound state unless an active lease "
4851 lease
->released
= ISC_FALSE
;
4852 old
= client
->old_lease
;
4854 client
->v6_handler
= bound_handler
;
4856 switch (client
->state
) {
4858 case S_REBOOTING
: /* Pretend we got bound. */
4871 log_fatal("Impossible condition at %s:%d.", MDL
);
4872 /* Silence compiler warnings. */
4876 log_debug("PRC: Bound to lease %s.",
4877 print_hex_1(client
->active_lease
->server_id
.len
,
4878 client
->active_lease
->server_id
.data
, 55));
4879 client
->state
= S_BOUND
;
4881 write_client6_lease(client
, lease
, 0, 1);
4884 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
4886 oldia
= find_ia(old
->bindings
,
4892 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
4893 /* Don't try to use the address if it's already expired */
4894 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
4897 if (oldia
!= NULL
) {
4898 if (ia
->ia_type
!= D6O_IA_PD
)
4899 oldaddr
= find_addr(oldia
->addrs
,
4902 oldaddr
= find_pref(oldia
->addrs
,
4908 #if defined (NSUPDATE)
4909 if ((oldaddr
== NULL
) && (ia
->ia_type
== D6O_IA_NA
))
4910 dhclient_schedule_updates(client
,
4912 dns_update_offset
++);
4915 /* Shell out to setup the new binding. */
4916 script_init(client
, reason
, NULL
);
4919 dhc6_marshall_values("old_", client
, old
,
4921 dhc6_marshall_values("new_", client
, lease
, ia
, addr
);
4922 script_write_requested6(client
);
4924 /* When script returns 3, DAD failed */
4925 if (script_go(client
) == 3) {
4926 if (ia
->ia_type
== D6O_IA_NA
) {
4927 addr
->flags
|= DHC6_ADDR_DECLINED
;
4928 log_debug ("Flag address declined:%s",
4929 piaddr(addr
->address
));
4935 /* If the client script DAD failed any addresses we need
4936 * build and issue a DECLINE */
4938 start_decline6(client
);
4942 /* XXX: maybe we should loop on the old values instead? */
4943 if (ia
->addrs
== NULL
) {
4944 script_init(client
, reason
, NULL
);
4947 dhc6_marshall_values("old_", client
, old
,
4950 oldia
->addrs
: NULL
);
4952 dhc6_marshall_values("new_", client
, lease
, ia
,
4954 script_write_requested6(client
);
4960 /* XXX: maybe we should loop on the old values instead? */
4961 if (lease
->bindings
== NULL
) {
4962 script_init(client
, reason
, NULL
);
4965 dhc6_marshall_values("old_", client
, old
,
4967 (old
->bindings
!= NULL
) ?
4968 old
->bindings
->addrs
: NULL
);
4970 dhc6_marshall_values("new_", client
, lease
, NULL
, NULL
);
4971 script_write_requested6(client
);
4977 if (dhcpv4_over_dhcpv6
)
4983 if (client
->old_lease
!= NULL
) {
4984 dhc6_lease_destroy(&client
->old_lease
, MDL
);
4985 client
->old_lease
= NULL
;
4988 /* Schedule events. */
4989 dhc6_check_times(client
);
4992 /* While bound, ignore packets. In the future we'll want to answer
4993 * Reconfigure-Request messages and the like.
4996 bound_handler(struct packet
*packet
, struct client_state
*client
)
4998 log_debug("RCV: Input packets are ignored once bound.");
5002 * start_decline6() kicks off the decline process, transmitting
5003 * an decline packet and scheduling a retransmission event.
5006 start_decline6(struct client_state
*client
)
5008 /* Cancel any pending transmissions */
5009 cancel_timeout(do_confirm6
, client
);
5010 cancel_timeout(do_select6
, client
);
5011 cancel_timeout(do_refresh6
, client
);
5012 cancel_timeout(do_release6
, client
);
5013 cancel_timeout(do_decline6
, client
);
5014 client
->state
= S_DECLINING
;
5016 if (client
->active_lease
== NULL
)
5019 /* Set timers per RFC3315 section 18.1.7. */
5020 client
->IRT
= DEC_TIMEOUT
* 100;
5022 client
->MRC
= DEC_MAX_RC
;
5025 dhc6_retrans_init(client
);
5026 client
->v6_handler
= reply_handler
;
5028 client
->refresh_type
= DHCPV6_DECLINE
;
5029 do_decline6(client
);
5033 * do_decline6() creates a Decline packet and transmits it.
5034 * The decline will contain an IA_NA with iasubopt(s) for
5035 * each IA_NA containing declined address(es) in the active
5039 do_decline6(void *input
)
5041 struct client_state
*client
;
5042 struct data_string ds
;
5044 struct timeval elapsed
, tv
;
5047 if (client
== NULL
|| client
->active_lease
== NULL
) {
5051 if ((client
->MRC
!= 0) && (client
->txcount
> client
->MRC
)) {
5052 log_info("Max retransmission count exceeded.");
5057 * Start_time starts at the first transmission.
5059 if (client
->txcount
== 0) {
5060 client
->start_time
.tv_sec
= cur_tv
.tv_sec
;
5061 client
->start_time
.tv_usec
= cur_tv
.tv_usec
;
5064 /* elapsed = cur - start */
5065 elapsed
.tv_sec
= cur_tv
.tv_sec
- client
->start_time
.tv_sec
;
5066 elapsed
.tv_usec
= cur_tv
.tv_usec
- client
->start_time
.tv_usec
;
5067 if (elapsed
.tv_usec
< 0) {
5068 elapsed
.tv_sec
-= 1;
5069 elapsed
.tv_usec
+= 1000000;
5072 memset(&ds
, 0, sizeof(ds
));
5073 if (!buffer_allocate(&ds
.buffer
, 4, MDL
)) {
5074 log_error("Unable to allocate memory for Decline.");
5078 ds
.data
= ds
.buffer
->data
;
5080 ds
.buffer
->data
[0] = DHCPV6_DECLINE
;
5081 memcpy(ds
.buffer
->data
+ 1, client
->dhcpv6_transaction_id
, 3);
5083 /* Form an elapsed option. */
5084 /* Maximum value is 65535 1/100s coded as 0xffff. */
5085 if ((elapsed
.tv_sec
< 0) || (elapsed
.tv_sec
> 655) ||
5086 ((elapsed
.tv_sec
== 655) && (elapsed
.tv_usec
> 350000))) {
5087 client
->elapsed
= 0xffff;
5089 client
->elapsed
= elapsed
.tv_sec
* 100;
5090 client
->elapsed
+= elapsed
.tv_usec
/ 10000;
5093 client
->elapsed
= htons(client
->elapsed
);
5095 log_debug("XMT: Forming Decline.");
5096 make_client6_options(client
, &client
->sent_options
,
5097 client
->active_lease
, DHCPV6_DECLINE
);
5098 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
, NULL
,
5099 client
->sent_options
, &global_scope
,
5102 /* Append IA_NA's. */
5103 if (dhc6_add_ia_na_decline(client
, &ds
, client
->active_lease
)
5105 data_string_forget(&ds
, MDL
);
5109 /* Transmit and wait. */
5110 log_info("XMT: Decline on %s, interval %ld0ms.",
5111 client
->name
? client
->name
: client
->interface
->name
,
5112 (long int)client
->RT
);
5114 send_ret
= send_packet6(client
->interface
, ds
.data
, ds
.len
,
5116 if (send_ret
!= ds
.len
) {
5117 log_error("dhc6: sendpacket6() sent %d of %d bytes",
5121 data_string_forget(&ds
, MDL
);
5124 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
5125 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
5126 if (tv
.tv_usec
>= 1000000) {
5128 tv
.tv_usec
-= 1000000;
5130 add_timeout(&tv
, do_decline6
, client
, NULL
, NULL
);
5131 dhc6_retrans_advance(client
);
5135 /* We here because we've exhausted our retry limits or
5136 * something else has gone wrong with the decline process.
5137 * So let's just toss the existing lease and start over. */
5138 dhc6_lease_destroy(&client
->active_lease
, MDL
);
5139 client
->active_lease
= NULL
;
5141 start_init6(client
);
5145 /* start_renew6() gets us all ready to go to start transmitting Renew packets.
5146 * Note that client->next_MRD must be set before entering this function -
5147 * it must be set to the time at which the client should start Rebinding.
5150 start_renew6(void *input
)
5152 struct client_state
*client
;
5154 client
= (struct client_state
*)input
;
5156 log_info("PRC: Renewing lease on %s.",
5157 client
->name
? client
->name
: client
->interface
->name
);
5158 client
->state
= S_RENEWING
;
5160 client
->v6_handler
= reply_handler
;
5162 /* Times per RFC3315 section 18.1.3. */
5163 client
->IRT
= REN_TIMEOUT
* 100;
5164 client
->MRT
= REN_MAX_RT
* 100;
5166 /* MRD is special in renew - we need to set it by checking timer
5169 client
->MRD
= client
->next_MRD
- cur_time
;
5171 dhc6_retrans_init(client
);
5173 client
->refresh_type
= DHCPV6_RENEW
;
5174 do_refresh6(client
);
5177 /* do_refresh6() transmits one DHCPv6 packet, be it a Renew or Rebind, and
5178 * gives the retransmission state a bump for the next time. Note that
5179 * client->refresh_type must be set before entering this function.
5182 do_refresh6(void *input
)
5184 struct option_cache
*oc
;
5185 struct sockaddr_in6 unicast
, *dest_addr
= &DHCPv6DestAddr
;
5186 struct data_string ds
;
5187 struct client_state
*client
;
5188 struct dhc6_lease
*lease
;
5189 struct timeval elapsed
, tv
;
5190 int send_ret
, added
;
5192 client
= (struct client_state
*)input
;
5193 memset(&ds
, 0, sizeof(ds
));
5195 lease
= client
->active_lease
;
5196 if (lease
== NULL
) {
5197 log_error("Cannot renew without an active binding.");
5201 /* Ensure we're emitting a valid message type. */
5202 switch (client
->refresh_type
) {
5208 log_fatal("Internal inconsistency (%d) at %s:%d.",
5209 client
->refresh_type
, MDL
);
5213 * Start_time starts at the first transmission.
5215 if (client
->txcount
== 0) {
5216 client
->start_time
.tv_sec
= cur_tv
.tv_sec
;
5217 client
->start_time
.tv_usec
= cur_tv
.tv_usec
;
5220 /* elapsed = cur - start */
5221 elapsed
.tv_sec
= cur_tv
.tv_sec
- client
->start_time
.tv_sec
;
5222 elapsed
.tv_usec
= cur_tv
.tv_usec
- client
->start_time
.tv_usec
;
5223 if (elapsed
.tv_usec
< 0) {
5224 elapsed
.tv_sec
-= 1;
5225 elapsed
.tv_usec
+= 1000000;
5227 if (((client
->MRC
!= 0) && (client
->txcount
> client
->MRC
)) ||
5228 ((client
->MRD
!= 0) && (elapsed
.tv_sec
>= client
->MRD
))) {
5229 /* We're done. Move on to the next phase, if any. */
5230 dhc6_check_times(client
);
5235 * Check whether the server has sent a unicast option; if so, we can
5236 * use the address it specified for RENEWs.
5238 oc
= lookup_option(&dhcpv6_universe
, lease
->options
, D6O_UNICAST
);
5239 if (oc
&& evaluate_option_cache(&ds
, NULL
, NULL
, NULL
,
5240 lease
->options
, NULL
, &global_scope
,
5243 log_error("Invalid unicast option length %d.", ds
.len
);
5245 memset(&unicast
, 0, sizeof(DHCPv6DestAddr
));
5246 unicast
.sin6_family
= AF_INET6
;
5247 unicast
.sin6_port
= remote_port
;
5248 memcpy(&unicast
.sin6_addr
, ds
.data
, 16);
5249 if (client
->refresh_type
== DHCPV6_RENEW
) {
5250 dest_addr
= &unicast
;
5254 data_string_forget(&ds
, MDL
);
5257 /* Commence forming a renew packet. */
5258 memset(&ds
, 0, sizeof(ds
));
5259 if (!buffer_allocate(&ds
.buffer
, 4, MDL
)) {
5260 log_error("Unable to allocate memory for packet.");
5263 ds
.data
= ds
.buffer
->data
;
5266 ds
.buffer
->data
[0] = client
->refresh_type
;
5267 memcpy(ds
.buffer
->data
+ 1, client
->dhcpv6_transaction_id
, 3);
5269 /* Form an elapsed option. */
5270 /* Maximum value is 65535 1/100s coded as 0xffff. */
5271 if ((elapsed
.tv_sec
< 0) || (elapsed
.tv_sec
> 655) ||
5272 ((elapsed
.tv_sec
== 655) && (elapsed
.tv_usec
> 350000))) {
5273 client
->elapsed
= 0xffff;
5275 client
->elapsed
= elapsed
.tv_sec
* 100;
5276 client
->elapsed
+= elapsed
.tv_usec
/ 10000;
5279 if (client
->elapsed
== 0)
5280 log_debug("XMT: Forming %s, 0 ms elapsed.",
5281 dhcpv6_type_names
[client
->refresh_type
]);
5283 log_debug("XMT: Forming %s, %u0 ms elapsed.",
5284 dhcpv6_type_names
[client
->refresh_type
],
5285 (unsigned)client
->elapsed
);
5287 client
->elapsed
= htons(client
->elapsed
);
5289 make_client6_options(client
, &client
->sent_options
, lease
,
5290 client
->refresh_type
);
5292 /* Put in any options from the sent cache. */
5293 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
, NULL
,
5294 client
->sent_options
, &global_scope
,
5297 /* Now append any IA's, and within them any IAADDR/IAPREFIXs.
5298 * For each type of IA (na, ta, pd) we start with the ones for
5299 * which we already have addresses (dhc6_add_ia_xx) and then
5300 * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
5303 ((dhc6_add_ia_na(client
, &ds
, lease
, client
->refresh_type
,
5304 wanted_ia_na
, &added
) != ISC_R_SUCCESS
) ||
5305 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_na
- added
,
5306 D6O_IA_NA
) != ISC_R_SUCCESS
))) {
5307 data_string_forget(&ds
, MDL
);
5311 ((dhc6_add_ia_pd(client
, &ds
, lease
, client
->refresh_type
,
5312 wanted_ia_pd
, &added
) != ISC_R_SUCCESS
) ||
5313 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_pd
- added
,
5314 D6O_IA_PD
) != ISC_R_SUCCESS
))) {
5315 data_string_forget(&ds
, MDL
);
5319 log_info("XMT: %s on %s, interval %ld0ms.",
5320 dhcpv6_type_names
[client
->refresh_type
],
5321 client
->name
? client
->name
: client
->interface
->name
,
5322 (long int)client
->RT
);
5324 send_ret
= send_packet6(client
->interface
, ds
.data
, ds
.len
, dest_addr
);
5326 if (send_ret
!= ds
.len
) {
5327 log_error("dhc6: send_packet6() sent %d of %d bytes",
5331 data_string_forget(&ds
, MDL
);
5334 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
5335 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
5336 if (tv
.tv_usec
>= 1000000) {
5338 tv
.tv_usec
-= 1000000;
5340 add_timeout(&tv
, do_refresh6
, client
, NULL
, NULL
);
5342 dhc6_retrans_advance(client
);
5345 /* start_rebind6() gets us all set up to go and rebind a lease. Note that
5346 * client->next_MRD must be set before entering this function. In this case,
5347 * MRD must be set to the maximum time any address in the packet will
5351 start_rebind6(void *input
)
5353 struct client_state
*client
;
5355 client
= (struct client_state
*)input
;
5357 log_info("PRC: Rebinding lease on %s.",
5358 client
->name
? client
->name
: client
->interface
->name
);
5359 client
->state
= S_REBINDING
;
5361 client
->v6_handler
= reply_handler
;
5363 /* Times per RFC3315 section 18.1.4. */
5364 client
->IRT
= REB_TIMEOUT
* 100;
5365 client
->MRT
= REB_MAX_RT
* 100;
5367 /* MRD is special in rebind - it's determined by the timer
5370 client
->MRD
= client
->next_MRD
- cur_time
;
5372 dhc6_retrans_init(client
);
5374 client
->refresh_type
= DHCPV6_REBIND
;
5375 do_refresh6(client
);
5378 /* do_depref() runs through a given lease's addresses, for each that has
5379 * not yet been depreffed, shells out to the dhclient-script to inform it
5380 * of the status change. The dhclient-script should then do...something...
5381 * to encourage applications to move off the address and onto one of the
5382 * remaining 'preferred' addresses.
5385 do_depref(void *input
)
5387 struct client_state
*client
;
5388 struct dhc6_lease
*lease
;
5390 struct dhc6_addr
*addr
;
5392 client
= (struct client_state
*)input
;
5394 lease
= client
->active_lease
;
5398 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
5399 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
5400 if (addr
->flags
& DHC6_ADDR_DEPREFFED
)
5403 if (addr
->starts
+ addr
->preferred_life
<= cur_time
) {
5404 script_init(client
, "DEPREF6", NULL
);
5405 dhc6_marshall_values("cur_", client
, lease
,
5407 script_write_requested6(client
);
5410 addr
->flags
|= DHC6_ADDR_DEPREFFED
;
5412 if (ia
->ia_type
!= D6O_IA_PD
)
5413 log_info("PRC: Address %s depreferred.",
5414 piaddr(addr
->address
));
5416 log_info("PRC: Prefix %s/%u depreferred.",
5417 piaddr(addr
->address
),
5418 (unsigned) addr
->plen
);
5420 #if defined (NSUPDATE)
5421 /* Remove DDNS bindings at depref time. */
5422 if ((ia
->ia_type
== D6O_IA_NA
) &&
5423 client
->config
->do_forward_update
)
5424 client_dns_remove(client
,
5431 dhc6_check_times(client
);
5434 /* do_expire() searches through all the addresses on a given lease, and
5435 * expires/removes any addresses that are no longer valid.
5438 do_expire(void *input
)
5440 struct client_state
*client
;
5441 struct dhc6_lease
*lease
;
5442 struct dhc6_ia
*ia
, **tia
;
5443 struct dhc6_addr
*addr
;
5444 int has_addrs
= ISC_FALSE
;
5445 int ia_has_addrs
= ISC_FALSE
;
5447 client
= (struct client_state
*)input
;
5449 lease
= client
->active_lease
;
5453 for (ia
= lease
->bindings
, tia
= &lease
->bindings
; ia
!= NULL
; ) {
5454 ia_has_addrs
= ISC_FALSE
;
5455 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
5456 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
5459 if (addr
->starts
+ addr
->max_life
<= cur_time
) {
5460 script_init(client
, "EXPIRE6", NULL
);
5461 dhc6_marshall_values("old_", client
, lease
,
5463 script_write_requested6(client
);
5466 addr
->flags
|= DHC6_ADDR_EXPIRED
;
5468 if (ia
->ia_type
!= D6O_IA_PD
)
5469 log_info("PRC: Address %s expired.",
5470 piaddr(addr
->address
));
5472 log_info("PRC: Prefix %s/%u expired.",
5473 piaddr(addr
->address
),
5474 (unsigned) addr
->plen
);
5476 #if defined (NSUPDATE)
5477 /* We remove DNS records at depref time, but
5478 * it is possible that we might get here
5479 * without depreffing.
5481 if ((ia
->ia_type
== D6O_IA_NA
) &&
5482 client
->config
->do_forward_update
&&
5483 !(addr
->flags
& DHC6_ADDR_DEPREFFED
))
5484 client_dns_remove(client
,
5491 ia_has_addrs
= ISC_TRUE
;
5492 has_addrs
= ISC_TRUE
;
5495 /* Update to the next ia and git rid of this ia
5496 * if it doesn't have any leases.
5498 if (ia_has_addrs
== ISC_TRUE
) {
5499 /* leases, just advance the list pointer */
5500 tia
= &(*tia
)->next
;
5502 /* no leases, update the list pointer
5506 dhc6_ia_destroy(&ia
, MDL
);
5508 /* lastly update the ia pointer to our new ia */
5512 /* Clean up empty leases. */
5513 if (has_addrs
== ISC_FALSE
) {
5514 log_info("PRC: Bound lease is devoid of active addresses."
5515 " Re-initializing.");
5517 dhc6_lease_destroy(&lease
, MDL
);
5518 client
->active_lease
= NULL
;
5520 start_init6(client
);
5524 /* Schedule the next run through. */
5525 dhc6_check_times(client
);
5529 * Run client script to unconfigure interface.
5530 * Called with reason STOP6 when dhclient -x is run, or with reason
5531 * RELEASE6 when server has replied to a Release message.
5532 * Stateless is a special case.
5535 unconfigure6(struct client_state
*client
, const char *reason
)
5538 struct dhc6_addr
*addr
;
5541 script_init(client
, reason
, NULL
);
5542 if (client
->active_lease
!= NULL
)
5543 script_write_params6(client
, "old_",
5544 client
->active_lease
->options
);
5545 script_write_requested6(client
);
5550 if (client
->active_lease
== NULL
)
5553 for (ia
= client
->active_lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
5554 if (ia
->ia_type
== D6O_IA_TA
)
5557 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
5558 script_init(client
, reason
, NULL
);
5559 dhc6_marshall_values("old_", client
,
5560 client
->active_lease
, ia
, addr
);
5561 script_write_requested6(client
);
5564 #if defined (NSUPDATE)
5565 if ((ia
->ia_type
== D6O_IA_NA
) &&
5566 client
->config
->do_forward_update
)
5567 client_dns_remove(client
, &addr
->address
);
5574 refresh_info_request6(void *input
)
5576 struct client_state
*client
;
5578 client
= (struct client_state
*)input
;
5579 start_info_request6(client
);
5582 /* Timeout for Information-Request (using the IRT option).
5585 dhc6_check_irt(struct client_state
*client
)
5587 struct option
**req
;
5588 struct option_cache
*oc
;
5589 TIME expire
= MAX_TIME
;
5592 isc_boolean_t found
= ISC_FALSE
;
5594 cancel_timeout(refresh_info_request6
, client
);
5596 req
= client
->config
->requested_options
;
5597 for (i
= 0; req
[i
] != NULL
; i
++) {
5598 if (req
[i
] == irt_option
) {
5603 /* Simply return gives a endless loop waiting for nothing. */
5606 if (!dhcpv4_over_dhcpv6
)
5611 oc
= lookup_option(&dhcpv6_universe
, client
->active_lease
->options
,
5612 D6O_INFORMATION_REFRESH_TIME
);
5614 struct data_string irt
;
5616 memset(&irt
, 0, sizeof(irt
));
5617 if (!evaluate_option_cache(&irt
, NULL
, NULL
, client
,
5618 client
->active_lease
->options
,
5619 NULL
, &global_scope
, oc
, MDL
) ||
5621 log_error("Can't evaluate IRT.");
5623 expire
= getULong(irt
.data
);
5624 if (expire
< IRT_MINIMUM
)
5625 expire
= IRT_MINIMUM
;
5626 if (expire
== 0xffffffff)
5629 data_string_forget(&irt
, MDL
);
5631 expire
= IRT_DEFAULT
;
5633 if (expire
!= MAX_TIME
) {
5634 log_debug("PRC: Refresh event scheduled in %u seconds.",
5636 tv
.tv_sec
= cur_time
+ expire
;
5638 add_timeout(&tv
, refresh_info_request6
, client
, NULL
, NULL
);
5642 /* We got a Reply. Give dhclient-script a tickle to inform it about
5643 * the new values, and then lay in wait for the next event.
5646 start_informed(struct client_state
*client
)
5648 client
->v6_handler
= informed_handler
;
5650 log_debug("PRC: Done.");
5652 client
->state
= S_BOUND
;
5654 script_init(client
, "RENEW6", NULL
);
5655 if (client
->old_lease
!= NULL
)
5656 script_write_params6(client
, "old_",
5657 client
->old_lease
->options
);
5658 script_write_params6(client
, "new_", client
->active_lease
->options
);
5659 script_write_requested6(client
);
5663 if (dhcpv4_over_dhcpv6
)
5669 if (client
->old_lease
!= NULL
) {
5670 dhc6_lease_destroy(&client
->old_lease
, MDL
);
5671 client
->old_lease
= NULL
;
5674 /* Schedule events. */
5675 dhc6_check_irt(client
);
5678 /* While informed, ignore packets.
5681 informed_handler(struct packet
*packet
, struct client_state
*client
)
5683 log_debug("RCV: Input packets are ignored once bound.");
5686 /* make_client6_options() fetches option caches relevant to the client's
5687 * scope and places them into the sent_options cache. This cache is later
5688 * used to populate DHCPv6 output packets with options.
5691 make_client6_options(struct client_state
*client
, struct option_state
**op
,
5692 struct dhc6_lease
*lease
, u_int8_t message
)
5694 struct option_cache
*oc
;
5695 struct option
**req
;
5696 struct buffer
*buffer
;
5697 int buflen
, i
, oro_len
;
5699 if ((op
== NULL
) || (client
== NULL
))
5703 option_state_dereference(op
, MDL
);
5705 /* Create a cache to carry options to transmission. */
5706 option_state_allocate(op
, MDL
);
5708 /* Create and store an 'elapsed time' option in the cache. */
5710 if (option_cache_allocate(&oc
, MDL
)) {
5711 const unsigned char *cdata
;
5713 cdata
= (unsigned char *)&client
->elapsed
;
5715 if (make_const_data(&oc
->expression
, cdata
, 2, 0, 0, MDL
)) {
5716 option_reference(&oc
->option
, elapsed_option
, MDL
);
5717 save_option(&dhcpv6_universe
, *op
, oc
);
5720 option_cache_dereference(&oc
, MDL
);
5723 /* Bring in any configured options to send. */
5724 if (client
->config
->on_transmission
)
5725 execute_statements_in_scope(NULL
, NULL
, NULL
, client
,
5726 lease
? lease
->options
: NULL
,
5728 client
->config
->on_transmission
,
5731 /* Rapid-commit is only for SOLICITs. */
5732 if (message
!= DHCPV6_SOLICIT
)
5733 delete_option(&dhcpv6_universe
, *op
, D6O_RAPID_COMMIT
);
5735 /* See if the user configured a DUID in a relevant scope. If not,
5736 * introduce our default manufactured id.
5738 if ((oc
= lookup_option(&dhcpv6_universe
, *op
,
5739 D6O_CLIENTID
)) == NULL
) {
5740 if (!option_cache(&oc
, &default_duid
, NULL
, clientid_option
,
5742 log_fatal("Failure assembling a DUID.");
5744 save_option(&dhcpv6_universe
, *op
, oc
);
5745 option_cache_dereference(&oc
, MDL
);
5748 /* In cases where we're responding to a single server, put the
5749 * server's id in the response.
5751 * Note that lease is NULL for SOLICIT or INFO request messages,
5752 * and otherwise MUST be present.
5754 if (lease
== NULL
) {
5755 if ((message
!= DHCPV6_SOLICIT
) &&
5756 (message
!= DHCPV6_INFORMATION_REQUEST
))
5757 log_fatal("Impossible condition at %s:%d.", MDL
);
5758 } else if ((message
!= DHCPV6_REBIND
) &&
5759 (message
!= DHCPV6_CONFIRM
)) {
5760 oc
= lookup_option(&dhcpv6_universe
, lease
->options
,
5763 save_option(&dhcpv6_universe
, *op
, oc
);
5766 /* 'send dhcp6.oro foo;' syntax we used in 4.0.0a1/a2 has been
5767 * deprecated by adjustments to the 'request' syntax also used for
5770 if (lookup_option(&dhcpv6_universe
, *op
, D6O_ORO
) != NULL
)
5771 log_error("'send dhcp6.oro' syntax is deprecated, please "
5772 "use the 'request' syntax (\"man dhclient.conf\").");
5774 /* Construct and store an ORO (Option Request Option). It is a
5775 * fatal error to fail to send an ORO (of at least zero length).
5777 * Discussion: RFC3315 appears to be inconsistent in its statements
5778 * of whether or not the ORO is mandatory. In section 18.1.1
5779 * ("Creation and Transmission of Request Messages"):
5781 * The client MUST include an Option Request option (see section
5782 * 22.7) to indicate the options the client is interested in
5783 * receiving. The client MAY include options with data values as
5784 * hints to the server about parameter values the client would like
5787 * This MUST is missing from the creation/transmission of other
5788 * messages (such as Renew and Rebind), and the section 22.7 ("Option
5789 * Request Option" format and definition):
5791 * A client MAY include an Option Request option in a Solicit,
5792 * Request, Renew, Rebind, Confirm or Information-request message to
5793 * inform the server about options the client wants the server to
5794 * send to the client. A server MAY include an Option Request
5795 * option in a Reconfigure option to indicate which options the
5796 * client should request from the server.
5798 * seems to relax the requirement from MUST to MAY (and still other
5799 * language in RFC3315 supports this).
5801 * In lieu of a clarification of RFC3315, we will conform with the
5802 * MUST. Instead of an absent ORO, we will if there are no options
5803 * to request supply an empty ORO. Theoretically, an absent ORO is
5804 * difficult to interpret (does the client want all options or no
5805 * options?). A zero-length ORO is intuitively clear: requesting
5811 if (!buffer_allocate(&buffer
, buflen
, MDL
))
5812 log_fatal("Out of memory constructing DHCPv6 ORO.");
5813 req
= client
->config
->requested_options
;
5815 for (i
= 0 ; req
[i
] != NULL
; i
++) {
5816 if (buflen
== oro_len
) {
5817 struct buffer
*tmpbuf
= NULL
;
5822 buffer_reference(&tmpbuf
, buffer
, MDL
);
5823 buffer_dereference(&buffer
, MDL
);
5825 if (!buffer_allocate(&buffer
, buflen
, MDL
))
5826 log_fatal("Out of memory resizing "
5827 "DHCPv6 ORO buffer.");
5829 memcpy(buffer
->data
, tmpbuf
->data
, oro_len
);
5831 buffer_dereference(&tmpbuf
, MDL
);
5834 if (req
[i
]->universe
== &dhcpv6_universe
) {
5835 /* Append the code to the ORO. */
5836 putUShort(buffer
->data
+ oro_len
,
5844 if (make_const_option_cache(&oc
, &buffer
, NULL
, oro_len
,
5846 save_option(&dhcpv6_universe
, *op
, oc
);
5848 log_fatal("Unable to create ORO option cache.");
5852 * Note: make_const_option_cache() consumes the buffer, we do not
5853 * need to dereference it (XXX).
5855 option_cache_dereference(&oc
, MDL
);
5858 /* A clone of the DHCPv4 script_write_params() minus the DHCPv4-specific
5859 * filename, server-name, etc specifics.
5861 * Simply, store all values present in all universes of the option state
5862 * (probably derived from a DHCPv6 packet) into environment variables
5863 * named after the option names (and universe names) but with the 'prefix'
5866 * Later, dhclient-script may compare for example "new_time_servers" and
5867 * "old_time_servers" for differences, and only upon detecting a change
5868 * bother to rewrite ntp.conf and restart it. Or something along those
5872 script_write_params6(struct client_state
*client
, const char *prefix
,
5873 struct option_state
*options
)
5875 struct envadd_state es
;
5878 if (options
== NULL
)
5884 for (i
= 0 ; i
< options
->universe_count
; i
++) {
5885 option_space_foreach(NULL
, NULL
, client
, NULL
, options
,
5886 &global_scope
, universes
[i
], &es
,
5887 client_option_envadd
);
5892 * A clone of the DHCPv4 routine.
5893 * Write out the environment variables for the objects that the
5894 * client requested. If the object was requested the variable will be:
5895 * requested_<option_name>=1
5896 * If it wasn't requested there won't be a variable.
5898 static void script_write_requested6(client
)
5899 struct client_state
*client
;
5902 struct option
**req
;
5904 req
= client
->config
->requested_options
;
5909 for (i
= 0 ; req
[i
] != NULL
; i
++) {
5910 if ((req
[i
]->universe
== &dhcpv6_universe
) &&
5911 dhcp_option_ev_name (name
, sizeof(name
), req
[i
])) {
5912 client_envadd(client
, "requested_", name
, "%d", 1);
5918 * Check if there is something not fully defined in the active lease.
5920 static isc_boolean_t
5921 active_prefix(struct client_state
*client
)
5923 struct dhc6_lease
*lease
;
5925 struct dhc6_addr
*pref
;
5928 lease
= client
->active_lease
;
5931 memset(zeros
, 0, 16);
5932 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
5933 if (ia
->ia_type
!= D6O_IA_PD
)
5935 for (pref
= ia
->addrs
; pref
!= NULL
; pref
= pref
->next
) {
5936 if (pref
->plen
== 0)
5938 if (pref
->address
.len
!= 16)
5940 if (memcmp(pref
->address
.iabuf
, zeros
, 16) == 0)
5947 /* Adds a leases's declined addreses to the outbound packet
5949 * For each IA_NA in the lease that contains one or more declined
5950 * addresses, an IA_NA option with an iasubopt for each declined
5951 * address is added to the outbound packet.
5953 * We skip PDs and TAs as declines are undefined for them.
5956 dhc6_add_ia_na_decline(struct client_state
*client
, struct data_string
*packet
,
5957 struct dhc6_lease
*lease
) {
5958 struct data_string iads
;
5959 struct data_string addrds
;
5960 struct dhc6_addr
*addr
;
5962 isc_result_t rval
= ISC_R_SUCCESS
;
5964 memset(&iads
, 0, sizeof(iads
));
5965 memset(&addrds
, 0, sizeof(addrds
));
5966 for (ia
= lease
->bindings
; ia
!= NULL
&& rval
== ISC_R_SUCCESS
;
5968 if (ia
->ia_type
!= D6O_IA_NA
)
5971 int start_new_ia
= 1;
5972 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
5974 * Do not confirm expired addresses, do not request
5975 * expired addresses (but we keep them around for
5978 if (!(addr
->flags
& DHC6_ADDR_DECLINED
)) {
5983 if (!buffer_allocate(&iads
.buffer
, 12, MDL
)) {
5984 log_error("Unable to allocate memory"
5986 rval
= ISC_R_NOMEMORY
;
5990 /* Copy the IAID into the packet buffer. */
5991 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
5992 iads
.data
= iads
.buffer
->data
;
5995 /* Set t1/t2 to zero; server will ignore them */
5996 memset(iads
.buffer
->data
+ 4, 0, 8);
5997 log_debug("XMT: X-- IA_NA %s",
5998 print_hex_1(4, iads
.buffer
->data
, 55));
6002 if (addr
->address
.len
!= 16) {
6003 log_error("Illegal IPv6 address length (%d), "
6004 "ignoring. (%s:%d)",
6005 addr
->address
.len
, MDL
);
6009 if (!buffer_allocate(&addrds
.buffer
, 24, MDL
)) {
6010 log_error("Unable to allocate memory for "
6012 rval
= ISC_R_NOMEMORY
;
6016 addrds
.data
= addrds
.buffer
->data
;
6019 /* Copy the address into the packet buffer. */
6020 memcpy(addrds
.buffer
->data
, addr
->address
.iabuf
, 16);
6022 /* Preferred and max life are irrelevant */
6023 memset(addrds
.buffer
->data
+ 16, 0, 8);
6024 log_debug("XMT: | X-- Decline Address %s",
6025 piaddr(addr
->address
));
6027 append_option(&iads
, &dhcpv6_universe
, iaaddr_option
,
6029 data_string_forget(&addrds
, MDL
);
6033 * It doesn't make sense to make a request without an
6036 if (ia
->addrs
== NULL
) {
6037 log_debug("!!!: V IA_NA has no IAADDRs - removed.");
6038 rval
= ISC_R_FAILURE
;
6039 } else if (rval
== ISC_R_SUCCESS
) {
6040 log_debug("XMT: V IA_NA appended.");
6041 append_option(packet
, &dhcpv6_universe
, ia_na_option
,
6045 data_string_forget(&iads
, MDL
);
6052 * Remove any declined NA addresses from the lease.
6054 * Returns zero if the all of the bindings on the lease
6055 * were removed, non-zero if there are PD, TA, or usuable NA
6058 int drop_declined_addrs(struct dhc6_lease
*lease
) {
6062 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
6063 struct dhc6_addr
* prev_addr
;
6064 struct dhc6_addr
* addr
;
6065 struct dhc6_addr
* next
;
6067 /* If it's a PD or TA, we assume it has at least
6068 * one usuable binding */
6069 if (ia
->ia_type
!= D6O_IA_NA
) {
6075 for (addr
= ia
->addrs
; addr
!= NULL
; ) {
6076 if (!(addr
->flags
& DHC6_ADDR_DECLINED
)) {
6083 /* If we're deleting head, move it up one */
6084 if (ia
->addrs
== addr
) {
6085 ia
->addrs
= addr
->next
;
6086 prev_addr
= addr
->next
;
6088 prev_addr
->next
= addr
->next
;
6091 if (addr
->options
!= NULL
) {
6092 option_state_dereference(&addr
->options
, MDL
);
6104 /* Run through the addresses in lease and return true if there's any unexpired.
6105 * Return false otherwise.
6107 static isc_boolean_t
6108 unexpired_address_in_lease(struct dhc6_lease
*lease
)
6111 struct dhc6_addr
*addr
;
6113 if (lease
== NULL
) {
6117 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
6118 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
6119 if (!(addr
->flags
& DHC6_ADDR_EXPIRED
) &&
6120 (addr
->starts
+ addr
->max_life
> cur_time
)) {
6126 log_debug("PRC: Previous lease is devoid of active addresses.");