1 /* dhc6.c - DHCPv6 client routines. */
4 * Copyright (c) 2012-2015 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Internet Systems Consortium, Inc.
21 * Redwood City, CA 94063
23 * https://www.isc.org/
30 struct sockaddr_in6 DHCPv6DestAddr
;
33 * Option definition structures that are used by the software - declared
34 * here once and assigned at startup to save lookups.
36 struct option
*clientid_option
= NULL
;
37 struct option
*elapsed_option
= NULL
;
38 struct option
*ia_na_option
= NULL
;
39 struct option
*ia_ta_option
= NULL
;
40 struct option
*ia_pd_option
= NULL
;
41 struct option
*iaaddr_option
= NULL
;
42 struct option
*iaprefix_option
= NULL
;
43 struct option
*oro_option
= NULL
;
44 struct option
*irt_option
= NULL
;
46 static struct dhc6_lease
*dhc6_dup_lease(struct dhc6_lease
*lease
,
47 const char *file
, int line
);
48 static struct dhc6_ia
*dhc6_dup_ia(struct dhc6_ia
*ia
,
49 const char *file
, int line
);
50 static struct dhc6_addr
*dhc6_dup_addr(struct dhc6_addr
*addr
,
51 const char *file
, int line
);
52 static void dhc6_ia_destroy(struct dhc6_ia
**src
, const char *file
, int line
);
53 static isc_result_t
dhc6_parse_ia_na(struct dhc6_ia
**pia
,
54 struct packet
*packet
,
55 struct option_state
*options
,
57 static isc_result_t
dhc6_parse_ia_ta(struct dhc6_ia
**pia
,
58 struct packet
*packet
,
59 struct option_state
*options
,
61 static isc_result_t
dhc6_parse_ia_pd(struct dhc6_ia
**pia
,
62 struct packet
*packet
,
63 struct option_state
*options
,
65 static isc_result_t
dhc6_parse_addrs(struct dhc6_addr
**paddr
,
66 struct packet
*packet
,
67 struct option_state
*options
);
68 static isc_result_t
dhc6_parse_prefixes(struct dhc6_addr
**ppref
,
69 struct packet
*packet
,
70 struct option_state
*options
);
71 static struct dhc6_ia
*find_ia(struct dhc6_ia
*head
,
72 u_int16_t type
, const char *id
);
73 static struct dhc6_addr
*find_addr(struct dhc6_addr
*head
,
74 struct iaddr
*address
);
75 static struct dhc6_addr
*find_pref(struct dhc6_addr
*head
,
76 struct iaddr
*prefix
, u_int8_t plen
);
77 void init_handler(struct packet
*packet
, struct client_state
*client
);
78 void info_request_handler(struct packet
*packet
, struct client_state
*client
);
79 void rapid_commit_handler(struct packet
*packet
, struct client_state
*client
);
80 void do_init6(void *input
);
81 void do_info_request6(void *input
);
82 void do_confirm6(void *input
);
83 void reply_handler(struct packet
*packet
, struct client_state
*client
);
84 static isc_result_t
dhc6_create_iaid(struct client_state
*client
,
85 struct data_string
*ia
,
88 static int dhc6_count_ia(struct dhc6_lease
*lease
,
90 static isc_result_t
dhc6_bare_ia_xx(struct client_state
*client
,
91 struct data_string
*packet
,
94 static isc_result_t
dhc6_add_ia_na(struct client_state
*client
,
95 struct data_string
*packet
,
96 struct dhc6_lease
*lease
,
100 static isc_result_t
dhc6_add_ia_ta(struct client_state
*client
,
101 struct data_string
*packet
,
102 struct dhc6_lease
*lease
,
106 static isc_result_t
dhc6_add_ia_pd(struct client_state
*client
,
107 struct data_string
*packet
,
108 struct dhc6_lease
*lease
,
112 static isc_boolean_t
stopping_finished(void);
113 static void dhc6_merge_lease(struct dhc6_lease
*src
, struct dhc6_lease
*dst
);
114 void do_select6(void *input
);
115 void do_refresh6(void *input
);
116 static void do_release6(void *input
);
117 static void start_bound(struct client_state
*client
);
118 static void start_informed(struct client_state
*client
);
119 void informed_handler(struct packet
*packet
, struct client_state
*client
);
120 void bound_handler(struct packet
*packet
, struct client_state
*client
);
121 void start_renew6(void *input
);
122 void start_rebind6(void *input
);
123 void do_depref(void *input
);
124 void do_expire(void *input
);
125 static void make_client6_options(struct client_state
*client
,
126 struct option_state
**op
,
127 struct dhc6_lease
*lease
, u_int8_t message
);
128 static void script_write_params6(struct client_state
*client
,
130 struct option_state
*options
);
131 static void script_write_requested6(struct client_state
*client
);
132 static isc_boolean_t
active_prefix(struct client_state
*client
);
134 static int check_timing6(struct client_state
*client
, u_int8_t msg_type
,
135 char *msg_str
, struct dhc6_lease
*lease
,
136 struct data_string
*ds
);
137 static isc_result_t
dhc6_get_status_code(struct option_state
*options
,
139 struct data_string
*msg
);
140 static isc_result_t
dhc6_check_status(isc_result_t rval
,
141 struct option_state
*options
,
146 extern int stateless
;
149 * Assign DHCPv6 port numbers as a client.
152 dhcpv6_client_assignments(void)
157 if (path_dhclient_pid
== NULL
)
158 path_dhclient_pid
= _PATH_DHCLIENT6_PID
;
159 if (path_dhclient_db
== NULL
)
160 path_dhclient_db
= _PATH_DHCLIENT6_DB
;
162 if (local_port
== 0) {
163 ent
= getservbyname("dhcpv6-client", "udp");
165 local_port
= htons(546);
167 local_port
= ent
->s_port
;
170 if (remote_port
== 0) {
171 ent
= getservbyname("dhcpv6-server", "udp");
173 remote_port
= htons(547);
175 remote_port
= ent
->s_port
;
178 memset(&DHCPv6DestAddr
, 0, sizeof(DHCPv6DestAddr
));
179 DHCPv6DestAddr
.sin6_family
= AF_INET6
;
180 DHCPv6DestAddr
.sin6_port
= remote_port
;
181 if (inet_pton(AF_INET6
, All_DHCP_Relay_Agents_and_Servers
,
182 &DHCPv6DestAddr
.sin6_addr
) <= 0) {
183 log_fatal("Bad address %s", All_DHCP_Relay_Agents_and_Servers
);
187 if (!option_code_hash_lookup(&clientid_option
,
188 dhcpv6_universe
.code_hash
, &code
, 0, MDL
))
189 log_fatal("Unable to find the CLIENTID option definition.");
191 code
= D6O_ELAPSED_TIME
;
192 if (!option_code_hash_lookup(&elapsed_option
,
193 dhcpv6_universe
.code_hash
, &code
, 0, MDL
))
194 log_fatal("Unable to find the ELAPSED_TIME option definition.");
197 if (!option_code_hash_lookup(&ia_na_option
, dhcpv6_universe
.code_hash
,
199 log_fatal("Unable to find the IA_NA option definition.");
202 if (!option_code_hash_lookup(&ia_ta_option
, dhcpv6_universe
.code_hash
,
204 log_fatal("Unable to find the IA_TA option definition.");
207 if (!option_code_hash_lookup(&ia_pd_option
, dhcpv6_universe
.code_hash
,
209 log_fatal("Unable to find the IA_PD option definition.");
212 if (!option_code_hash_lookup(&iaaddr_option
, dhcpv6_universe
.code_hash
,
214 log_fatal("Unable to find the IAADDR option definition.");
217 if (!option_code_hash_lookup(&iaprefix_option
,
218 dhcpv6_universe
.code_hash
,
220 log_fatal("Unable to find the IAPREFIX option definition.");
223 if (!option_code_hash_lookup(&oro_option
, dhcpv6_universe
.code_hash
,
225 log_fatal("Unable to find the ORO option definition.");
227 code
= D6O_INFORMATION_REFRESH_TIME
;
228 if (!option_code_hash_lookup(&irt_option
, dhcpv6_universe
.code_hash
,
230 log_fatal("Unable to find the IRT option definition.");
232 #ifndef __CYGWIN32__ /* XXX */
238 * Instead of implementing RFC3315 RAND (section 14) as a float "between"
239 * -0.1 and 0.1 non-inclusive, we implement it as an integer.
241 * The result is expected to follow this table:
244 * - ERROR - base <= 0
245 * 0 1 0..0 1 <= base <= 10
246 * 1 3 -1..1 11 <= base <= 20
247 * 2 5 -2..2 21 <= base <= 30
248 * 3 7 -3..3 31 <= base <= 40
251 * XXX: For this to make sense, we really need to do timing on a
252 * XXX: usec scale...we currently can assume zero for any value less than
253 * XXX: 11, which are very common in early stages of transmission for most
264 * A zero or less timeout is a bad thing...we don't want to
268 log_fatal("Impossible condition at %s:%d.", MDL
);
271 * The first thing we do is count how many random integers we want
272 * in either direction (best thought of as the maximum negative
273 * integer, as we will subtract this potentially from a random 0).
275 split
= (base
- 1) / 10;
277 /* Don't bother with the rest of the math if we know we'll get 0. */
282 * Then we count the total number of integers in this set. This
283 * is twice the number of integers in positive and negative
284 * directions, plus zero (-1, 0, 1 is 3, -2..2 adds 2 to 5, so forth).
286 range
= (split
* 2) + 1;
288 /* Take a random number from [0..(range-1)]. */
292 /* Offset it to uncover potential negative values. */
298 /* Initialize message exchange timers (set RT from Initial-RT). */
300 dhc6_retrans_init(struct client_state
*client
)
304 /* Initialize timers. */
306 client
->RT
= client
->IRT
+ dhc6_rand(client
->IRT
);
308 /* Generate a new random 24-bit transaction ID for this exchange. */
310 #if (RAND_MAX >= 0x00ffffff)
312 #elif (RAND_MAX >= 0x0000ffff)
313 xid
= (random() << 16) ^ random();
314 #elif (RAND_MAX >= 0x000000ff)
315 xid
= (random() << 16) ^ (random() << 8) ^ random();
317 # error "Random number generator of less than 8 bits not supported."
320 client
->dhcpv6_transaction_id
[0] = (xid
>> 16) & 0xff;
321 client
->dhcpv6_transaction_id
[1] = (xid
>> 8) & 0xff;
322 client
->dhcpv6_transaction_id
[2] = xid
& 0xff;
325 /* Advance the DHCPv6 retransmission state once. */
327 dhc6_retrans_advance(struct client_state
*client
)
329 struct timeval elapsed
, elapsed_plus_rt
;
331 /* elapsed = cur - start */
332 elapsed
.tv_sec
= cur_tv
.tv_sec
- client
->start_time
.tv_sec
;
333 elapsed
.tv_usec
= cur_tv
.tv_usec
- client
->start_time
.tv_usec
;
334 if (elapsed
.tv_usec
< 0) {
336 elapsed
.tv_usec
+= 1000000;
338 /* retrans_advance is called after consuming client->RT. */
340 elapsed
.tv_sec
+= client
->RT
/ 100;
341 elapsed
.tv_usec
+= (client
->RT
% 100) * 10000;
342 if (elapsed
.tv_usec
>= 1000000) {
344 elapsed
.tv_usec
-= 1000000;
347 * Save what the time will be after the current RT to determine
348 * what the delta to MRD will be.
350 elapsed_plus_rt
.tv_sec
= elapsed
.tv_sec
;
351 elapsed_plus_rt
.tv_usec
= elapsed
.tv_usec
;
354 * RT for each subsequent message transmission is based on the previous
357 * RT = 2*RTprev + RAND*RTprev
359 client
->RT
+= client
->RT
+ dhc6_rand(client
->RT
);
362 * MRT specifies an upper bound on the value of RT (disregarding the
363 * randomization added by the use of RAND). If MRT has a value of 0,
364 * there is no upper limit on the value of RT. Otherwise:
367 * RT = MRT + RAND*MRT
369 if ((client
->MRT
!= 0) && (client
->RT
> client
->MRT
))
370 client
->RT
= client
->MRT
+ dhc6_rand(client
->MRT
);
373 * Further, if there's an MRD, we should wake up upon reaching
374 * the MRD rather than at some point after it.
376 if (client
->MRD
== 0) {
381 /* elapsed += client->RT */
382 elapsed
.tv_sec
+= client
->RT
/ 100;
383 elapsed
.tv_usec
+= (client
->RT
% 100) * 10000;
384 if (elapsed
.tv_usec
>= 1000000) {
386 elapsed
.tv_usec
-= 1000000;
388 if (elapsed
.tv_sec
>= client
->MRD
) {
390 * The desired RT is the time that will be remaining in MRD
391 * when the current timeout finishes. We then have
392 * desired RT = MRD - (elapsed time + previous RT); or
393 * desired RT = MRD - elapsed_plut_rt;
395 client
->RT
= client
->MRD
- elapsed_plus_rt
.tv_sec
;
396 client
->RT
= (client
->RT
* 100) -
397 (elapsed_plus_rt
.tv_usec
/ 10000);
404 /* Quick validation of DHCPv6 ADVERTISE packet contents. */
406 valid_reply(struct packet
*packet
, struct client_state
*client
)
408 struct data_string sid
, cid
;
409 struct option_cache
*oc
;
412 memset(&sid
, 0, sizeof(sid
));
413 memset(&cid
, 0, sizeof(cid
));
415 if (!lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
)) {
416 log_error("Response without a server identifier received.");
420 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_CLIENTID
);
422 !evaluate_option_cache(&sid
, packet
, NULL
, client
, packet
->options
,
423 client
->sent_options
, &global_scope
, oc
,
425 log_error("Response without a client identifier.");
429 oc
= lookup_option(&dhcpv6_universe
, client
->sent_options
,
432 !evaluate_option_cache(&cid
, packet
, NULL
, client
,
433 client
->sent_options
, NULL
, &global_scope
,
435 log_error("Local client identifier is missing!");
440 sid
.len
!= cid
.len
||
441 memcmp(sid
.data
, cid
.data
, sid
.len
)) {
442 log_error("Advertise with matching transaction ID, but "
443 "mismatching client id.");
447 /* clean up pointers to the strings */
448 if (sid
.data
!= NULL
)
449 data_string_forget(&sid
, MDL
);
450 if (cid
.data
!= NULL
)
451 data_string_forget(&cid
, MDL
);
457 * Create a complete copy of a DHCPv6 lease structure.
459 static struct dhc6_lease
*
460 dhc6_dup_lease(struct dhc6_lease
*lease
, const char *file
, int line
)
462 struct dhc6_lease
*copy
;
463 struct dhc6_ia
**insert_ia
, *ia
;
465 copy
= dmalloc(sizeof(*copy
), file
, line
);
467 log_error("Out of memory for v6 lease structure.");
471 data_string_copy(©
->server_id
, &lease
->server_id
, file
, line
);
472 copy
->pref
= lease
->pref
;
474 memcpy(copy
->dhcpv6_transaction_id
, lease
->dhcpv6_transaction_id
,
475 sizeof(copy
->dhcpv6_transaction_id
));
477 option_state_reference(©
->options
, lease
->options
, file
, line
);
479 insert_ia
= ©
->bindings
;
480 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
481 *insert_ia
= dhc6_dup_ia(ia
, file
, line
);
483 if (*insert_ia
== NULL
) {
484 dhc6_lease_destroy(©
, file
, line
);
488 insert_ia
= &(*insert_ia
)->next
;
495 * Duplicate an IA structure.
497 static struct dhc6_ia
*
498 dhc6_dup_ia(struct dhc6_ia
*ia
, const char *file
, int line
)
500 struct dhc6_ia
*copy
;
501 struct dhc6_addr
**insert_addr
, *addr
;
503 copy
= dmalloc(sizeof(*ia
), file
, line
);
505 log_error("Out of memory for v6 duplicate IA structure.");
509 memcpy(copy
->iaid
, ia
->iaid
, sizeof(copy
->iaid
));
511 copy
->ia_type
= ia
->ia_type
;
512 copy
->starts
= ia
->starts
;
513 copy
->renew
= ia
->renew
;
514 copy
->rebind
= ia
->rebind
;
516 insert_addr
= ©
->addrs
;
517 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
518 *insert_addr
= dhc6_dup_addr(addr
, file
, line
);
520 if (*insert_addr
== NULL
) {
521 dhc6_ia_destroy(©
, file
, line
);
525 insert_addr
= &(*insert_addr
)->next
;
528 if (ia
->options
!= NULL
)
529 option_state_reference(©
->options
, ia
->options
,
536 * Duplicate an IAADDR or IAPREFIX structure.
538 static struct dhc6_addr
*
539 dhc6_dup_addr(struct dhc6_addr
*addr
, const char *file
, int line
)
541 struct dhc6_addr
*copy
;
543 copy
= dmalloc(sizeof(*addr
), file
, line
);
548 memcpy(©
->address
, &addr
->address
, sizeof(copy
->address
));
550 copy
->plen
= addr
->plen
;
551 copy
->flags
= addr
->flags
;
552 copy
->starts
= addr
->starts
;
553 copy
->preferred_life
= addr
->preferred_life
;
554 copy
->max_life
= addr
->max_life
;
556 if (addr
->options
!= NULL
)
557 option_state_reference(©
->options
, addr
->options
,
564 * Form a DHCPv6 lease structure based upon packet contents. Creates and
565 * populates IA's and any IAADDR/IAPREFIX's they contain.
566 * Parsed options are deleted in order to not save them in the lease file.
568 * If we get a status code of NoAddrs or NoPrefix we toss the affected
569 * IAs. If it as at the top level we toss all IAs of that type. If it
570 * is in an IA we only toss that one. According to the spec we shouldn't
571 * get a NoPrefix status at the top level but we will allow it.
574 static struct dhc6_lease
*
575 dhc6_leaseify(struct packet
*packet
)
577 struct data_string ds
;
578 struct dhc6_lease
*lease
;
579 struct option_cache
*oc
;
582 lease
= dmalloc(sizeof(*lease
), MDL
);
584 log_error("Out of memory for v6 lease structure.");
588 memcpy(lease
->dhcpv6_transaction_id
, packet
->dhcpv6_transaction_id
, 3);
589 option_state_reference(&lease
->options
, packet
->options
, MDL
);
591 memset(&ds
, 0, sizeof(ds
));
593 /* Determine preference (default zero). */
594 oc
= lookup_option(&dhcpv6_universe
, lease
->options
, D6O_PREFERENCE
);
596 evaluate_option_cache(&ds
, packet
, NULL
, NULL
, lease
->options
,
597 NULL
, &global_scope
, oc
, MDL
)) {
599 log_error("Invalid length of DHCPv6 Preference option "
600 "(%d != 1)", ds
.len
);
601 data_string_forget(&ds
, MDL
);
602 dhc6_lease_destroy(&lease
, MDL
);
605 lease
->pref
= ds
.data
[0];
606 log_debug("RCV: X-- Preference %u.",
607 (unsigned)lease
->pref
);
610 data_string_forget(&ds
, MDL
);
612 delete_option(&dhcpv6_universe
, lease
->options
, D6O_PREFERENCE
);
614 /* Get the top level status code. If the code is NoAddrsAvail
615 * or NoPrefixAvail strip it from the options as we don't
616 * want it to show up in check_[advertise reply]. We
617 * pass it along to the parse_ia_xx routines and they
618 * will drop the affected IAs for NoAddrs or NoPrefix,
619 * other status codes will be ignored and handled by
620 * the check_[advertise reply] routines.
622 code
= STATUS_Success
;
623 if ((dhc6_get_status_code(lease
->options
, &code
, NULL
) == ISC_R_SUCCESS
)
625 ((code
== STATUS_NoAddrsAvail
) || (code
== STATUS_NoPrefixAvail
))) {
626 delete_option(&dhcpv6_universe
, lease
->options
,
631 * Dig into recursive DHCPv6 pockets for IA_NA and contained IAADDR
634 if (dhc6_parse_ia_na(&lease
->bindings
, packet
,
635 lease
->options
, code
) != ISC_R_SUCCESS
) {
636 /* Error conditions are logged by the caller. */
637 dhc6_lease_destroy(&lease
, MDL
);
641 * Dig into recursive DHCPv6 pockets for IA_TA and contained IAADDR
644 if (dhc6_parse_ia_ta(&lease
->bindings
, packet
,
645 lease
->options
, code
) != ISC_R_SUCCESS
) {
646 /* Error conditions are logged by the caller. */
647 dhc6_lease_destroy(&lease
, MDL
);
651 * Dig into recursive DHCPv6 pockets for IA_PD and contained IAPREFIX
654 if (dhc6_parse_ia_pd(&lease
->bindings
, packet
,
655 lease
->options
, code
) != ISC_R_SUCCESS
) {
656 /* Error conditions are logged by the caller. */
657 dhc6_lease_destroy(&lease
, MDL
);
662 * This is last because in the future we may want to make a different
663 * key based upon additional information from the packet (we may need
664 * to allow multiple leases in one client state per server, but we're
665 * not sure based on what additional keys now).
667 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
669 !evaluate_option_cache(&lease
->server_id
, packet
, NULL
, NULL
,
670 lease
->options
, NULL
, &global_scope
,
672 lease
->server_id
.len
== 0) {
673 /* This should be impossible due to validation checks earlier.
675 log_error("Invalid SERVERID option cache.");
676 dhc6_lease_destroy(&lease
, MDL
);
679 log_debug("RCV: X-- Server ID: %s",
680 print_hex_1(lease
->server_id
.len
,
681 lease
->server_id
.data
, 52));
688 dhc6_parse_ia_na(struct dhc6_ia
**pia
, struct packet
*packet
,
689 struct option_state
*options
, unsigned code
)
691 struct data_string ds
;
693 struct option_cache
*oc
;
697 memset(&ds
, 0, sizeof(ds
));
699 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IA_NA
);
700 for ( ; oc
!= NULL
; oc
= oc
->next
) {
701 ia
= dmalloc(sizeof(*ia
), MDL
);
703 log_error("Out of memory allocating IA_NA structure.");
704 return ISC_R_NOMEMORY
;
705 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
707 &global_scope
, oc
, MDL
) &&
709 memcpy(ia
->iaid
, ds
.data
, 4);
710 ia
->ia_type
= D6O_IA_NA
;
711 ia
->starts
= cur_time
;
712 ia
->renew
= getULong(ds
.data
+ 4);
713 ia
->rebind
= getULong(ds
.data
+ 8);
715 log_debug("RCV: X-- IA_NA %s",
716 print_hex_1(4, ia
->iaid
, 59));
717 /* XXX: This should be the printed time I think. */
718 log_debug("RCV: | X-- starts %u",
719 (unsigned)ia
->starts
);
720 log_debug("RCV: | X-- t1 - renew +%u", ia
->renew
);
721 log_debug("RCV: | X-- t2 - rebind +%u", ia
->rebind
);
724 * RFC3315 section 22.4, discard IA_NA's that
725 * have t1 greater than t2, and both not zero.
726 * Since RFC3315 defines this behaviour, it is not
727 * an error - just normal operation.
729 * Note that RFC3315 says we MUST honor these values
730 * if they are not zero. So insane values are
733 if ((ia
->renew
> 0) && (ia
->rebind
> 0) &&
734 (ia
->renew
> ia
->rebind
)) {
735 log_debug("RCV: | !-- INVALID renew/rebind "
736 "times, IA_NA discarded.");
738 data_string_forget(&ds
, MDL
);
743 log_debug("RCV: | X-- [Options]");
745 if (!option_state_allocate(&ia
->options
,
747 log_error("Out of memory allocating "
748 "IA_NA option state.");
750 data_string_forget(&ds
, MDL
);
751 return ISC_R_NOMEMORY
;
754 if (!parse_option_buffer(ia
->options
,
758 log_error("Corrupt IA_NA options.");
759 option_state_dereference(&ia
->options
,
762 data_string_forget(&ds
, MDL
);
763 return DHCP_R_BADPARSE
;
766 data_string_forget(&ds
, MDL
);
768 if (ia
->options
!= NULL
) {
769 result
= dhc6_parse_addrs(&ia
->addrs
, packet
,
771 if (result
!= ISC_R_SUCCESS
) {
772 option_state_dereference(&ia
->options
,
779 /* If we have no addresses or the top level status code
780 * or the status code in this IA indicate no addresses
783 ia_code
= STATUS_Success
;
784 if ((ia
->addrs
== NULL
) ||
785 (code
== STATUS_NoAddrsAvail
) ||
786 ((ia
->options
!= NULL
) &&
787 (dhc6_get_status_code(ia
->options
, &ia_code
, NULL
)
789 (ia_code
== STATUS_NoAddrsAvail
))) {
790 log_debug("RCV: | !-- Status code of "
791 "no addrs, IA_NA discarded.");
792 dhc6_ia_destroy(&ia
, MDL
);
801 log_error("Invalid IA_NA option cache.");
804 data_string_forget(&ds
, MDL
);
805 return ISC_R_UNEXPECTED
;
808 delete_option(&dhcpv6_universe
, options
, D6O_IA_NA
);
810 return ISC_R_SUCCESS
;
814 dhc6_parse_ia_ta(struct dhc6_ia
**pia
, struct packet
*packet
,
815 struct option_state
*options
, unsigned code
)
817 struct data_string ds
;
819 struct option_cache
*oc
;
823 memset(&ds
, 0, sizeof(ds
));
825 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IA_TA
);
826 for ( ; oc
!= NULL
; oc
= oc
->next
) {
827 ia
= dmalloc(sizeof(*ia
), MDL
);
829 log_error("Out of memory allocating IA_TA structure.");
830 return ISC_R_NOMEMORY
;
831 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
833 &global_scope
, oc
, MDL
) &&
835 memcpy(ia
->iaid
, ds
.data
, 4);
836 ia
->ia_type
= D6O_IA_TA
;
837 ia
->starts
= cur_time
;
839 log_debug("RCV: X-- IA_TA %s",
840 print_hex_1(4, ia
->iaid
, 59));
841 /* XXX: This should be the printed time I think. */
842 log_debug("RCV: | X-- starts %u",
843 (unsigned)ia
->starts
);
846 log_debug("RCV: | X-- [Options]");
848 if (!option_state_allocate(&ia
->options
,
850 log_error("Out of memory allocating "
851 "IA_TA option state.");
853 data_string_forget(&ds
, MDL
);
854 return ISC_R_NOMEMORY
;
857 if (!parse_option_buffer(ia
->options
,
861 log_error("Corrupt IA_TA options.");
862 option_state_dereference(&ia
->options
,
865 data_string_forget(&ds
, MDL
);
866 return DHCP_R_BADPARSE
;
869 data_string_forget(&ds
, MDL
);
871 if (ia
->options
!= NULL
) {
872 result
= dhc6_parse_addrs(&ia
->addrs
, packet
,
874 if (result
!= ISC_R_SUCCESS
) {
875 option_state_dereference(&ia
->options
,
882 /* If we have no addresses or the top level status code
883 * or the status code in this IA indicate no addresses
886 ia_code
= STATUS_Success
;
887 if ((ia
->addrs
== NULL
) ||
888 (code
== STATUS_NoAddrsAvail
) ||
889 ((ia
->options
!= NULL
) &&
890 (dhc6_get_status_code(ia
->options
, &ia_code
, NULL
)
892 (ia_code
== STATUS_NoAddrsAvail
))) {
893 log_debug("RCV: | !-- Status code of "
894 "no addrs, IA_TA discarded.");
895 dhc6_ia_destroy(&ia
, MDL
);
904 log_error("Invalid IA_TA option cache.");
907 data_string_forget(&ds
, MDL
);
908 return ISC_R_UNEXPECTED
;
911 delete_option(&dhcpv6_universe
, options
, D6O_IA_TA
);
913 return ISC_R_SUCCESS
;
917 dhc6_parse_ia_pd(struct dhc6_ia
**pia
, struct packet
*packet
,
918 struct option_state
*options
, unsigned code
)
920 struct data_string ds
;
922 struct option_cache
*oc
;
926 memset(&ds
, 0, sizeof(ds
));
928 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IA_PD
);
929 for ( ; oc
!= NULL
; oc
= oc
->next
) {
930 ia
= dmalloc(sizeof(*ia
), MDL
);
932 log_error("Out of memory allocating IA_PD structure.");
933 return ISC_R_NOMEMORY
;
934 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
936 &global_scope
, oc
, MDL
) &&
938 memcpy(ia
->iaid
, ds
.data
, 4);
939 ia
->ia_type
= D6O_IA_PD
;
940 ia
->starts
= cur_time
;
941 ia
->renew
= getULong(ds
.data
+ 4);
942 ia
->rebind
= getULong(ds
.data
+ 8);
944 log_debug("RCV: X-- IA_PD %s",
945 print_hex_1(4, ia
->iaid
, 59));
946 /* XXX: This should be the printed time I think. */
947 log_debug("RCV: | X-- starts %u",
948 (unsigned)ia
->starts
);
949 log_debug("RCV: | X-- t1 - renew +%u", ia
->renew
);
950 log_debug("RCV: | X-- t2 - rebind +%u", ia
->rebind
);
953 * RFC3633 section 9, discard IA_PD's that
954 * have t1 greater than t2, and both not zero.
955 * Since RFC3633 defines this behaviour, it is not
956 * an error - just normal operation.
958 if ((ia
->renew
> 0) && (ia
->rebind
> 0) &&
959 (ia
->renew
> ia
->rebind
)) {
960 log_debug("RCV: | !-- INVALID renew/rebind "
961 "times, IA_PD discarded.");
963 data_string_forget(&ds
, MDL
);
968 log_debug("RCV: | X-- [Options]");
970 if (!option_state_allocate(&ia
->options
,
972 log_error("Out of memory allocating "
973 "IA_PD option state.");
975 data_string_forget(&ds
, MDL
);
976 return ISC_R_NOMEMORY
;
979 if (!parse_option_buffer(ia
->options
,
983 log_error("Corrupt IA_PD options.");
984 option_state_dereference(&ia
->options
,
987 data_string_forget(&ds
, MDL
);
988 return DHCP_R_BADPARSE
;
991 data_string_forget(&ds
, MDL
);
993 if (ia
->options
!= NULL
) {
994 result
= dhc6_parse_prefixes(&ia
->addrs
,
997 if (result
!= ISC_R_SUCCESS
) {
998 option_state_dereference(&ia
->options
,
1005 /* If we have no prefixes or the top level status code
1006 * or the status code in this IA indicate no prefixes
1009 ia_code
= STATUS_Success
;
1010 if ((ia
->addrs
== NULL
) ||
1011 (code
== STATUS_NoPrefixAvail
) ||
1012 ((ia
->options
!= NULL
) &&
1013 (dhc6_get_status_code(ia
->options
, &ia_code
, NULL
)
1014 == ISC_R_SUCCESS
) &&
1015 (ia_code
== STATUS_NoPrefixAvail
))) {
1016 log_debug("RCV: | !-- Status code of "
1017 "no prefix, IA_PD discarded.");
1018 dhc6_ia_destroy(&ia
, MDL
);
1022 while (*pia
!= NULL
)
1023 pia
= &(*pia
)->next
;
1027 log_error("Invalid IA_PD option cache.");
1030 data_string_forget(&ds
, MDL
);
1031 return ISC_R_UNEXPECTED
;
1034 delete_option(&dhcpv6_universe
, options
, D6O_IA_PD
);
1036 return ISC_R_SUCCESS
;
1041 dhc6_parse_addrs(struct dhc6_addr
**paddr
, struct packet
*packet
,
1042 struct option_state
*options
)
1044 struct data_string ds
;
1045 struct option_cache
*oc
;
1046 struct dhc6_addr
*addr
;
1047 isc_result_t rval
= ISC_R_SUCCESS
;
1050 memset(&ds
, 0, sizeof(ds
));
1052 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IAADDR
);
1053 for ( ; oc
!= NULL
; oc
= oc
->next
) {
1054 addr
= dmalloc(sizeof(*addr
), MDL
);
1056 log_error("Out of memory allocating "
1057 "address structure.");
1058 return ISC_R_NOMEMORY
;
1059 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
1060 options
, NULL
, &global_scope
,
1064 addr
->address
.len
= 16;
1065 memcpy(addr
->address
.iabuf
, ds
.data
, 16);
1066 addr
->starts
= cur_time
;
1067 addr
->preferred_life
= getULong(ds
.data
+ 16);
1068 addr
->max_life
= getULong(ds
.data
+ 20);
1070 log_debug("RCV: | | X-- IAADDR %s",
1071 piaddr(addr
->address
));
1072 log_debug("RCV: | | | X-- Preferred lifetime %u.",
1073 addr
->preferred_life
);
1074 log_debug("RCV: | | | X-- Max lifetime %u.",
1078 * RFC 3315 section 22.6 says we must discard
1079 * addresses whose pref is later than valid.
1081 if ((addr
->preferred_life
> addr
->max_life
)) {
1082 log_debug("RCV: | | | !-- INVALID lifetimes, "
1083 "IAADDR discarded. Check your "
1084 "server configuration.");
1086 data_string_forget(&ds
, MDL
);
1091 * Fortunately this is the last recursion in the
1095 if (!option_state_allocate(&addr
->options
,
1097 log_error("Out of memory allocating "
1098 "IAADDR option state.");
1100 data_string_forget(&ds
, MDL
);
1101 return ISC_R_NOMEMORY
;
1104 if (!parse_option_buffer(addr
->options
,
1107 &dhcpv6_universe
)) {
1108 log_error("Corrupt IAADDR options.");
1109 option_state_dereference(&addr
->options
,
1112 data_string_forget(&ds
, MDL
);
1113 return DHCP_R_BADPARSE
;
1117 data_string_forget(&ds
, MDL
);
1119 if (addr
->options
!= NULL
) {
1120 log_debug("RCV: | | | X-- [Options]");
1122 /* Get the status code if the return value
1123 * indicates an error or the status code
1124 * indicates no address toss the address
1126 code
= STATUS_Success
;
1127 rval
= dhc6_check_status(ISC_R_SUCCESS
,
1130 if (rval
!= ISC_R_SUCCESS
) {
1131 log_debug("RCV: | | | X-- Status code"
1132 " issue, IAADDR discarded.");
1133 option_state_dereference(&addr
->options
,
1141 paddr
= &addr
->next
;
1143 log_error("Invalid IAADDR option cache.");
1146 data_string_forget(&ds
, MDL
);
1147 return ISC_R_UNEXPECTED
;
1150 delete_option(&dhcpv6_universe
, options
, D6O_IAADDR
);
1152 return ISC_R_SUCCESS
;
1156 dhc6_parse_prefixes(struct dhc6_addr
**ppfx
, struct packet
*packet
,
1157 struct option_state
*options
)
1159 struct data_string ds
;
1160 struct option_cache
*oc
;
1161 struct dhc6_addr
*pfx
;
1162 isc_result_t rval
= ISC_R_SUCCESS
;
1165 memset(&ds
, 0, sizeof(ds
));
1167 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_IAPREFIX
);
1168 for ( ; oc
!= NULL
; oc
= oc
->next
) {
1169 pfx
= dmalloc(sizeof(*pfx
), MDL
);
1171 log_error("Out of memory allocating "
1172 "prefix structure.");
1173 return ISC_R_NOMEMORY
;
1174 } else if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
1175 options
, NULL
, &global_scope
,
1179 pfx
->preferred_life
= getULong(ds
.data
);
1180 pfx
->max_life
= getULong(ds
.data
+ 4);
1181 pfx
->plen
= getUChar(ds
.data
+ 8);
1182 pfx
->address
.len
= 16;
1183 memcpy(pfx
->address
.iabuf
, ds
.data
+ 9, 16);
1184 pfx
->starts
= cur_time
;
1186 log_debug("RCV: | | X-- IAPREFIX %s/%d",
1187 piaddr(pfx
->address
), (int)pfx
->plen
);
1188 log_debug("RCV: | | | X-- Preferred lifetime %u.",
1189 pfx
->preferred_life
);
1190 log_debug("RCV: | | | X-- Max lifetime %u.",
1193 /* Sanity check over the prefix length */
1194 if ((pfx
->plen
< 4) || (pfx
->plen
> 128)) {
1195 log_debug("RCV: | | | !-- INVALID prefix "
1196 "length, IAPREFIX discarded. "
1197 "Check your server configuration.");
1199 data_string_forget(&ds
, MDL
);
1203 * RFC 3633 section 10 says we must discard
1204 * prefixes whose pref is later than valid.
1206 if ((pfx
->preferred_life
> pfx
->max_life
)) {
1207 log_debug("RCV: | | | !-- INVALID lifetimes, "
1208 "IAPREFIX discarded. Check your "
1209 "server configuration.");
1211 data_string_forget(&ds
, MDL
);
1216 * Fortunately this is the last recursion in the
1220 if (!option_state_allocate(&pfx
->options
,
1222 log_error("Out of memory allocating "
1223 "IAPREFIX option state.");
1225 data_string_forget(&ds
, MDL
);
1226 return ISC_R_NOMEMORY
;
1229 if (!parse_option_buffer(pfx
->options
,
1232 &dhcpv6_universe
)) {
1233 log_error("Corrupt IAPREFIX options.");
1234 option_state_dereference(&pfx
->options
,
1237 data_string_forget(&ds
, MDL
);
1238 return DHCP_R_BADPARSE
;
1242 data_string_forget(&ds
, MDL
);
1244 if (pfx
->options
!= NULL
) {
1245 log_debug("RCV: | | | X-- [Options]");
1247 /* Get the status code if the return value
1248 * indicates an error or the status code
1249 * indicates no prefix toss the prefix
1251 code
= STATUS_Success
;
1252 rval
= dhc6_check_status(ISC_R_SUCCESS
,
1255 if (rval
!= ISC_R_SUCCESS
) {
1256 log_debug("RCV: | | | X-- Status code"
1257 " issue IAPREFIX discarded.");
1258 option_state_dereference(&pfx
->options
,
1268 log_error("Invalid IAPREFIX option cache.");
1271 data_string_forget(&ds
, MDL
);
1272 return ISC_R_UNEXPECTED
;
1275 delete_option(&dhcpv6_universe
, options
, D6O_IAPREFIX
);
1277 return ISC_R_SUCCESS
;
1280 /* Clean up a lease object, deallocate all its parts, and set it to NULL. */
1282 dhc6_lease_destroy(struct dhc6_lease
**src
, const char *file
, int line
)
1284 struct dhc6_ia
*ia
, *nia
;
1285 struct dhc6_lease
*lease
;
1287 if (src
== NULL
|| *src
== NULL
) {
1288 log_error("Attempt to destroy null lease.");
1293 if (lease
->server_id
.len
!= 0)
1294 data_string_forget(&lease
->server_id
, file
, line
);
1296 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= nia
) {
1299 dhc6_ia_destroy(&ia
, file
, line
);
1302 if (lease
->options
!= NULL
)
1303 option_state_dereference(&lease
->options
, file
, line
);
1305 dfree(lease
, file
, line
);
1310 * Traverse the addresses list, and destroy their contents, and NULL the
1314 dhc6_ia_destroy(struct dhc6_ia
**src
, const char *file
, int line
)
1316 struct dhc6_addr
*addr
, *naddr
;
1319 if (src
== NULL
|| *src
== NULL
) {
1320 log_error("Attempt to destroy null IA.");
1325 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= naddr
) {
1328 if (addr
->options
!= NULL
)
1329 option_state_dereference(&addr
->options
, file
, line
);
1331 dfree(addr
, file
, line
);
1334 if (ia
->options
!= NULL
)
1335 option_state_dereference(&ia
->options
, file
, line
);
1337 dfree(ia
, file
, line
);
1342 * For a given lease, insert it into the tail of the lease list. Upon
1343 * finding a duplicate by server id, remove it and take over its position.
1346 insert_lease(struct dhc6_lease
**head
, struct dhc6_lease
*new)
1348 while (*head
!= NULL
) {
1349 if ((*head
)->server_id
.len
== new->server_id
.len
&&
1350 memcmp((*head
)->server_id
.data
, new->server_id
.data
,
1351 new->server_id
.len
) == 0) {
1352 new->next
= (*head
)->next
;
1353 dhc6_lease_destroy(head
, MDL
);
1357 head
= &(*head
)->next
;
1366 * \brief Determine a score for a lease. We use this to
1367 * compare and choose leases if we receive multiple candidates.
1369 * We originally started with scores of 50 for a binding and 100 for
1370 * an address. This would select multiple adresses over multiple
1371 * bindings. As part of the 7550 work I've changed this to be
1372 * 10000 for a binding, 100 for an address and 1 for an option.
1373 * This will cause us to choose a lease with more bindings over
1374 * a lease with less bindings but more addresses which seems
1375 * to be the best selection criteria to me.
1376 * In theory we could end up with a lease with enough addresses
1377 * or options being better but at 100 to 1 I don't think it's likely.
1379 * \param client = the state of the entire client
1380 * \param lease = the lease to score.
1382 * \retrun the score of the lease
1385 /* The scores for individual items. */
1386 #ifdef USE_ORIGINAL_CLIENT_LEASE_WEIGHTS
1387 #define SCORE_BINDING 50
1388 #define SCORE_ADDRESS 100
1390 #define SCORE_BINDING 10000
1391 #define SCORE_ADDRESS 100
1394 #define SCORE_OPTION 1
1395 /* We need a lease with at least 1 binding and 1 address */
1396 #define SCORE_MIN (SCORE_BINDING + SCORE_ADDRESS)
1399 dhc6_score_lease(struct client_state
*client
, struct dhc6_lease
*lease
)
1402 struct dhc6_addr
*addr
;
1403 struct option
**req
;
1407 return lease
->score
;
1409 lease
->score
= SCORE_OPTION
;
1411 /* If this lease lacks a required option, dump it. */
1412 /* XXX: we should be able to cache the failure... */
1413 req
= client
->config
->required_options
;
1415 for (i
= 0 ; req
[i
] != NULL
; i
++) {
1416 if (lookup_option(&dhcpv6_universe
, lease
->options
,
1417 req
[i
]->code
) == NULL
) {
1419 return lease
->score
;
1424 /* If this lease contains a requested option, improve its score. */
1425 req
= client
->config
->requested_options
;
1427 for (i
= 0 ; req
[i
] != NULL
; i
++) {
1428 if (lookup_option(&dhcpv6_universe
, lease
->options
,
1429 req
[i
]->code
) != NULL
)
1430 lease
->score
+= SCORE_OPTION
;
1434 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
1435 lease
->score
+= SCORE_BINDING
;
1437 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
1438 lease
->score
+= SCORE_ADDRESS
;
1442 return lease
->score
;
1446 * start_init6() kicks off the process, transmitting a packet and
1447 * scheduling a retransmission event.
1450 start_init6(struct client_state
*client
)
1454 log_debug("PRC: Soliciting for leases (INIT).");
1455 client
->state
= S_INIT
;
1457 /* Initialize timers, RFC3315 section 17.1.2. */
1458 client
->IRT
= SOL_TIMEOUT
* 100;
1459 client
->MRT
= SOL_MAX_RT
* 100;
1461 /* Default is 0 (no max) but -1 changes this. */
1465 client
->MRD
= client
->config
->timeout
;
1467 dhc6_retrans_init(client
);
1470 * RFC3315 section 17.1.2 goes out of its way:
1471 * Also, the first RT MUST be selected to be strictly greater than IRT
1472 * by choosing RAND to be strictly greater than 0.
1474 /* if RAND < 0 then RAND = -RAND */
1475 if (client
->RT
<= client
->IRT
)
1476 client
->RT
= client
->IRT
+ (client
->IRT
- client
->RT
);
1477 /* if RAND == 0 then RAND = 1 */
1478 if (client
->RT
<= client
->IRT
)
1479 client
->RT
= client
->IRT
+ 1;
1481 client
->v6_handler
= init_handler
;
1484 * RFC3315 section 17.1.2 says we MUST start the first packet
1485 * between 0 and SOL_MAX_DELAY seconds. The good news is
1486 * SOL_MAX_DELAY is 1.
1488 tv
.tv_sec
= cur_tv
.tv_sec
;
1489 tv
.tv_usec
= cur_tv
.tv_usec
;
1490 tv
.tv_usec
+= (random() % (SOL_MAX_DELAY
* 100)) * 10000;
1491 if (tv
.tv_usec
>= 1000000) {
1493 tv
.tv_usec
-= 1000000;
1495 add_timeout(&tv
, do_init6
, client
, NULL
, NULL
);
1502 * start_info_request6() kicks off the process, transmitting an info
1503 * request packet and scheduling a retransmission event.
1506 start_info_request6(struct client_state
*client
)
1510 log_debug("PRC: Requesting information (INIT).");
1511 client
->state
= S_INIT
;
1513 /* Initialize timers, RFC3315 section 18.1.5. */
1514 client
->IRT
= INF_TIMEOUT
* 100;
1515 client
->MRT
= INF_MAX_RT
* 100;
1517 /* Default is 0 (no max) but -1 changes this. */
1521 client
->MRD
= client
->config
->timeout
;
1523 dhc6_retrans_init(client
);
1525 client
->v6_handler
= info_request_handler
;
1528 * RFC3315 section 18.1.5 says we MUST start the first packet
1529 * between 0 and INF_MAX_DELAY seconds. The good news is
1530 * INF_MAX_DELAY is 1.
1532 tv
.tv_sec
= cur_tv
.tv_sec
;
1533 tv
.tv_usec
= cur_tv
.tv_usec
;
1534 tv
.tv_usec
+= (random() % (INF_MAX_DELAY
* 100)) * 10000;
1535 if (tv
.tv_usec
>= 1000000) {
1537 tv
.tv_usec
-= 1000000;
1539 add_timeout(&tv
, do_info_request6
, client
, NULL
, NULL
);
1546 * start_confirm6() kicks off an "init-reboot" version of the process, at
1547 * startup to find out if old bindings are 'fair' and at runtime whenever
1548 * a link cycles state we'll eventually want to do this.
1551 start_confirm6(struct client_state
*client
)
1555 /* If there is no active lease, there is nothing to check. */
1556 if ((client
->active_lease
== NULL
) ||
1557 !active_prefix(client
) ||
1558 client
->active_lease
->released
) {
1559 start_init6(client
);
1563 log_debug("PRC: Confirming active lease (INIT-REBOOT).");
1564 client
->state
= S_REBOOTING
;
1566 /* Initialize timers, RFC3315 section 17.1.3. */
1567 client
->IRT
= CNF_TIMEOUT
* 100;
1568 client
->MRT
= CNF_MAX_RT
* 100;
1570 client
->MRD
= CNF_MAX_RD
;
1572 dhc6_retrans_init(client
);
1574 client
->v6_handler
= reply_handler
;
1577 * RFC3315 section 18.1.2 says we MUST start the first packet
1578 * between 0 and CNF_MAX_DELAY seconds. The good news is
1579 * CNF_MAX_DELAY is 1.
1581 tv
.tv_sec
= cur_tv
.tv_sec
;
1582 tv
.tv_usec
= cur_tv
.tv_usec
;
1583 tv
.tv_usec
+= (random() % (CNF_MAX_DELAY
* 100)) * 10000;
1584 if (tv
.tv_usec
>= 1000000) {
1586 tv
.tv_usec
-= 1000000;
1589 /* We do a rebind instead of a confirm if the user
1590 * is requesting PDs or previously requesed PDs or
1591 * increased the number of NAs or TAs they want
1592 * Confirms don't tell us if PDs are still on-link and
1593 * we won't add new IAs on a confirm.
1596 if ((wanted_ia_pd
!= 0) ||
1597 (dhc6_count_ia(client
->active_lease
, D6O_IA_PD
) != 0) ||
1598 (dhc6_count_ia(client
->active_lease
, D6O_IA_NA
) < wanted_ia_na
) ||
1599 (dhc6_count_ia(client
->active_lease
, D6O_IA_TA
) < wanted_ia_ta
)) {
1600 client
->state
= S_REBINDING
;
1601 client
->refresh_type
= DHCPV6_REBIND
;
1602 add_timeout(&tv
, do_refresh6
, client
, NULL
, NULL
);
1604 add_timeout(&tv
, do_confirm6
, client
, NULL
, NULL
);
1608 * check_timing6() check on the timing for sending a v6 message
1609 * and then do the basic initialization for a v6 message.
1611 #define CHK_TIM_SUCCESS 0
1612 #define CHK_TIM_MRC_EXCEEDED 1
1613 #define CHK_TIM_MRD_EXCEEDED 2
1614 #define CHK_TIM_ALLOC_FAILURE 3
1617 check_timing6 (struct client_state
*client
, u_int8_t msg_type
,
1618 char *msg_str
, struct dhc6_lease
*lease
,
1619 struct data_string
*ds
)
1621 struct timeval elapsed
;
1624 * Start_time starts at the first transmission.
1626 if (client
->txcount
== 0) {
1627 client
->start_time
.tv_sec
= cur_tv
.tv_sec
;
1628 client
->start_time
.tv_usec
= cur_tv
.tv_usec
;
1629 } else if ((client
->MRC
!= 0) && (client
->txcount
> client
->MRC
)) {
1630 log_info("Max retransmission count exceeded.");
1631 return(CHK_TIM_MRC_EXCEEDED
);
1634 /* elapsed = cur - start */
1635 elapsed
.tv_sec
= cur_tv
.tv_sec
- client
->start_time
.tv_sec
;
1636 elapsed
.tv_usec
= cur_tv
.tv_usec
- client
->start_time
.tv_usec
;
1637 if (elapsed
.tv_usec
< 0) {
1638 elapsed
.tv_sec
-= 1;
1639 elapsed
.tv_usec
+= 1000000;
1642 /* Check if finished (-1 argument). */
1643 if ((client
->MRD
!= 0) && (elapsed
.tv_sec
>= client
->MRD
)) {
1644 log_info("Max retransmission duration exceeded.");
1645 return(CHK_TIM_MRD_EXCEEDED
);
1648 memset(ds
, 0, sizeof(*ds
));
1649 if (!buffer_allocate(&(ds
->buffer
), 4, MDL
)) {
1650 log_error("Unable to allocate memory for %s.", msg_str
);
1651 return(CHK_TIM_ALLOC_FAILURE
);
1653 ds
->data
= ds
->buffer
->data
;
1656 ds
->buffer
->data
[0] = msg_type
;
1657 memcpy(ds
->buffer
->data
+ 1, client
->dhcpv6_transaction_id
, 3);
1659 /* Form an elapsed option. */
1660 /* Maximum value is 65535 1/100s coded as 0xffff. */
1661 if ((elapsed
.tv_sec
< 0) || (elapsed
.tv_sec
> 655) ||
1662 ((elapsed
.tv_sec
== 655) && (elapsed
.tv_usec
> 350000))) {
1663 client
->elapsed
= 0xffff;
1665 client
->elapsed
= elapsed
.tv_sec
* 100;
1666 client
->elapsed
+= elapsed
.tv_usec
/ 10000;
1669 if (client
->elapsed
== 0)
1670 log_debug("XMT: Forming %s, 0 ms elapsed.", msg_str
);
1672 log_debug("XMT: Forming %s, %u0 ms elapsed.", msg_str
,
1673 (unsigned)client
->elapsed
);
1675 client
->elapsed
= htons(client
->elapsed
);
1677 make_client6_options(client
, &client
->sent_options
, lease
, msg_type
);
1679 return(CHK_TIM_SUCCESS
);
1684 * \brief Create an iaid from information from the client.
1686 * \param client = the state of the entire client
1687 * \param ia = the ia to fill in
1688 * \param idx = index of the ia in case we are doing multiples
1689 * \param len = length of the base IA (4 for TA, 12 for NA & PD)
1691 * \return ISC_R_SUCCESS - all is well continue, any other return indicates
1692 * an error and the packet should be tossed
1696 dhc6_create_iaid(struct client_state
*client
,
1697 struct data_string
*ia
,
1701 int start_idx
, copy_len
;
1703 memset(ia
, 0, sizeof(*ia
));
1704 if (!buffer_allocate(&ia
->buffer
, 12, MDL
)) {
1705 return (ISC_R_NOMEMORY
);
1707 ia
->data
= ia
->buffer
->data
;
1711 * A simple IAID is the last 4 bytes
1712 * of the hardware address.
1714 if (client
->interface
->hw_address
.hlen
> 4) {
1715 start_idx
= client
->interface
->hw_address
.hlen
- 4;
1719 copy_len
= client
->interface
->hw_address
.hlen
;
1721 memcpy(ia
->buffer
->data
,
1722 client
->interface
->hw_address
.hbuf
+ start_idx
,
1725 ia
->buffer
->data
[3] += idx
;
1727 return (ISC_R_SUCCESS
);
1732 * \brief Add bare IA_NAs, IA_TAs or IA_PDs to the packet we are building.
1734 * Attempt to add the number of bare IAs indicated by wanted to
1735 * the packet. As we have already added a number of IAs based
1736 * on what is in the current lease after we create an IAID we check
1737 * it against the current lease and skip any that are already in use.
1739 * \param client = the state of the entire client
1740 * \param packet = the packet we are building and where we
1741 * shall append the IA_NA, IA_TA or IA_PDs we create
1742 * \param wanted = the number of IA_NA, IA_TA or IA_PDs we want to create
1743 * \param ia_type = the type of the IAs we want to create: NA, TA or PD.
1745 * \return ISC_R_SUCCESS - all is well continue, any other return indicates
1746 * an error and the packet should be tossed
1749 dhc6_bare_ia_xx(struct client_state
*client
,
1750 struct data_string
*packet
,
1754 struct dhc6_ia
*old_ia
;
1755 struct data_string ia
;
1760 struct option
*type_option
;
1762 /* figure out what type of option we are working with */
1765 type_string
= "IA_NA";
1766 type_option
= ia_na_option
;
1770 type_string
= "IA_TA";
1771 type_option
= ia_ta_option
;
1775 type_string
= "IA_PD";
1776 type_option
= ia_pd_option
;
1780 return (ISC_R_FAILURE
);
1783 for (i
= 0; wanted
!= 0; i
++) {
1784 rval
= dhc6_create_iaid(client
, &ia
, i
, len
);
1785 if (rval
!= ISC_R_SUCCESS
) {
1786 log_error("Unable to allocate memory for %s.",
1791 /* If we are already using this IAID, skip it and try again */
1792 if ((client
->active_lease
!= NULL
) &&
1793 ((old_ia
= find_ia(client
->active_lease
->bindings
,
1795 (char *)ia
.buffer
->data
)) != NULL
)) {
1796 data_string_forget(&ia
, MDL
);
1800 /* We have a good IAID, log it */
1801 log_debug("XMT: X-- %s %s",
1802 type_string
, print_hex_1(4, ia
.buffer
->data
, 55));
1804 /* If we are requesting an NA or a PD we also want to add
1805 * the renew and rebind times we are requesting.
1808 t1
= client
->config
->requested_lease
/ 2;
1810 putULong(ia
.buffer
->data
+ 4, t1
);
1811 putULong(ia
.buffer
->data
+ 8, t2
);
1813 log_debug("XMT: | X-- Request renew in +%u",
1815 log_debug("XMT: | X-- Request rebind in +%u",
1819 /* and append it to the packet */
1820 append_option(packet
, &dhcpv6_universe
, type_option
, &ia
);
1821 data_string_forget(&ia
, MDL
);
1823 /* decrement the number of IAs we want */
1827 return (ISC_R_SUCCESS
);
1831 * do_init6() marshals and transmits a solicit.
1834 do_init6(void *input
)
1836 struct client_state
*client
;
1837 struct dhc6_ia
*old_ia
;
1838 struct dhc6_addr
*old_addr
;
1839 struct data_string ds
;
1840 struct data_string ia
;
1841 struct data_string addr
;
1849 * In RFC3315 section 17.1.2, the retransmission timer is
1850 * used as the selecting timer.
1852 if (client
->advertised_leases
!= NULL
) {
1853 start_selecting6(client
);
1857 switch(check_timing6(client
, DHCPV6_SOLICIT
, "Solicit", NULL
, &ds
)) {
1858 case CHK_TIM_MRC_EXCEEDED
:
1859 case CHK_TIM_ALLOC_FAILURE
:
1861 case CHK_TIM_MRD_EXCEEDED
:
1862 client
->state
= S_STOPPED
;
1863 if (client
->active_lease
!= NULL
) {
1864 dhc6_lease_destroy(&client
->active_lease
, MDL
);
1865 client
->active_lease
= NULL
;
1867 /* Stop if and only if this is the last client. */
1868 if (stopping_finished())
1874 * Fetch any configured 'sent' options (includes DUID) in wire format.
1876 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
,
1877 NULL
, client
->sent_options
, &global_scope
,
1880 /* Use a specific handler with rapid-commit. */
1881 if (lookup_option(&dhcpv6_universe
, client
->sent_options
,
1882 D6O_RAPID_COMMIT
) != NULL
) {
1883 client
->v6_handler
= rapid_commit_handler
;
1887 for (i
= 0; i
< wanted_ia_na
; i
++) {
1889 * XXX: maybe the IA_NA('s) should be put into the sent_options
1890 * cache. They'd have to be pulled down as they also contain
1891 * different option caches in the same universe...
1893 if (dhc6_create_iaid(client
, &ia
, i
, 12) != ISC_R_SUCCESS
) {
1894 log_error("Unable to allocate memory for IA_NA.");
1895 data_string_forget(&ds
, MDL
);
1899 t1
= client
->config
->requested_lease
/ 2;
1901 putULong(ia
.buffer
->data
+ 4, t1
);
1902 putULong(ia
.buffer
->data
+ 8, t2
);
1904 log_debug("XMT: X-- IA_NA %s",
1905 print_hex_1(4, ia
.buffer
->data
, 55));
1906 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1
);
1907 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2
);
1909 if ((client
->active_lease
!= NULL
) &&
1910 ((old_ia
= find_ia(client
->active_lease
->bindings
,
1912 (char *)ia
.buffer
->data
)) != NULL
)) {
1914 * For each address in the old IA_NA,
1915 * request a binding.
1917 memset(&addr
, 0, sizeof(addr
));
1918 for (old_addr
= old_ia
->addrs
; old_addr
!= NULL
;
1919 old_addr
= old_addr
->next
) {
1920 if (old_addr
->address
.len
!= 16) {
1921 log_error("Invalid IPv6 address "
1923 "Ignoring. (%s:%d)",
1924 old_addr
->address
.len
,
1929 if (!buffer_allocate(&addr
.buffer
, 24, MDL
)) {
1930 log_error("Unable to allocate memory "
1932 data_string_forget(&ia
, MDL
);
1933 data_string_forget(&ds
, MDL
);
1936 addr
.data
= addr
.buffer
->data
;
1939 memcpy(addr
.buffer
->data
,
1940 old_addr
->address
.iabuf
,
1943 t1
= client
->config
->requested_lease
;
1945 putULong(addr
.buffer
->data
+ 16, t1
);
1946 putULong(addr
.buffer
->data
+ 20, t2
);
1948 log_debug("XMT: | X-- Request address %s.",
1949 piaddr(old_addr
->address
));
1950 log_debug("XMT: | | X-- Request "
1953 log_debug("XMT: | | X-- Request valid "
1957 append_option(&ia
, &dhcpv6_universe
,
1961 data_string_forget(&addr
, MDL
);
1965 append_option(&ds
, &dhcpv6_universe
, ia_na_option
, &ia
);
1966 data_string_forget(&ia
, MDL
);
1970 for (i
= 0; i
< wanted_ia_ta
; i
++) {
1972 * XXX: maybe the IA_TA('s) should be put into the sent_options
1973 * cache. They'd have to be pulled down as they also contain
1974 * different option caches in the same universe...
1976 if (dhc6_create_iaid(client
, &ia
, i
, 4) != ISC_R_SUCCESS
) {
1977 log_error("Unable to allocate memory for IA_TA.");
1978 data_string_forget(&ds
, MDL
);
1982 log_debug("XMT: X-- IA_TA %s",
1983 print_hex_1(4, ia
.buffer
->data
, 55));
1985 if ((client
->active_lease
!= NULL
) &&
1986 ((old_ia
= find_ia(client
->active_lease
->bindings
,
1988 (char *)ia
.buffer
->data
)) != NULL
)) {
1990 * For each address in the old IA_TA,
1991 * request a binding.
1993 memset(&addr
, 0, sizeof(addr
));
1994 for (old_addr
= old_ia
->addrs
; old_addr
!= NULL
;
1995 old_addr
= old_addr
->next
) {
1996 if (old_addr
->address
.len
!= 16) {
1997 log_error("Invalid IPv6 address "
1999 "Ignoring. (%s:%d)",
2000 old_addr
->address
.len
,
2005 if (!buffer_allocate(&addr
.buffer
, 24, MDL
)) {
2006 log_error("Unable to allocate memory "
2008 data_string_forget(&ia
, MDL
);
2009 data_string_forget(&ds
, MDL
);
2012 addr
.data
= addr
.buffer
->data
;
2015 memcpy(addr
.buffer
->data
,
2016 old_addr
->address
.iabuf
,
2019 t1
= client
->config
->requested_lease
;
2021 putULong(addr
.buffer
->data
+ 16, t1
);
2022 putULong(addr
.buffer
->data
+ 20, t2
);
2024 log_debug("XMT: | X-- Request address %s.",
2025 piaddr(old_addr
->address
));
2026 log_debug("XMT: | | X-- Request "
2029 log_debug("XMT: | | X-- Request valid "
2033 append_option(&ia
, &dhcpv6_universe
,
2037 data_string_forget(&addr
, MDL
);
2041 append_option(&ds
, &dhcpv6_universe
, ia_ta_option
, &ia
);
2042 data_string_forget(&ia
, MDL
);
2046 for (i
= 0; i
< wanted_ia_pd
; i
++) {
2048 * XXX: maybe the IA_PD('s) should be put into the sent_options
2049 * cache. They'd have to be pulled down as they also contain
2050 * different option caches in the same universe...
2052 memset(&ia
, 0, sizeof(ia
));
2053 if (dhc6_create_iaid(client
, &ia
, i
, 12) != ISC_R_SUCCESS
) {
2054 log_error("Unable to allocate memory for IA_PD.");
2055 data_string_forget(&ds
, MDL
);
2059 t1
= client
->config
->requested_lease
/ 2;
2061 putULong(ia
.buffer
->data
+ 4, t1
);
2062 putULong(ia
.buffer
->data
+ 8, t2
);
2064 log_debug("XMT: X-- IA_PD %s",
2065 print_hex_1(4, ia
.buffer
->data
, 55));
2066 log_debug("XMT: | X-- Request renew in +%u", (unsigned)t1
);
2067 log_debug("XMT: | X-- Request rebind in +%u", (unsigned)t2
);
2069 if ((client
->active_lease
!= NULL
) &&
2070 ((old_ia
= find_ia(client
->active_lease
->bindings
,
2072 (char *)ia
.buffer
->data
)) != NULL
)) {
2074 * For each prefix in the old IA_PD,
2075 * request a binding.
2077 memset(&addr
, 0, sizeof(addr
));
2078 for (old_addr
= old_ia
->addrs
; old_addr
!= NULL
;
2079 old_addr
= old_addr
->next
) {
2080 if (old_addr
->address
.len
!= 16) {
2081 log_error("Invalid IPv6 prefix, "
2082 "Ignoring. (%s:%d)",
2087 if (!buffer_allocate(&addr
.buffer
, 25, MDL
)) {
2088 log_error("Unable to allocate memory "
2090 data_string_forget(&ia
, MDL
);
2091 data_string_forget(&ds
, MDL
);
2094 addr
.data
= addr
.buffer
->data
;
2097 t1
= client
->config
->requested_lease
;
2099 putULong(addr
.buffer
->data
, t1
);
2100 putULong(addr
.buffer
->data
+ 4, t2
);
2102 putUChar(addr
.buffer
->data
+ 8,
2104 memcpy(addr
.buffer
->data
+ 9,
2105 old_addr
->address
.iabuf
,
2108 log_debug("XMT: | X-- Request prefix %s/%u.",
2109 piaddr(old_addr
->address
),
2110 (unsigned) old_addr
->plen
);
2111 log_debug("XMT: | | X-- Request "
2114 log_debug("XMT: | | X-- Request valid "
2118 append_option(&ia
, &dhcpv6_universe
,
2122 data_string_forget(&addr
, MDL
);
2126 append_option(&ds
, &dhcpv6_universe
, ia_pd_option
, &ia
);
2127 data_string_forget(&ia
, MDL
);
2130 /* Transmit and wait. */
2132 log_info("XMT: Solicit on %s, interval %ld0ms.",
2133 client
->name
? client
->name
: client
->interface
->name
,
2134 (long int)client
->RT
);
2136 send_ret
= send_packet6(client
->interface
,
2137 ds
.data
, ds
.len
, &DHCPv6DestAddr
);
2138 if (send_ret
!= ds
.len
) {
2139 log_error("dhc6: send_packet6() sent %d of %d bytes",
2143 data_string_forget(&ds
, MDL
);
2146 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2147 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2148 if (tv
.tv_usec
>= 1000000) {
2150 tv
.tv_usec
-= 1000000;
2152 add_timeout(&tv
, do_init6
, client
, NULL
, NULL
);
2154 dhc6_retrans_advance(client
);
2157 /* do_info_request6() marshals and transmits an information-request. */
2159 do_info_request6(void *input
)
2161 struct client_state
*client
;
2162 struct data_string ds
;
2168 switch(check_timing6(client
, DHCPV6_INFORMATION_REQUEST
,
2169 "Info-Request", NULL
, &ds
)) {
2170 case CHK_TIM_MRC_EXCEEDED
:
2171 case CHK_TIM_ALLOC_FAILURE
:
2173 case CHK_TIM_MRD_EXCEEDED
:
2175 case CHK_TIM_SUCCESS
:
2179 /* Fetch any configured 'sent' options (includes DUID) in wire format.
2181 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
,
2182 NULL
, client
->sent_options
, &global_scope
,
2185 /* Transmit and wait. */
2187 log_info("XMT: Info-Request on %s, interval %ld0ms.",
2188 client
->name
? client
->name
: client
->interface
->name
,
2189 (long int)client
->RT
);
2191 send_ret
= send_packet6(client
->interface
,
2192 ds
.data
, ds
.len
, &DHCPv6DestAddr
);
2193 if (send_ret
!= ds
.len
) {
2194 log_error("dhc6: send_packet6() sent %d of %d bytes",
2198 data_string_forget(&ds
, MDL
);
2201 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2202 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2203 if (tv
.tv_usec
>= 1000000) {
2205 tv
.tv_usec
-= 1000000;
2207 add_timeout(&tv
, do_info_request6
, client
, NULL
, NULL
);
2209 dhc6_retrans_advance(client
);
2212 /* do_confirm6() creates a Confirm packet and transmits it. This function
2213 * is called on every timeout to (re)transmit.
2216 do_confirm6(void *input
)
2218 struct client_state
*client
;
2219 struct data_string ds
;
2220 int send_ret
, added
;
2225 if (client
->active_lease
== NULL
)
2226 log_fatal("Impossible condition at %s:%d.", MDL
);
2228 /* In section 17.1.3, it is said:
2230 * If the client receives no responses before the message
2231 * transmission process terminates, as described in section 14,
2232 * the client SHOULD continue to use any IP addresses, using the
2233 * last known lifetimes for those addresses, and SHOULD continue
2234 * to use any other previously obtained configuration parameters.
2236 * So if confirm times out, we go active.
2238 * XXX: Should we reduce all IA's t1 to 0, so that we renew and
2239 * stick there until we get a reply?
2242 switch(check_timing6(client
, DHCPV6_CONFIRM
, "Confirm",
2243 client
->active_lease
, &ds
)) {
2244 case CHK_TIM_MRC_EXCEEDED
:
2245 case CHK_TIM_MRD_EXCEEDED
:
2246 start_bound(client
);
2248 case CHK_TIM_ALLOC_FAILURE
:
2250 case CHK_TIM_SUCCESS
:
2254 /* Fetch any configured 'sent' options (includes DUID') in wire format.
2256 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
, NULL
,
2257 client
->sent_options
, &global_scope
,
2262 dhc6_add_ia_na(client
, &ds
, client
->active_lease
,
2263 DHCPV6_CONFIRM
, 0, &added
) != ISC_R_SUCCESS
) {
2264 data_string_forget(&ds
, MDL
);
2268 dhc6_add_ia_ta(client
, &ds
, client
->active_lease
,
2269 DHCPV6_CONFIRM
, 0, &added
) != ISC_R_SUCCESS
) {
2270 data_string_forget(&ds
, MDL
);
2274 /* Transmit and wait. */
2276 log_info("XMT: Confirm on %s, interval %ld0ms.",
2277 client
->name
? client
->name
: client
->interface
->name
,
2278 (long int)client
->RT
);
2280 send_ret
= send_packet6(client
->interface
, ds
.data
, ds
.len
,
2282 if (send_ret
!= ds
.len
) {
2283 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2287 data_string_forget(&ds
, MDL
);
2290 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2291 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2292 if (tv
.tv_usec
>= 1000000) {
2294 tv
.tv_usec
-= 1000000;
2296 add_timeout(&tv
, do_confirm6
, client
, NULL
, NULL
);
2298 dhc6_retrans_advance(client
);
2302 * Release addresses.
2305 start_release6(struct client_state
*client
)
2307 /* Cancel any pending transmissions */
2308 cancel_timeout(do_confirm6
, client
);
2309 cancel_timeout(do_select6
, client
);
2310 cancel_timeout(do_refresh6
, client
);
2311 cancel_timeout(do_release6
, client
);
2312 client
->state
= S_STOPPED
;
2315 * It is written: "The client MUST NOT use any of the addresses it
2316 * is releasing as the source address in the Release message or in
2317 * any subsequently transmitted message." So unconfigure now.
2319 unconfigure6(client
, "RELEASE6");
2321 /* Note this in the lease file. */
2322 if (client
->active_lease
== NULL
)
2324 client
->active_lease
->released
= ISC_TRUE
;
2325 write_client6_lease(client
, client
->active_lease
, 0, 1);
2327 /* Set timers per RFC3315 section 18.1.6. */
2328 client
->IRT
= REL_TIMEOUT
* 100;
2330 client
->MRC
= REL_MAX_RC
;
2333 dhc6_retrans_init(client
);
2334 client
->v6_handler
= reply_handler
;
2336 do_release6(client
);
2339 * do_release6() creates a Release packet and transmits it.
2342 do_release6(void *input
)
2344 struct client_state
*client
;
2345 struct data_string ds
;
2346 int send_ret
, added
;
2351 if ((client
->active_lease
== NULL
) || !active_prefix(client
))
2354 switch(check_timing6(client
, DHCPV6_RELEASE
, "Release",
2355 client
->active_lease
, &ds
)) {
2356 case CHK_TIM_MRC_EXCEEDED
:
2357 case CHK_TIM_ALLOC_FAILURE
:
2358 case CHK_TIM_MRD_EXCEEDED
:
2360 case CHK_TIM_SUCCESS
:
2365 * Don't use unicast as we don't know if we still have an
2366 * available address with enough scope.
2369 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
, NULL
,
2370 client
->sent_options
, &global_scope
,
2373 /* Append IA's (but don't release temporary addresses). */
2375 dhc6_add_ia_na(client
, &ds
, client
->active_lease
,
2376 DHCPV6_RELEASE
, 0, &added
) != ISC_R_SUCCESS
) {
2377 data_string_forget(&ds
, MDL
);
2381 dhc6_add_ia_pd(client
, &ds
, client
->active_lease
,
2382 DHCPV6_RELEASE
, 0, &added
) != ISC_R_SUCCESS
) {
2383 data_string_forget(&ds
, MDL
);
2387 /* Transmit and wait. */
2388 log_info("XMT: Release on %s, interval %ld0ms.",
2389 client
->name
? client
->name
: client
->interface
->name
,
2390 (long int)client
->RT
);
2392 send_ret
= send_packet6(client
->interface
, ds
.data
, ds
.len
,
2394 if (send_ret
!= ds
.len
) {
2395 log_error("dhc6: sendpacket6() sent %d of %d bytes",
2399 data_string_forget(&ds
, MDL
);
2402 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
2403 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
2404 if (tv
.tv_usec
>= 1000000) {
2406 tv
.tv_usec
-= 1000000;
2408 add_timeout(&tv
, do_release6
, client
, NULL
, NULL
);
2409 dhc6_retrans_advance(client
);
2413 dhc6_lease_destroy(&client
->active_lease
, MDL
);
2414 client
->active_lease
= NULL
;
2415 if (stopping_finished())
2419 /* status_log() just puts a status code into displayable form and logs it
2423 status_log(int code
, const char *scope
, const char *additional
, int len
)
2425 const char *msg
= NULL
;
2428 case STATUS_Success
:
2432 case STATUS_UnspecFail
:
2436 case STATUS_NoAddrsAvail
:
2437 msg
= "NoAddrsAvail";
2440 case STATUS_NoBinding
:
2444 case STATUS_NotOnLink
:
2448 case STATUS_UseMulticast
:
2449 msg
= "UseMulticast";
2452 case STATUS_NoPrefixAvail
:
2453 msg
= "NoPrefixAvail";
2462 log_info("%s status code %s: %s", scope
, msg
,
2464 (const unsigned char *)additional
, 50));
2466 log_info("%s status code %s.", scope
, msg
);
2469 /* Acquire a status code.
2472 dhc6_get_status_code(struct option_state
*options
, unsigned *code
,
2473 struct data_string
*msg
)
2475 struct option_cache
*oc
;
2476 struct data_string ds
;
2477 isc_result_t rval
= ISC_R_SUCCESS
;
2479 if ((options
== NULL
) || (code
== NULL
))
2480 return DHCP_R_INVALIDARG
;
2482 if ((msg
!= NULL
) && (msg
->len
!= 0))
2483 return DHCP_R_INVALIDARG
;
2485 memset(&ds
, 0, sizeof(ds
));
2487 /* Assume success if there is no option. */
2488 *code
= STATUS_Success
;
2490 oc
= lookup_option(&dhcpv6_universe
, options
, D6O_STATUS_CODE
);
2492 evaluate_option_cache(&ds
, NULL
, NULL
, NULL
, options
,
2493 NULL
, &global_scope
, oc
, MDL
)) {
2495 log_error("Invalid status code length %d.", ds
.len
);
2496 rval
= DHCP_R_FORMERR
;
2498 *code
= getUShort(ds
.data
);
2500 if ((msg
!= NULL
) && (ds
.len
> 2)) {
2501 data_string_copy(msg
, &ds
, MDL
);
2506 data_string_forget(&ds
, MDL
);
2510 return ISC_R_NOTFOUND
;
2513 /* Look at status codes in an advertise, and reform the return value.
2516 dhc6_check_status(isc_result_t rval
, struct option_state
*options
,
2517 const char *scope
, unsigned *code
)
2519 struct data_string msg
;
2520 isc_result_t status
;
2522 if ((scope
== NULL
) || (code
== NULL
))
2523 return DHCP_R_INVALIDARG
;
2525 /* If we don't find a code, we assume success. */
2526 *code
= STATUS_Success
;
2528 /* If there is no options cache, then there is no code. */
2529 if (options
!= NULL
) {
2530 memset(&msg
, 0, sizeof(msg
));
2531 status
= dhc6_get_status_code(options
, code
, &msg
);
2533 if (status
== ISC_R_SUCCESS
) {
2534 status_log(*code
, scope
, (char *)msg
.data
, msg
.len
);
2535 data_string_forget(&msg
, MDL
);
2537 if (*code
!= STATUS_Success
)
2538 rval
= ISC_R_FAILURE
;
2540 } else if (status
!= ISC_R_NOTFOUND
)
2547 /* Determine if this packet could provide usable information.
2548 * We check the status codes at the top level and at the IA level,
2549 * IAADDRS have already been checked in the leaseify step and any with
2550 * a bad format or status code that wasn't success have been dropped.
2552 * leaseify has also already removed any IAs for which the top level status
2553 * code or the IA status code indicated no addresses or prefixes were
2557 dhc6_check_advertise(struct dhc6_lease
*lease
)
2560 isc_result_t rval
= ISC_R_SUCCESS
;
2561 int have_addrs
= ISC_FALSE
;
2564 int got_na
= 0, got_ta
= 0, got_pd
= 0;
2566 rval
= dhc6_check_status(rval
, lease
->options
, "message", &code
);
2568 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
2569 switch (ia
->ia_type
) {
2583 log_error("dhc6_check_advertise: no type.");
2584 return ISC_R_FAILURE
;
2586 /* Currently we toss packets if we have an error getting a
2587 * status code or if the status code isn't success, so
2588 * no need to loop through the addresses */
2589 rval
= dhc6_check_status(rval
, ia
->options
, scope
, &code
);
2590 if (rval
!= ISC_R_SUCCESS
)
2593 /* We don't need to check status on IAADDRS here as we already
2594 * did it as part of the leaseify step and tossed bad IAADDRS.
2595 * We are just checking to see if we have any addrs.
2596 * Should we check the addr itself for usability?
2598 if (ia
->addrs
!= NULL
) {
2599 have_addrs
= ISC_TRUE
;
2603 /* If we didn't get some addrs or the user required us to
2604 * get all of the requested IAs and we didn't return an error
2606 if ((have_addrs
!= ISC_TRUE
) ||
2607 ((require_all_ias
!= 0) &&
2608 ((got_na
< wanted_ia_na
) ||
2609 (got_ta
< wanted_ia_ta
) ||
2610 (got_pd
< wanted_ia_pd
))))
2611 rval
= ISC_R_ADDRNOTAVAIL
;
2616 /* status code <-> action matrix for the client in INIT state
2617 * (rapid/commit). Returns always false as no action is defined.
2619 static isc_boolean_t
2620 dhc6_init_action(struct client_state
*client
, isc_result_t
*rvalp
,
2624 log_fatal("Impossible condition at %s:%d.", MDL
);
2626 if (client
== NULL
) {
2627 *rvalp
= DHCP_R_INVALIDARG
;
2631 if (*rvalp
== ISC_R_SUCCESS
)
2634 /* No possible action in any case... */
2638 /* status code <-> action matrix for the client in SELECT state
2639 * (request/reply). Returns true if action was taken (and the
2640 * packet should be ignored), or false if no action was taken.
2642 static isc_boolean_t
2643 dhc6_select_action(struct client_state
*client
, isc_result_t
*rvalp
,
2646 struct dhc6_lease
*lease
;
2650 log_fatal("Impossible condition at %s:%d.", MDL
);
2652 if (client
== NULL
) {
2653 *rvalp
= DHCP_R_INVALIDARG
;
2658 if (rval
== ISC_R_SUCCESS
)
2662 /* We may have an earlier failure status code (so no
2663 * success rval), and a success code now. This
2664 * doesn't upgrade the rval to success, but it does
2665 * mean we take no action here.
2667 case STATUS_Success
:
2668 /* Gimpy server, or possibly an attacker. */
2669 case STATUS_NoBinding
:
2670 case STATUS_UseMulticast
:
2671 /* Take no action. */
2674 /* If the server can't deal with us, either try the
2675 * next advertised server, or continue retrying if there
2679 case STATUS_UnspecFail
:
2680 if (client
->advertised_leases
!= NULL
) {
2681 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
2682 client
->selected_lease
= NULL
;
2684 start_selecting6(client
);
2687 } else /* Take no action - continue to retry. */
2690 /* If the server has no addresses, try other servers if
2691 * we got some, otherwise go to INIT to hope for more
2694 case STATUS_NoAddrsAvail
:
2695 case STATUS_NoPrefixAvail
:
2696 if (client
->state
== S_REBOOTING
)
2699 if (client
->selected_lease
== NULL
)
2700 log_fatal("Impossible case at %s:%d.", MDL
);
2702 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
2703 client
->selected_lease
= NULL
;
2705 if (client
->advertised_leases
!= NULL
)
2706 start_selecting6(client
);
2708 start_init6(client
);
2712 /* If we got a NotOnLink from a Confirm, then we're not
2713 * on link. Kill the old-active binding and start over.
2715 * If we got a NotOnLink from our Request, something weird
2716 * happened. Start over from scratch anyway.
2718 case STATUS_NotOnLink
:
2719 if (client
->state
== S_REBOOTING
) {
2720 if (client
->active_lease
== NULL
)
2721 log_fatal("Impossible case at %s:%d.", MDL
);
2723 dhc6_lease_destroy(&client
->active_lease
, MDL
);
2725 if (client
->selected_lease
== NULL
)
2726 log_fatal("Impossible case at %s:%d.", MDL
);
2728 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
2729 client
->selected_lease
= NULL
;
2731 while (client
->advertised_leases
!= NULL
) {
2732 lease
= client
->advertised_leases
;
2733 client
->advertised_leases
= lease
->next
;
2735 dhc6_lease_destroy(&lease
, MDL
);
2739 start_init6(client
);
2747 dhc6_withdraw_lease(struct client_state
*client
)
2750 struct dhc6_addr
*addr
;
2752 if ((client
== NULL
) || (client
->active_lease
== NULL
))
2755 for (ia
= client
->active_lease
->bindings
; ia
!= NULL
;
2757 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
2758 addr
->max_life
= addr
->preferred_life
= 0;
2762 /* Perform expiry. */
2766 /* status code <-> action matrix for the client in BOUND state
2767 * (request/reply). Returns true if action was taken (and the
2768 * packet should be ignored), or false if no action was taken.
2770 static isc_boolean_t
2771 dhc6_reply_action(struct client_state
*client
, isc_result_t
*rvalp
,
2777 log_fatal("Impossible condition at %s:%d.", MDL
);
2779 if (client
== NULL
) {
2780 *rvalp
= DHCP_R_INVALIDARG
;
2785 if (rval
== ISC_R_SUCCESS
)
2789 /* It's possible an earlier status code set rval to a failure
2790 * code, and we've encountered a later success.
2792 case STATUS_Success
:
2793 /* In "refreshes" (where we get replies), we probably
2794 * still have a valid lease. So "take no action" and
2795 * the upper levels will keep retrying until the lease
2796 * expires (or we rebind).
2798 case STATUS_UnspecFail
:
2799 /* For unknown codes...it's a soft (retryable) error. */
2803 /* The server is telling us to use a multicast address, so
2804 * we have to delete the unicast option from the active
2805 * lease, then allow retransmission to occur normally.
2806 * (XXX: It might be preferable in this case to retransmit
2807 * sooner than the current interval, but for now we don't.)
2809 case STATUS_UseMulticast
:
2810 if (client
->active_lease
!= NULL
)
2811 delete_option(&dhcp_universe
,
2812 client
->active_lease
->options
,
2816 /* "When the client receives a NotOnLink status from the
2817 * server in response to a Request, the client can either
2818 * re-issue the Request without specifying any addresses
2819 * or restart the DHCP server discovery process."
2821 * This is strange. If competing server evaluation is
2822 * useful (and therefore in the protocol), then why would
2823 * a client's first reaction be to request from the same
2824 * server on a different link? Surely you'd want to
2825 * re-evaluate your server selection.
2827 * Well, I guess that's the answer.
2829 case STATUS_NotOnLink
:
2830 /* In this case, we need to rescind all current active
2831 * bindings (just 'expire' them all normally, if early).
2832 * They're no use to us on the wrong link. Then head back
2833 * to init, redo server selection and get new addresses.
2835 dhc6_withdraw_lease(client
);
2838 /* "If the status code is NoAddrsAvail, the client has
2839 * received no usable addresses in the IA and may choose
2840 * to try obtaining addresses for the IA from another
2843 case STATUS_NoAddrsAvail
:
2844 case STATUS_NoPrefixAvail
:
2845 /* Head back to init, keeping any active bindings (!). */
2846 start_init6(client
);
2849 /* - sends a Request message if the IA contained a Status
2850 * Code option with the NoBinding status (and does not
2851 * send any additional Renew/Rebind messages)
2853 case STATUS_NoBinding
:
2854 if (client
->advertised_leases
!= NULL
)
2855 log_fatal("Impossible condition at %s:%d.", MDL
);
2857 client
->advertised_leases
=
2858 dhc6_dup_lease(client
->active_lease
, MDL
);
2859 start_selecting6(client
);
2866 /* status code <-> action matrix for the client in STOPPED state
2867 * (release/decline). Returns true if action was taken (and the
2868 * packet should be ignored), or false if no action was taken.
2869 * NoBinding is translated into Success.
2871 static isc_boolean_t
2872 dhc6_stop_action(struct client_state
*client
, isc_result_t
*rvalp
,
2878 log_fatal("Impossible condition at %s:%d.", MDL
);
2880 if (client
== NULL
) {
2881 *rvalp
= DHCP_R_INVALIDARG
;
2886 if (rval
== ISC_R_SUCCESS
)
2890 /* It's possible an earlier status code set rval to a failure
2891 * code, and we've encountered a later success.
2893 case STATUS_Success
:
2894 /* For unknown codes...it's a soft (retryable) error. */
2895 case STATUS_UnspecFail
:
2899 /* NoBinding is not an error */
2900 case STATUS_NoBinding
:
2901 if (rval
== ISC_R_FAILURE
)
2902 *rvalp
= ISC_R_SUCCESS
;
2905 /* Should not happen */
2906 case STATUS_NoAddrsAvail
:
2907 case STATUS_NoPrefixAvail
:
2911 case STATUS_NotOnLink
:
2914 /* The server is telling us to use a multicast address, so
2915 * we have to delete the unicast option from the active
2916 * lease, then allow retransmission to occur normally.
2917 * (XXX: It might be preferable in this case to retransmit
2918 * sooner than the current interval, but for now we don't.)
2920 case STATUS_UseMulticast
:
2921 if (client
->active_lease
!= NULL
)
2922 delete_option(&dhcp_universe
,
2923 client
->active_lease
->options
,
2931 /* Look at a new and old lease, and make sure the new information is not
2932 * losing us any state.
2935 dhc6_check_reply(struct client_state
*client
, struct dhc6_lease
*new)
2937 isc_boolean_t (*action
)(struct client_state
*,
2938 isc_result_t
*, unsigned);
2940 isc_result_t rval
= ISC_R_SUCCESS
;
2944 int have_addrs
= ISC_FALSE
;
2945 int got_na
= 0, got_ta
= 0, got_pd
= 0;
2947 if ((client
== NULL
) || (new == NULL
))
2948 return DHCP_R_INVALIDARG
;
2950 switch (client
->state
) {
2952 action
= dhc6_init_action
;
2957 action
= dhc6_select_action
;
2962 action
= dhc6_reply_action
;
2966 action
= dhc6_stop_action
;
2970 log_fatal("Impossible condition at %s:%d.", MDL
);
2971 return ISC_R_CANCELED
;
2974 /* If there is a code to extract, and if there is some
2975 * action to take based on that code, then take the action
2976 * and do not continue.
2978 rval
= dhc6_check_status(rval
, new->options
, "message", &code
);
2979 if (action(client
, &rval
, code
))
2980 return ISC_R_CANCELED
;
2982 for (ia
= new->bindings
; ia
!= NULL
; ia
= ia
->next
) {
2983 switch (ia
->ia_type
) {
2997 log_error("dhc6_check_reply: no type.");
2998 return DHCP_R_INVALIDARG
;
3000 rval
= dhc6_check_status(rval
, ia
->options
, scope
, &code
);
3002 if (action(client
, &rval
, code
))
3003 return ISC_R_CANCELED
;
3005 if (ia
->addrs
!= NULL
) {
3006 have_addrs
= ISC_TRUE
;
3010 /* A Confirm->Reply is unsuitable for comparison to the old lease. */
3011 if (client
->state
== S_REBOOTING
)
3014 /* We expect the lease to have at least one address and if
3015 * required all of the requested IAs if not flag it as
3016 * NoAddrs and call the action routine to try again.
3018 * Currently we don't completely handle TAs in all cases
3019 * so we don't check them for requires. I've left the
3020 * check in and commented it as I eventually do want
3021 * us to check for TAs as well. SAR
3023 if ((have_addrs
!= ISC_TRUE
) ||
3024 ((require_all_ias
!= 0) &&
3025 ((got_na
< wanted_ia_na
) ||
3026 /*(got_ta < wanted_ia_ta) ||*/
3027 (got_pd
< wanted_ia_pd
)))) {
3028 rval
= ISC_R_FAILURE
;
3029 if (action(client
, &rval
, STATUS_NoAddrsAvail
) == ISC_TRUE
) {
3030 return ISC_R_CANCELED
;
3034 /* No old lease in rapid-commit. */
3035 if (client
->state
== S_INIT
)
3038 switch (client
->state
) {
3040 /* Compare the new lease with the selected lease to make
3041 * sure there is no risky business.
3043 nscore
= dhc6_score_lease(client
, new);
3044 sscore
= dhc6_score_lease(client
, client
->selected_lease
);
3045 if ((client
->advertised_leases
!= NULL
) &&
3046 (nscore
< (sscore
/ 2))) {
3047 /* XXX: An attacker might reply this way to make
3048 * XXX: sure we latch onto their configuration.
3049 * XXX: We might want to ignore the packet and
3050 * XXX: schedule re-selection at the next timeout?
3052 log_error("PRC: BAIT AND SWITCH detected. Score of "
3053 "supplied lease (%d) is substantially "
3054 "smaller than the advertised score (%d). "
3055 "Trying other servers.",
3058 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
3059 client
->selected_lease
= NULL
;
3061 start_selecting6(client
);
3063 return ISC_R_CANCELED
;
3069 /* This leaves one RFC3315 status check unimplemented:
3071 * - sends a Renew/Rebind if the IA is not in the Reply
3074 * We rely on the scheduling system to note that the IA has
3075 * not left Renewal/Rebinding/whatever since it still carries
3076 * old times from the last successful binding. So this is
3077 * implemented actually, just not explicitly.
3082 /* Nothing critical to do at this stage. */
3086 log_fatal("REALLY impossible condition at %s:%d.", MDL
);
3087 return ISC_R_CANCELED
;
3093 /* While in init state, we only collect advertisements. If there happens
3094 * to be an advertisement with a preference option of 255, that's an
3095 * automatic exit. Otherwise, we collect advertisements until our timeout
3096 * expires (client->RT).
3099 init_handler(struct packet
*packet
, struct client_state
*client
)
3101 struct dhc6_lease
*lease
;
3103 /* In INIT state, we send solicits, we only expect to get
3104 * advertises (rapid commit has its own handler).
3106 if (packet
->dhcpv6_msg_type
!= DHCPV6_ADVERTISE
)
3109 /* RFC3315 section 15.3 validation (same as 15.10 since we
3110 * always include a client id).
3112 if (!valid_reply(packet
, client
)) {
3113 log_error("Invalid Advertise - rejecting.");
3117 lease
= dhc6_leaseify(packet
);
3119 /* Out of memory or corrupt packet condition...hopefully a temporary
3120 * problem. Returning now makes us try to retransmit later.
3125 if (dhc6_check_advertise(lease
) != ISC_R_SUCCESS
) {
3126 log_debug("PRC: Lease failed to satisfy.");
3127 dhc6_lease_destroy(&lease
, MDL
);
3131 insert_lease(&client
->advertised_leases
, lease
);
3133 /* According to RFC3315 section 17.1.2, the client MUST wait for
3134 * the first RT before selecting a lease. But on the 400th RT,
3135 * we dont' want to wait the full timeout if we finally get an
3136 * advertise. We could probably wait a second, but ohwell,
3137 * RFC3315 doesn't say so.
3139 * If the lease is highest possible preference, 255, RFC3315 claims
3140 * we should continue immediately even on the first RT. We probably
3141 * should not if the advertise contains less than one IA and address.
3143 if ((client
->txcount
> 1) ||
3144 ((lease
->pref
== 255) &&
3145 (dhc6_score_lease(client
, lease
) > SCORE_MIN
))) {
3146 log_debug("RCV: Advertisement immediately selected.");
3147 cancel_timeout(do_init6
, client
);
3148 start_selecting6(client
);
3150 log_debug("RCV: Advertisement recorded.");
3153 /* info_request_handler() accepts a Reply to an Info-request.
3156 info_request_handler(struct packet
*packet
, struct client_state
*client
)
3158 isc_result_t check_status
;
3161 if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
3164 /* RFC3315 section 15.10 validation (same as 15.3 since we
3165 * always include a client id).
3167 if (!valid_reply(packet
, client
)) {
3168 log_error("Invalid Reply - rejecting.");
3172 check_status
= dhc6_check_status(ISC_R_SUCCESS
, packet
->options
,
3175 if (check_status
!= ISC_R_SUCCESS
) {
3176 /* If no action was taken, but there is an error, then
3177 * we wait for a retransmission.
3179 if (check_status
!= ISC_R_CANCELED
)
3183 /* We're done retransmitting at this point. */
3184 cancel_timeout(do_info_request6
, client
);
3186 /* Action was taken, so now that we've torn down our scheduled
3187 * retransmissions, return.
3189 if (check_status
== ISC_R_CANCELED
)
3192 /* Cleanup if a previous attempt to go bound failed. */
3193 if (client
->old_lease
!= NULL
) {
3194 dhc6_lease_destroy(&client
->old_lease
, MDL
);
3195 client
->old_lease
= NULL
;
3198 /* Cache options in the active_lease. */
3199 if (client
->active_lease
!= NULL
)
3200 client
->old_lease
= client
->active_lease
;
3201 client
->active_lease
= dmalloc(sizeof(struct dhc6_lease
), MDL
);
3202 if (client
->active_lease
== NULL
)
3203 log_fatal("Out of memory for v6 lease structure.");
3204 option_state_reference(&client
->active_lease
->options
,
3205 packet
->options
, MDL
);
3207 start_informed(client
);
3210 /* Specific version of init_handler() for rapid-commit.
3213 rapid_commit_handler(struct packet
*packet
, struct client_state
*client
)
3215 struct dhc6_lease
*lease
;
3216 isc_result_t check_status
;
3218 /* On ADVERTISE just fall back to the init_handler().
3220 if (packet
->dhcpv6_msg_type
== DHCPV6_ADVERTISE
) {
3221 init_handler(packet
, client
);
3223 } else if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
3226 /* RFC3315 section 15.10 validation (same as 15.3 since we
3227 * always include a client id).
3229 if (!valid_reply(packet
, client
)) {
3230 log_error("Invalid Reply - rejecting.");
3234 /* A rapid-commit option MUST be here. */
3235 if (lookup_option(&dhcpv6_universe
, packet
->options
,
3236 D6O_RAPID_COMMIT
) == 0) {
3237 log_error("Reply without Rapid-Commit - rejecting.");
3241 lease
= dhc6_leaseify(packet
);
3243 /* Out of memory or corrupt packet condition...hopefully a temporary
3244 * problem. Returning now makes us try to retransmit later.
3249 check_status
= dhc6_check_reply(client
, lease
);
3250 if (check_status
!= ISC_R_SUCCESS
) {
3251 dhc6_lease_destroy(&lease
, MDL
);
3255 /* Jump to the selecting state. */
3256 cancel_timeout(do_init6
, client
);
3257 client
->state
= S_SELECTING
;
3259 /* Merge any bindings in the active lease (if there is one) into
3260 * the new active lease.
3262 dhc6_merge_lease(client
->active_lease
, lease
);
3264 /* Cleanup if a previous attempt to go bound failed. */
3265 if (client
->old_lease
!= NULL
) {
3266 dhc6_lease_destroy(&client
->old_lease
, MDL
);
3267 client
->old_lease
= NULL
;
3270 /* Make this lease active and BIND to it. */
3271 if (client
->active_lease
!= NULL
)
3272 client
->old_lease
= client
->active_lease
;
3273 client
->active_lease
= lease
;
3275 /* We're done with the ADVERTISEd leases, if any. */
3276 while(client
->advertised_leases
!= NULL
) {
3277 lease
= client
->advertised_leases
;
3278 client
->advertised_leases
= lease
->next
;
3280 dhc6_lease_destroy(&lease
, MDL
);
3283 start_bound(client
);
3286 /* Find the 'best' lease in the cache of advertised leases (usually). From
3287 * RFC3315 Section 17.1.3:
3289 * Upon receipt of one or more valid Advertise messages, the client
3290 * selects one or more Advertise messages based upon the following
3293 * - Those Advertise messages with the highest server preference value
3294 * are preferred over all other Advertise messages.
3296 * - Within a group of Advertise messages with the same server
3297 * preference value, a client MAY select those servers whose
3298 * Advertise messages advertise information of interest to the
3299 * client. For example, the client may choose a server that returned
3300 * an advertisement with configuration options of interest to the
3303 * - The client MAY choose a less-preferred server if that server has a
3304 * better set of advertised parameters, such as the available
3305 * addresses advertised in IAs.
3307 * Note that the first and third contradict each other. The third should
3308 * probably be taken to mean that the client should prefer answers that
3309 * offer bindings, even if that violates the preference rule.
3311 * The above also isn't deterministic where there are ties. So the final
3312 * tiebreaker we add, if all other values are equal, is to compare the
3313 * server identifiers and to select the numerically lower one.
3315 static struct dhc6_lease
*
3316 dhc6_best_lease(struct client_state
*client
, struct dhc6_lease
**head
)
3318 struct dhc6_lease
**rpos
, *rval
, **candp
, *cand
;
3321 if (head
== NULL
|| *head
== NULL
)
3326 rscore
= dhc6_score_lease(client
, rval
);
3327 candp
= &rval
->next
;
3330 log_debug("PRC: Considering best lease.");
3331 log_debug("PRC: X-- Initial candidate %s (s: %d, p: %u).",
3332 print_hex_1(rval
->server_id
.len
,
3333 rval
->server_id
.data
, 48),
3334 rscore
, (unsigned)rval
->pref
);
3336 for (; cand
!= NULL
; candp
= &cand
->next
, cand
= *candp
) {
3337 cscore
= dhc6_score_lease(client
, cand
);
3339 log_debug("PRC: X-- Candidate %s (s: %d, p: %u).",
3340 print_hex_1(cand
->server_id
.len
,
3341 cand
->server_id
.data
, 48),
3342 cscore
, (unsigned)cand
->pref
);
3344 /* Above you'll find quoted RFC3315 Section 17.1.3.
3346 * The third clause tells us to give up on leases that
3347 * have no bindings even if their preference is better.
3348 * So where our 'selected' lease's score is less than
3349 * SCORE_MIN (1 ia + 1 addr), choose any candidate >= SCORE_MIN.
3351 * The first clause tells us to make preference the primary
3352 * deciding factor. So if it's lower, reject, if it's
3355 * The second clause tells us where the preference is
3356 * equal, we should use 'our judgement' of what we like
3357 * to see in an advertisement primarily.
3359 * But there can still be a tie. To make this deterministic,
3360 * we compare the server identifiers and select the binary
3363 * Since server id's are unique in this list, there is
3364 * no further tie to break.
3366 if ((rscore
< SCORE_MIN
) && (cscore
>= SCORE_MIN
)) {
3367 log_debug("PRC: | X-- Selected, has bindings.");
3368 } else if (cand
->pref
< rval
->pref
) {
3369 log_debug("PRC: | X-- Rejected, lower preference.");
3371 } else if (cand
->pref
> rval
->pref
) {
3372 log_debug("PRC: | X-- Selected, higher preference.");
3373 } else if (cscore
> rscore
) {
3374 log_debug("PRC: | X-- Selected, equal preference, "
3376 } else if (cscore
< rscore
) {
3377 log_debug("PRC: | X-- Rejected, equal preference, "
3380 } else if ((cand
->server_id
.len
< rval
->server_id
.len
) ||
3381 ((cand
->server_id
.len
== rval
->server_id
.len
) &&
3382 (memcmp(cand
->server_id
.data
,
3383 rval
->server_id
.data
,
3384 cand
->server_id
.len
) < 0))) {
3385 log_debug("PRC: | X-- Selected, equal preference, "
3386 "equal score, binary lesser server ID.");
3388 log_debug("PRC: | X-- Rejected, equal preference, "
3389 "equal score, binary greater server ID.");
3398 /* Remove the selected lease from the chain. */
3404 /* Select a lease out of the advertised leases and setup state to try and
3405 * acquire that lease.
3408 start_selecting6(struct client_state
*client
)
3410 struct dhc6_lease
*lease
;
3412 if (client
->advertised_leases
== NULL
) {
3413 log_error("Can not enter DHCPv6 SELECTING state with no "
3414 "leases to select from!");
3418 log_debug("PRC: Selecting best advertised lease.");
3419 client
->state
= S_SELECTING
;
3421 lease
= dhc6_best_lease(client
, &client
->advertised_leases
);
3424 log_fatal("Impossible error at %s:%d.", MDL
);
3426 client
->selected_lease
= lease
;
3428 /* Set timers per RFC3315 section 18.1.1. */
3429 client
->IRT
= REQ_TIMEOUT
* 100;
3430 client
->MRT
= REQ_MAX_RT
* 100;
3431 client
->MRC
= REQ_MAX_RC
;
3434 dhc6_retrans_init(client
);
3436 client
->v6_handler
= reply_handler
;
3438 /* ("re")transmit the first packet. */
3442 /* Transmit a Request to select a lease offered in Advertisements. In
3443 * the event of failure, either move on to the next-best advertised lease,
3444 * or head back to INIT state if there are none.
3447 do_select6(void *input
)
3449 struct client_state
*client
;
3450 struct dhc6_lease
*lease
;
3451 struct data_string ds
;
3453 int send_ret
, added
;
3457 /* 'lease' is fewer characters to type. */
3458 lease
= client
->selected_lease
;
3459 if (lease
== NULL
|| lease
->bindings
== NULL
) {
3460 log_error("Illegal to attempt selection without selecting "
3465 switch(check_timing6(client
, DHCPV6_REQUEST
, "Request", lease
, &ds
)) {
3466 case CHK_TIM_MRC_EXCEEDED
:
3467 case CHK_TIM_MRD_EXCEEDED
:
3468 log_debug("PRC: Lease %s failed.",
3469 print_hex_1(lease
->server_id
.len
,
3470 lease
->server_id
.data
, 56));
3472 /* Get rid of the lease that timed/counted out. */
3473 dhc6_lease_destroy(&lease
, MDL
);
3474 client
->selected_lease
= NULL
;
3476 /* If there are more leases great. If not, get more. */
3477 if (client
->advertised_leases
!= NULL
)
3478 start_selecting6(client
);
3480 start_init6(client
);
3482 case CHK_TIM_ALLOC_FAILURE
:
3484 case CHK_TIM_SUCCESS
:
3488 /* Now make a packet that looks suspiciously like the one we
3489 * got from the server. But different.
3491 * XXX: I guess IAID is supposed to be something the client
3492 * indicates and uses as a key to its internal state. It is
3493 * kind of odd to ask the server for IA's whose IAID the client
3494 * did not manufacture. We first need a formal dhclient.conf
3495 * construct for the iaid, then we can delve into this matter
3496 * more properly. In the time being, this will work.
3499 /* Fetch any configured 'sent' options (includes DUID) in wire format.
3501 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
,
3502 NULL
, client
->sent_options
, &global_scope
,
3505 /* Now append any IA's, and within them any IAADDR/IAPREFIXs.
3506 * For each type of IA (na, ta, pd) we start with the ones for
3507 * which we already have addresses (dhc6_add_ia_xx) and then
3508 * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
3511 ((dhc6_add_ia_na(client
, &ds
, lease
, DHCPV6_REQUEST
,
3512 wanted_ia_na
, &added
) != ISC_R_SUCCESS
) ||
3513 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_na
- added
,
3514 D6O_IA_NA
) != ISC_R_SUCCESS
))) {
3515 data_string_forget(&ds
, MDL
);
3519 ((dhc6_add_ia_ta(client
, &ds
, lease
, DHCPV6_REQUEST
,
3520 wanted_ia_ta
, &added
) != ISC_R_SUCCESS
) ||
3521 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_ta
- added
,
3522 D6O_IA_TA
) != ISC_R_SUCCESS
))) {
3523 data_string_forget(&ds
, MDL
);
3527 ((dhc6_add_ia_pd(client
, &ds
, lease
, DHCPV6_REQUEST
,
3528 wanted_ia_pd
, &added
) != ISC_R_SUCCESS
) ||
3529 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_pd
- added
,
3530 D6O_IA_PD
) != ISC_R_SUCCESS
))) {
3531 data_string_forget(&ds
, MDL
);
3535 log_info("XMT: Request on %s, interval %ld0ms.",
3536 client
->name
? client
->name
: client
->interface
->name
,
3537 (long int)client
->RT
);
3539 send_ret
= send_packet6(client
->interface
,
3540 ds
.data
, ds
.len
, &DHCPv6DestAddr
);
3541 if (send_ret
!= ds
.len
) {
3542 log_error("dhc6: send_packet6() sent %d of %d bytes",
3546 data_string_forget(&ds
, MDL
);
3549 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
3550 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
3551 if (tv
.tv_usec
>= 1000000) {
3553 tv
.tv_usec
-= 1000000;
3555 add_timeout(&tv
, do_select6
, client
, NULL
, NULL
);
3557 dhc6_retrans_advance(client
);
3562 * \brief Count the number of IAs in the bindings
3564 * \param lease the lease to count
3565 * \param ia_type the type of the IA we wish to count
3567 * \return The number of IAs of the specified type we found
3570 dhc6_count_ia(struct dhc6_lease
*lease
, u_int16_t ia_type
)
3575 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
3576 if (ia
->ia_type
== ia_type
)
3577 /* bump the counter for the correct types */
3586 * \brief Add IA_NA information from the lease to the packet
3589 * Walk through the lease and for each IA_NA in the lease
3590 * and for each address in the IA_NA append that information
3591 * onto the packet-so-far. If wanted is 0 include all IA_NAs
3592 * in the lease if wanted is non-zero include only that many
3593 * IA_NAs (this may occur if sommebody restarts a client with
3594 * arugments for a smaller number of NAs than before).
3596 * \param client = the state of the entire client
3597 * \param packet = the packet we are building and where we
3598 * shall append the IA_NAs we create
3599 * \param lease = the current lease
3600 * \param message = the type of the packet
3601 * \param wanted = the number of IA_NAs to include in the packet
3602 * 0 means include all
3603 * \param added = the number of IA_NAs that were added to the packet
3605 * \return ISC_R_SUCCESS - all is well continue, any other return
3606 * indicates an error (most likely memory issues)
3607 * and the packet should be tossed.
3610 dhc6_add_ia_na(struct client_state
*client
, struct data_string
*packet
,
3611 struct dhc6_lease
*lease
, u_int8_t message
,
3612 int wanted
, int *added
)
3614 struct data_string iads
;
3615 struct data_string addrds
;
3616 struct dhc6_addr
*addr
;
3618 isc_result_t rval
= ISC_R_SUCCESS
;
3623 memset(&iads
, 0, sizeof(iads
));
3624 memset(&addrds
, 0, sizeof(addrds
));
3625 for (ia
= lease
->bindings
, i
= 0;
3626 ia
!= NULL
&& rval
== ISC_R_SUCCESS
&& (wanted
== 0 || i
< wanted
);
3628 if (ia
->ia_type
!= D6O_IA_NA
)
3631 /* Now that we know this is an NA bump the counter */
3634 if (!buffer_allocate(&iads
.buffer
, 12, MDL
)) {
3635 log_error("Unable to allocate memory for IA_NA.");
3636 rval
= ISC_R_NOMEMORY
;
3640 /* Copy the IAID into the packet buffer. */
3641 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
3642 iads
.data
= iads
.buffer
->data
;
3646 case DHCPV6_REQUEST
:
3650 t1
= client
->config
->requested_lease
/ 2;
3652 #if MAX_TIME > 0xffffffff
3653 if (t1
> 0xffffffff)
3655 if (t2
> 0xffffffff)
3658 putULong(iads
.buffer
->data
+ 4, t1
);
3659 putULong(iads
.buffer
->data
+ 8, t2
);
3661 log_debug("XMT: X-- IA_NA %s",
3662 print_hex_1(4, iads
.data
, 59));
3663 log_debug("XMT: | X-- Requested renew +%u",
3665 log_debug("XMT: | X-- Requested rebind +%u",
3669 case DHCPV6_CONFIRM
:
3670 case DHCPV6_RELEASE
:
3671 case DHCPV6_DECLINE
:
3672 /* Set t1 and t2 to zero; server will ignore them */
3673 memset(iads
.buffer
->data
+ 4, 0, 8);
3674 log_debug("XMT: X-- IA_NA %s",
3675 print_hex_1(4, iads
.buffer
->data
, 55));
3680 log_fatal("Impossible condition at %s:%d.", MDL
);
3683 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
3685 * Do not confirm expired addresses, do not request
3686 * expired addresses (but we keep them around for
3689 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
3692 if (addr
->address
.len
!= 16) {
3693 log_error("Illegal IPv6 address length (%d), "
3694 "ignoring. (%s:%d)",
3695 addr
->address
.len
, MDL
);
3699 if (!buffer_allocate(&addrds
.buffer
, 24, MDL
)) {
3700 log_error("Unable to allocate memory for "
3702 rval
= ISC_R_NOMEMORY
;
3706 addrds
.data
= addrds
.buffer
->data
;
3709 /* Copy the address into the packet buffer. */
3710 memcpy(addrds
.buffer
->data
, addr
->address
.iabuf
, 16);
3712 /* Copy in additional information as appropriate */
3714 case DHCPV6_REQUEST
:
3717 t1
= client
->config
->requested_lease
;
3719 putULong(addrds
.buffer
->data
+ 16, t1
);
3720 putULong(addrds
.buffer
->data
+ 20, t2
);
3722 log_debug("XMT: | | X-- IAADDR %s",
3723 piaddr(addr
->address
));
3724 log_debug("XMT: | | | X-- Preferred "
3725 "lifetime +%u", (unsigned)t1
);
3726 log_debug("XMT: | | | X-- Max lifetime +%u",
3731 case DHCPV6_CONFIRM
:
3733 * Set preferred and max life to zero,
3736 memset(addrds
.buffer
->data
+ 16, 0, 8);
3737 log_debug("XMT: | X-- Confirm Address %s",
3738 piaddr(addr
->address
));
3741 case DHCPV6_RELEASE
:
3742 /* Preferred and max life are irrelevant */
3743 memset(addrds
.buffer
->data
+ 16, 0, 8);
3744 log_debug("XMT: | X-- Release Address %s",
3745 piaddr(addr
->address
));
3748 case DHCPV6_DECLINE
:
3749 /* Preferred and max life are irrelevant */
3750 memset(addrds
.buffer
->data
+ 16, 0, 8);
3751 log_debug("XMT: | X-- Decline Address %s",
3752 piaddr(addr
->address
));
3756 log_fatal("Impossible condition at %s:%d.",
3760 append_option(&iads
, &dhcpv6_universe
, iaaddr_option
,
3762 data_string_forget(&addrds
, MDL
);
3766 * It doesn't make sense to make a request without an
3769 if (ia
->addrs
== NULL
) {
3770 log_debug("!!!: V IA_NA has no IAADDRs - removed.");
3771 rval
= ISC_R_FAILURE
;
3772 } else if (rval
== ISC_R_SUCCESS
) {
3773 log_debug("XMT: V IA_NA appended.");
3774 append_option(packet
, &dhcpv6_universe
, ia_na_option
,
3778 data_string_forget(&iads
, MDL
);
3781 if (rval
== ISC_R_SUCCESS
)
3789 * \brief Add IA_TA information from the lease to the packet
3792 * Walk through the lease and for each IA_TA in the lease
3793 * and for each address in the IA_TA append that information
3794 * onto the packet-so-far. If wanted is 0 include all IA_TAs
3795 * in the lease if wanted is non-zero include only that many
3796 * IA_TAs (this may occur if sommebody restarts a client with
3797 * arugments for a smaller number of TAs than before).
3799 * \param client = the state of the entire client
3800 * \param packet = the packet we are building and where we
3801 * shall append the IA_TAs we create
3802 * \param lease = the current lease
3803 * \param message = the type of the packet
3804 * \param wanted = the number of IA_TAs to include in the packet
3805 * 0 means include all
3806 * \param added = the number of IA_TAs that were added to the packet
3808 * \return ISC_R_SUCCESS - all is well continue, any other return
3809 * indicates an error (most likely memory issues)
3810 * and the packet should be tossed.
3813 dhc6_add_ia_ta(struct client_state
*client
, struct data_string
*packet
,
3814 struct dhc6_lease
*lease
, u_int8_t message
,
3815 int wanted
, int *added
)
3817 struct data_string iads
;
3818 struct data_string addrds
;
3819 struct dhc6_addr
*addr
;
3821 isc_result_t rval
= ISC_R_SUCCESS
;
3826 memset(&iads
, 0, sizeof(iads
));
3827 memset(&addrds
, 0, sizeof(addrds
));
3828 for (ia
= lease
->bindings
, i
= 0;
3829 ia
!= NULL
&& rval
== ISC_R_SUCCESS
&& (wanted
== 0 || i
< wanted
);
3831 if (ia
->ia_type
!= D6O_IA_TA
)
3834 /* Now that we know this is an TA bump the counter */
3837 if (!buffer_allocate(&iads
.buffer
, 4, MDL
)) {
3838 log_error("Unable to allocate memory for IA_TA.");
3839 rval
= ISC_R_NOMEMORY
;
3843 /* Copy the IAID into the packet buffer. */
3844 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
3845 iads
.data
= iads
.buffer
->data
;
3848 log_debug("XMT: X-- IA_TA %s",
3849 print_hex_1(4, iads
.buffer
->data
, 55));
3851 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
3853 * Do not confirm expired addresses, do not request
3854 * expired addresses (but we keep them around for
3857 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
3860 if (addr
->address
.len
!= 16) {
3861 log_error("Illegal IPv6 address length (%d), "
3862 "ignoring. (%s:%d)",
3863 addr
->address
.len
, MDL
);
3867 if (!buffer_allocate(&addrds
.buffer
, 24, MDL
)) {
3868 log_error("Unable to allocate memory for "
3870 rval
= ISC_R_NOMEMORY
;
3874 addrds
.data
= addrds
.buffer
->data
;
3877 /* Copy the address into the packet buffer. */
3878 memcpy(addrds
.buffer
->data
, addr
->address
.iabuf
, 16);
3880 /* Copy in additional information as appropriate */
3882 case DHCPV6_REQUEST
:
3885 t1
= client
->config
->requested_lease
;
3887 putULong(addrds
.buffer
->data
+ 16, t1
);
3888 putULong(addrds
.buffer
->data
+ 20, t2
);
3890 log_debug("XMT: | | X-- IAADDR %s",
3891 piaddr(addr
->address
));
3892 log_debug("XMT: | | | X-- Preferred "
3893 "lifetime +%u", (unsigned)t1
);
3894 log_debug("XMT: | | | X-- Max lifetime +%u",
3899 case DHCPV6_CONFIRM
:
3901 * Set preferred and max life to zero,
3904 memset(addrds
.buffer
->data
+ 16, 0, 8);
3905 log_debug("XMT: | X-- Confirm Address %s",
3906 piaddr(addr
->address
));
3909 case DHCPV6_RELEASE
:
3910 /* Preferred and max life are irrelevant */
3911 memset(addrds
.buffer
->data
+ 16, 0, 8);
3912 log_debug("XMT: | X-- Release Address %s",
3913 piaddr(addr
->address
));
3917 log_fatal("Impossible condition at %s:%d.",
3921 append_option(&iads
, &dhcpv6_universe
, iaaddr_option
,
3923 data_string_forget(&addrds
, MDL
);
3927 * It doesn't make sense to make a request without an
3930 if (ia
->addrs
== NULL
) {
3931 log_debug("!!!: V IA_TA has no IAADDRs - removed.");
3932 rval
= ISC_R_FAILURE
;
3933 } else if (rval
== ISC_R_SUCCESS
) {
3934 log_debug("XMT: V IA_TA appended.");
3935 append_option(packet
, &dhcpv6_universe
, ia_ta_option
,
3939 data_string_forget(&iads
, MDL
);
3942 if (rval
== ISC_R_SUCCESS
)
3950 * \brief Add IA_PD information from the lease to the packet
3953 * Walk through the lease and for each IA_PD in the lease
3954 * and for each address in the IA_PD append that information
3955 * onto the packet-so-far. If wanted is 0 include all IA_PDs
3956 * in the lease if wanted is non-zero include only that many
3957 * IA_PDs (this may occur if sommebody restarts a client with
3958 * arugments for a smaller number of PDs than before).
3960 * \param client = the state of the entire client
3961 * \param packet = the packet we are building and where we
3962 * shall append the IA_PDs we create
3963 * \param lease = the current lease
3964 * \param message = the type of the packet
3965 * \param wanted = the number of IA_PDs to include in the packet
3966 * 0 means include all
3967 * \param added = the number of IA_PDs that were added to the packet
3969 * \return ISC_R_SUCCESS - all is well continue, any other return
3970 * indicates an error (most likely memory issues)
3971 * and the packet should be tossed.
3974 dhc6_add_ia_pd(struct client_state
*client
, struct data_string
*packet
,
3975 struct dhc6_lease
*lease
, u_int8_t message
,
3976 int wanted
, int *added
)
3978 struct data_string iads
;
3979 struct data_string prefds
;
3980 struct dhc6_addr
*pref
;
3982 isc_result_t rval
= ISC_R_SUCCESS
;
3987 memset(&iads
, 0, sizeof(iads
));
3988 memset(&prefds
, 0, sizeof(prefds
));
3989 for (ia
= lease
->bindings
, i
= 0;
3990 ia
!= NULL
&& rval
== ISC_R_SUCCESS
&& (wanted
== 0 || i
< wanted
);
3992 if (ia
->ia_type
!= D6O_IA_PD
)
3995 /* Now that we know this is an PD bump the counter */
3998 if (!buffer_allocate(&iads
.buffer
, 12, MDL
)) {
3999 log_error("Unable to allocate memory for IA_PD.");
4000 rval
= ISC_R_NOMEMORY
;
4004 /* Copy the IAID into the packet buffer. */
4005 memcpy(iads
.buffer
->data
, ia
->iaid
, 4);
4006 iads
.data
= iads
.buffer
->data
;
4010 case DHCPV6_REQUEST
:
4014 t1
= client
->config
->requested_lease
/ 2;
4016 #if MAX_TIME > 0xffffffff
4017 if (t1
> 0xffffffff)
4019 if (t2
> 0xffffffff)
4022 putULong(iads
.buffer
->data
+ 4, t1
);
4023 putULong(iads
.buffer
->data
+ 8, t2
);
4025 log_debug("XMT: X-- IA_PD %s",
4026 print_hex_1(4, iads
.data
, 59));
4027 log_debug("XMT: | X-- Requested renew +%u",
4029 log_debug("XMT: | X-- Requested rebind +%u",
4033 case DHCPV6_RELEASE
:
4034 /* Set t1 and t2 to zero; server will ignore them */
4035 memset(iads
.buffer
->data
+ 4, 0, 8);
4036 log_debug("XMT: X-- IA_PD %s",
4037 print_hex_1(4, iads
.buffer
->data
, 55));
4042 log_fatal("Impossible condition at %s:%d.", MDL
);
4045 for (pref
= ia
->addrs
; pref
!= NULL
; pref
= pref
->next
) {
4047 * Do not confirm expired prefixes, do not request
4048 * expired prefixes (but we keep them around for
4051 if (pref
->flags
& DHC6_ADDR_EXPIRED
)
4054 if (pref
->address
.len
!= 16) {
4055 log_error("Illegal IPv6 prefix "
4056 "ignoring. (%s:%d)",
4061 if (pref
->plen
== 0) {
4062 log_info("Null IPv6 prefix, "
4063 "ignoring. (%s:%d)",
4067 if (!buffer_allocate(&prefds
.buffer
, 25, MDL
)) {
4068 log_error("Unable to allocate memory for "
4070 rval
= ISC_R_NOMEMORY
;
4074 prefds
.data
= prefds
.buffer
->data
;
4077 /* Copy the prefix into the packet buffer. */
4078 putUChar(prefds
.buffer
->data
+ 8, pref
->plen
);
4079 memcpy(prefds
.buffer
->data
+ 9,
4080 pref
->address
.iabuf
,
4083 /* Copy in additional information as appropriate */
4085 case DHCPV6_REQUEST
:
4088 t1
= client
->config
->requested_lease
;
4090 putULong(prefds
.buffer
->data
, t1
);
4091 putULong(prefds
.buffer
->data
+ 4, t2
);
4093 log_debug("XMT: | | X-- IAPREFIX %s/%u",
4094 piaddr(pref
->address
),
4095 (unsigned) pref
->plen
);
4096 log_debug("XMT: | | | X-- Preferred "
4097 "lifetime +%u", (unsigned)t1
);
4098 log_debug("XMT: | | | X-- Max lifetime +%u",
4103 case DHCPV6_RELEASE
:
4104 /* Preferred and max life are irrelevant */
4105 memset(prefds
.buffer
->data
, 0, 8);
4106 log_debug("XMT: | X-- Release Prefix %s/%u",
4107 piaddr(pref
->address
),
4108 (unsigned) pref
->plen
);
4112 log_fatal("Impossible condition at %s:%d.",
4116 append_option(&iads
, &dhcpv6_universe
,
4117 iaprefix_option
, &prefds
);
4118 data_string_forget(&prefds
, MDL
);
4122 * It doesn't make sense to make a request without an
4125 if (ia
->addrs
== NULL
) {
4126 log_debug("!!!: V IA_PD has no IAPREFIXs - removed.");
4127 rval
= ISC_R_FAILURE
;
4128 } else if (rval
== ISC_R_SUCCESS
) {
4129 log_debug("XMT: V IA_PD appended.");
4130 append_option(packet
, &dhcpv6_universe
,
4131 ia_pd_option
, &iads
);
4134 data_string_forget(&iads
, MDL
);
4137 if (rval
== ISC_R_SUCCESS
)
4143 /* stopping_finished() checks if there is a remaining work to do.
4145 static isc_boolean_t
4146 stopping_finished(void)
4148 struct interface_info
*ip
;
4149 struct client_state
*client
;
4151 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
4152 for (client
= ip
-> client
; client
; client
= client
-> next
) {
4153 if (client
->state
!= S_STOPPED
)
4155 if (client
->active_lease
!= NULL
)
4162 /* reply_handler() accepts a Reply while we're attempting Select or Renew or
4163 * Rebind. Basically any Reply packet.
4166 reply_handler(struct packet
*packet
, struct client_state
*client
)
4168 struct dhc6_lease
*lease
;
4169 isc_result_t check_status
;
4171 if (packet
->dhcpv6_msg_type
!= DHCPV6_REPLY
)
4174 /* RFC3315 section 15.10 validation (same as 15.3 since we
4175 * always include a client id).
4177 if (!valid_reply(packet
, client
)) {
4178 log_error("Invalid Reply - rejecting.");
4182 lease
= dhc6_leaseify(packet
);
4184 /* Out of memory or corrupt packet condition...hopefully a temporary
4185 * problem. Returning now makes us try to retransmit later.
4190 check_status
= dhc6_check_reply(client
, lease
);
4191 if (check_status
!= ISC_R_SUCCESS
) {
4192 dhc6_lease_destroy(&lease
, MDL
);
4194 /* If no action was taken, but there is an error, then
4195 * we wait for a retransmission.
4197 if (check_status
!= ISC_R_CANCELED
)
4201 /* We're done retransmitting at this point. */
4202 cancel_timeout(do_confirm6
, client
);
4203 cancel_timeout(do_select6
, client
);
4204 cancel_timeout(do_refresh6
, client
);
4205 cancel_timeout(do_release6
, client
);
4207 /* If this is in response to a Release/Decline, clean up and return. */
4208 if (client
->state
== S_STOPPED
) {
4209 if (client
->active_lease
== NULL
)
4212 dhc6_lease_destroy(&client
->active_lease
, MDL
);
4213 client
->active_lease
= NULL
;
4214 /* We should never wait for nothing!? */
4215 if (stopping_finished())
4220 /* Action was taken, so now that we've torn down our scheduled
4221 * retransmissions, return.
4223 if (check_status
== ISC_R_CANCELED
)
4226 if (client
->selected_lease
!= NULL
) {
4227 dhc6_lease_destroy(&client
->selected_lease
, MDL
);
4228 client
->selected_lease
= NULL
;
4231 /* If this is in response to a confirm, we use the lease we've
4232 * already got, not the reply we were sent.
4234 if (client
->state
== S_REBOOTING
) {
4235 if (client
->active_lease
== NULL
)
4236 log_fatal("Impossible condition at %s:%d.", MDL
);
4238 dhc6_lease_destroy(&lease
, MDL
);
4239 start_bound(client
);
4243 /* Merge any bindings in the active lease (if there is one) into
4244 * the new active lease.
4246 dhc6_merge_lease(client
->active_lease
, lease
);
4248 /* Cleanup if a previous attempt to go bound failed. */
4249 if (client
->old_lease
!= NULL
) {
4250 dhc6_lease_destroy(&client
->old_lease
, MDL
);
4251 client
->old_lease
= NULL
;
4254 /* Make this lease active and BIND to it. */
4255 if (client
->active_lease
!= NULL
)
4256 client
->old_lease
= client
->active_lease
;
4257 client
->active_lease
= lease
;
4259 /* We're done with the ADVERTISEd leases, if any. */
4260 while(client
->advertised_leases
!= NULL
) {
4261 lease
= client
->advertised_leases
;
4262 client
->advertised_leases
= lease
->next
;
4264 dhc6_lease_destroy(&lease
, MDL
);
4267 start_bound(client
);
4270 /* DHCPv6 packets are a little sillier than they needed to be - the root
4271 * packet contains options, then IA's which contain options, then within
4272 * that IAADDR's which contain options.
4274 * To sort this out at dhclient-script time (which fetches config parameters
4275 * in environment variables), start_bound() iterates over each IAADDR, and
4276 * calls this function to marshall an environment variable set that includes
4277 * the most-specific option values related to that IAADDR in particular.
4279 * To achieve this, we load environment variables for the root options space,
4280 * then the IA, then the IAADDR. Any duplicate option names will be
4281 * over-written by the later versions.
4284 dhc6_marshall_values(const char *prefix
, struct client_state
*client
,
4285 struct dhc6_lease
*lease
, struct dhc6_ia
*ia
,
4286 struct dhc6_addr
*addr
)
4288 /* Option cache contents, in descending order of
4291 if ((lease
!= NULL
) && (lease
->options
!= NULL
))
4292 script_write_params6(client
, prefix
, lease
->options
);
4293 if ((ia
!= NULL
) && (ia
->options
!= NULL
))
4294 script_write_params6(client
, prefix
, ia
->options
);
4295 if ((addr
!= NULL
) && (addr
->options
!= NULL
))
4296 script_write_params6(client
, prefix
, addr
->options
);
4300 if ((ia
!= NULL
) && (ia
->ia_type
== D6O_IA_PD
)) {
4301 client_envadd(client
, prefix
,
4302 "ip6_prefix", "%s/%u",
4303 piaddr(addr
->address
),
4304 (unsigned) addr
->plen
);
4306 client_envadd(client
, prefix
, "ip6_prefixlen",
4307 "%d", DHCLIENT_DEFAULT_PREFIX_LEN
);
4308 client_envadd(client
, prefix
, "ip6_address",
4309 "%s", piaddr(addr
->address
));
4311 if ((ia
!= NULL
) && (ia
->ia_type
== D6O_IA_TA
)) {
4312 client_envadd(client
, prefix
,
4313 "ip6_type", "temporary");
4315 client_envadd(client
, prefix
, "life_starts", "%d",
4316 (int)(addr
->starts
));
4317 client_envadd(client
, prefix
, "preferred_life", "%u",
4318 addr
->preferred_life
);
4319 client_envadd(client
, prefix
, "max_life", "%u",
4325 client_envadd(client
, prefix
, "iaid", "%s",
4326 print_hex_1(4, ia
->iaid
, 12));
4327 client_envadd(client
, prefix
, "starts", "%d",
4329 client_envadd(client
, prefix
, "renew", "%u", ia
->renew
);
4330 client_envadd(client
, prefix
, "rebind", "%u", ia
->rebind
);
4334 /* Look at where the client's active lease is sitting. If it's looking to
4335 * time out on renew, rebind, depref, or expiration, do those things.
4338 dhc6_check_times(struct client_state
*client
)
4340 struct dhc6_lease
*lease
;
4342 struct dhc6_addr
*addr
;
4343 TIME renew
=MAX_TIME
, rebind
=MAX_TIME
, depref
=MAX_TIME
,
4344 lo_expire
=MAX_TIME
, hi_expire
=0, max_ia_starts
= 0, tmp
;
4345 int has_addrs
= ISC_FALSE
;
4348 lease
= client
->active_lease
;
4350 /* Bit spammy. We should probably keep record of scheduled
4353 cancel_timeout(start_renew6
, client
);
4354 cancel_timeout(start_rebind6
, client
);
4355 cancel_timeout(do_depref
, client
);
4356 cancel_timeout(do_expire
, client
);
4358 for(ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
4359 TIME this_ia_lo_expire
, this_ia_hi_expire
, use_expire
;
4361 this_ia_lo_expire
= MAX_TIME
;
4362 this_ia_hi_expire
= 0;
4364 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
4365 if(!(addr
->flags
& DHC6_ADDR_DEPREFFED
)) {
4366 if (addr
->preferred_life
== 0xffffffff)
4369 tmp
= addr
->starts
+
4370 addr
->preferred_life
;
4376 if (!(addr
->flags
& DHC6_ADDR_EXPIRED
)) {
4377 /* Find EPOCH-relative expiration. */
4378 if (addr
->max_life
== 0xffffffff)
4381 tmp
= addr
->starts
+ addr
->max_life
;
4383 /* Make the times ia->starts relative. */
4386 if (tmp
> this_ia_hi_expire
)
4387 this_ia_hi_expire
= tmp
;
4388 if (tmp
< this_ia_lo_expire
)
4389 this_ia_lo_expire
= tmp
;
4391 has_addrs
= ISC_TRUE
;
4395 /* These times are ia->starts relative. */
4396 if (this_ia_lo_expire
<= (this_ia_hi_expire
/ 2))
4397 use_expire
= this_ia_hi_expire
;
4399 use_expire
= this_ia_lo_expire
;
4402 * If the auto-selected expiration time is "infinite", or
4403 * zero, assert a reasonable default.
4405 if ((use_expire
== MAX_TIME
) || (use_expire
<= 1))
4406 use_expire
= client
->config
->requested_lease
/ 2;
4410 /* Don't renew/rebind temporary addresses. */
4411 /* For NA and PD we find the most recent IA and the smallest
4412 * values for the renew and rebind then base the timer on
4413 * the sum of the them.
4414 * Normally all the IAs will have the same time as they
4415 * are requested and served as a group but in some cases the
4416 * client isn't asking for all of the IAs (for example
4417 * restarted with a different set of arguments) or the server
4418 * isn't updating the client on all of them (probably a
4421 if (ia
->ia_type
!= D6O_IA_TA
) {
4422 if (ia
->starts
> max_ia_starts
)
4423 max_ia_starts
= ia
->starts
;
4425 if (ia
->renew
== 0) {
4427 } else if (ia
->renew
== 0xffffffff)
4435 if (ia
->rebind
== 0) {
4436 /* Set rebind to 3/4 expiration interval. */
4437 tmp
= use_expire
+ (use_expire
/ 2);
4438 } else if (ia
->rebind
== 0xffffffff)
4448 * Return expiration ranges to EPOCH relative for event
4449 * scheduling (add_timeout()).
4451 this_ia_hi_expire
+= ia
->starts
;
4452 this_ia_lo_expire
+= ia
->starts
;
4454 if (this_ia_hi_expire
> hi_expire
)
4455 hi_expire
= this_ia_hi_expire
;
4456 if (this_ia_lo_expire
< lo_expire
)
4457 lo_expire
= this_ia_lo_expire
;
4460 /* If there are no addresses, give up, go to INIT.
4461 * Note that if an address is unexpired with a date in the past,
4462 * we're scheduling an expiration event to ocurr in the past. We
4463 * could probably optimize this to expire now (but then there's
4466 * In the future, we may decide that we're done here, or to
4467 * schedule a future request (using 4-pkt info-request model).
4469 if (has_addrs
== ISC_FALSE
) {
4470 dhc6_lease_destroy(&client
->active_lease
, MDL
);
4471 client
->active_lease
= NULL
;
4473 /* Go back to the beginning. */
4474 start_init6(client
);
4478 /* Second part of calculating the renew and rebind times.
4479 * We have the start time and the desired periods for renew
4480 * and rebind, just add them to get the desired end time.
4482 if (renew
!= MAX_TIME
)
4483 renew
+= max_ia_starts
;
4484 if (rebind
!= MAX_TIME
)
4485 rebind
+= max_ia_starts
;
4487 switch(client
->state
) {
4489 /* We'd like to hit renewing, but if rebinding has already
4490 * passed (time warp), head straight there.
4492 if ((rebind
> cur_time
) && (renew
< rebind
)) {
4493 log_debug("PRC: Renewal event scheduled in %d seconds, "
4494 "to run for %u seconds.",
4495 (int)(renew
- cur_time
),
4496 (unsigned)(rebind
- renew
));
4497 client
->next_MRD
= rebind
;
4500 add_timeout(&tv
, start_renew6
, client
, NULL
, NULL
);
4506 /* While actively renewing, MRD is bounded by the time
4507 * we stop renewing and start rebinding. This helps us
4508 * process the state change on time.
4510 client
->MRD
= rebind
- cur_time
;
4511 if (rebind
!= MAX_TIME
) {
4512 log_debug("PRC: Rebind event scheduled in %d seconds, "
4513 "to run for %d seconds.",
4514 (int)(rebind
- cur_time
),
4515 (int)(hi_expire
- rebind
));
4516 client
->next_MRD
= hi_expire
;
4519 add_timeout(&tv
, start_rebind6
, client
, NULL
, NULL
);
4524 /* For now, we rebind up until the last lease expires. In
4525 * the future, we might want to start SOLICITing when we've
4526 * depreffed an address.
4528 client
->MRD
= hi_expire
- cur_time
;
4532 log_fatal("Impossible condition at %s:%d.", MDL
);
4535 /* Separately, set a time at which we will depref and expire
4536 * leases. This might happen with multiple addresses while we
4537 * keep trying to refresh.
4539 if (depref
!= MAX_TIME
) {
4540 log_debug("PRC: Depreference scheduled in %d seconds.",
4541 (int)(depref
- cur_time
));
4544 add_timeout(&tv
, do_depref
, client
, NULL
, NULL
);
4546 if (lo_expire
!= MAX_TIME
) {
4547 log_debug("PRC: Expiration scheduled in %d seconds.",
4548 (int)(lo_expire
- cur_time
));
4549 tv
.tv_sec
= lo_expire
;
4551 add_timeout(&tv
, do_expire
, client
, NULL
, NULL
);
4555 /* In a given IA chain, find the IA with the same type and 'iaid'. */
4556 static struct dhc6_ia
*
4557 find_ia(struct dhc6_ia
*head
, u_int16_t type
, const char *id
)
4561 for (ia
= head
; ia
!= NULL
; ia
= ia
->next
) {
4562 if (ia
->ia_type
!= type
)
4564 if (memcmp(ia
->iaid
, id
, 4) == 0)
4571 /* In a given address chain, find a matching address. */
4572 static struct dhc6_addr
*
4573 find_addr(struct dhc6_addr
*head
, struct iaddr
*address
)
4575 struct dhc6_addr
*addr
;
4577 for (addr
= head
; addr
!= NULL
; addr
= addr
->next
) {
4578 if ((addr
->address
.len
== address
->len
) &&
4579 (memcmp(addr
->address
.iabuf
, address
->iabuf
,
4580 address
->len
) == 0))
4587 /* In a given prefix chain, find a matching prefix. */
4588 static struct dhc6_addr
*
4589 find_pref(struct dhc6_addr
*head
, struct iaddr
*prefix
, u_int8_t plen
)
4591 struct dhc6_addr
*pref
;
4593 for (pref
= head
; pref
!= NULL
; pref
= pref
->next
) {
4594 if ((pref
->address
.len
== prefix
->len
) &&
4595 (pref
->plen
== plen
) &&
4596 (memcmp(pref
->address
.iabuf
, prefix
->iabuf
,
4606 * \brief Merge the bindings from the source lease into the destination
4607 * lease structure, where they are missing.
4609 * This is used to merge any extra information we have in the current
4610 * (older, src) lease into the lease we have just received. For example
4611 * the src lease might include a binding for an NA that is still usable
4612 * but that we didn't request or that the server is no longer serving.
4613 * We want to keep that information until we toss the binding (expire,
4614 * release) so we move it to the new lease.
4616 * We have to copy the stateful objects rather than move them over,
4617 * because later code needs to be able to compare new versus old if
4618 * they contain any bindings.
4620 * \param src The older lease to copy the objects from
4621 * \param dst The newer lease to copy the objects to
4624 dhc6_merge_lease(struct dhc6_lease
*src
, struct dhc6_lease
*dst
)
4626 struct dhc6_ia
*sia
, *dia
, *tia
, **eia
;
4627 struct dhc6_addr
*saddr
, *daddr
, *taddr
;
4630 if ((dst
== NULL
) || (src
== NULL
))
4633 for (sia
= src
->bindings
; sia
!= NULL
; sia
= sia
->next
) {
4634 dia
= find_ia(dst
->bindings
, sia
->ia_type
, (char *)sia
->iaid
);
4637 tia
= dhc6_dup_ia(sia
, MDL
);
4640 log_fatal("Out of memory merging lease - "
4641 "Unable to continue without losing "
4642 "state! (%s:%d)", MDL
);
4644 /* Put any bindings that aren't in the new lease at the
4645 * end of the list. If the user or server reduces the
4646 * number of IAs the ones in use will be at the front
4647 * and will be used when building the next requests
4648 * We could be more efficient by finding the end
4649 * of the list once but we don't expect to do this
4652 for (eia
= &dst
->bindings
;
4654 eia
= &(*eia
)->next
) {
4655 ; /* no work just find the end */
4660 for (saddr
= sia
->addrs
; saddr
!= NULL
;
4661 saddr
= saddr
->next
) {
4662 if (sia
->ia_type
!= D6O_IA_PD
)
4663 daddr
= find_addr(dia
->addrs
,
4666 daddr
= find_pref(dia
->addrs
,
4670 if (daddr
== NULL
) {
4671 taddr
= dhc6_dup_addr(saddr
, MDL
);
4674 log_fatal("Out of memory "
4676 "Unable to continue "
4681 /* XXX: consider sorting? */
4682 taddr
->next
= dia
->addrs
;
4690 /* If we made changes, reset the score to 0 so it is recalculated. */
4695 /* We've either finished selecting or succeeded in Renew or Rebinding our
4696 * lease. In all cases we got a Reply. Give dhclient-script a tickle
4697 * to inform it about the new values, and then lay in wait for the next
4701 start_bound(struct client_state
*client
)
4703 struct dhc6_ia
*ia
, *oldia
;
4704 struct dhc6_addr
*addr
, *oldaddr
;
4705 struct dhc6_lease
*lease
, *old
;
4707 #if defined (NSUPDATE)
4708 TIME dns_update_offset
= 1;
4711 lease
= client
->active_lease
;
4712 if (lease
== NULL
) {
4713 log_error("Cannot enter bound state unless an active lease "
4717 lease
->released
= ISC_FALSE
;
4718 old
= client
->old_lease
;
4720 client
->v6_handler
= bound_handler
;
4722 switch (client
->state
) {
4724 case S_REBOOTING
: /* Pretend we got bound. */
4737 log_fatal("Impossible condition at %s:%d.", MDL
);
4738 /* Silence compiler warnings. */
4742 log_debug("PRC: Bound to lease %s.",
4743 print_hex_1(client
->active_lease
->server_id
.len
,
4744 client
->active_lease
->server_id
.data
, 55));
4745 client
->state
= S_BOUND
;
4747 write_client6_lease(client
, lease
, 0, 1);
4750 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
4752 oldia
= find_ia(old
->bindings
,
4758 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
4759 /* Don't try to use the address if it's already expired */
4760 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
4763 if (oldia
!= NULL
) {
4764 if (ia
->ia_type
!= D6O_IA_PD
)
4765 oldaddr
= find_addr(oldia
->addrs
,
4768 oldaddr
= find_pref(oldia
->addrs
,
4774 #if defined (NSUPDATE)
4775 if ((oldaddr
== NULL
) && (ia
->ia_type
== D6O_IA_NA
))
4776 dhclient_schedule_updates(client
,
4778 dns_update_offset
++);
4781 /* Shell out to setup the new binding. */
4782 script_init(client
, reason
, NULL
);
4785 dhc6_marshall_values("old_", client
, old
,
4787 dhc6_marshall_values("new_", client
, lease
, ia
, addr
);
4788 script_write_requested6(client
);
4793 /* XXX: maybe we should loop on the old values instead? */
4794 if (ia
->addrs
== NULL
) {
4795 script_init(client
, reason
, NULL
);
4798 dhc6_marshall_values("old_", client
, old
,
4801 oldia
->addrs
: NULL
);
4803 dhc6_marshall_values("new_", client
, lease
, ia
,
4805 script_write_requested6(client
);
4811 /* XXX: maybe we should loop on the old values instead? */
4812 if (lease
->bindings
== NULL
) {
4813 script_init(client
, reason
, NULL
);
4816 dhc6_marshall_values("old_", client
, old
,
4818 (old
->bindings
!= NULL
) ?
4819 old
->bindings
->addrs
: NULL
);
4821 dhc6_marshall_values("new_", client
, lease
, NULL
, NULL
);
4822 script_write_requested6(client
);
4829 if (client
->old_lease
!= NULL
) {
4830 dhc6_lease_destroy(&client
->old_lease
, MDL
);
4831 client
->old_lease
= NULL
;
4834 /* Schedule events. */
4835 dhc6_check_times(client
);
4838 /* While bound, ignore packets. In the future we'll want to answer
4839 * Reconfigure-Request messages and the like.
4842 bound_handler(struct packet
*packet
, struct client_state
*client
)
4844 log_debug("RCV: Input packets are ignored once bound.");
4847 /* start_renew6() gets us all ready to go to start transmitting Renew packets.
4848 * Note that client->next_MRD must be set before entering this function -
4849 * it must be set to the time at which the client should start Rebinding.
4852 start_renew6(void *input
)
4854 struct client_state
*client
;
4856 client
= (struct client_state
*)input
;
4858 log_info("PRC: Renewing lease on %s.",
4859 client
->name
? client
->name
: client
->interface
->name
);
4860 client
->state
= S_RENEWING
;
4862 client
->v6_handler
= reply_handler
;
4864 /* Times per RFC3315 section 18.1.3. */
4865 client
->IRT
= REN_TIMEOUT
* 100;
4866 client
->MRT
= REN_MAX_RT
* 100;
4868 /* MRD is special in renew - we need to set it by checking timer
4871 client
->MRD
= client
->next_MRD
- cur_time
;
4873 dhc6_retrans_init(client
);
4875 client
->refresh_type
= DHCPV6_RENEW
;
4876 do_refresh6(client
);
4879 /* do_refresh6() transmits one DHCPv6 packet, be it a Renew or Rebind, and
4880 * gives the retransmission state a bump for the next time. Note that
4881 * client->refresh_type must be set before entering this function.
4884 do_refresh6(void *input
)
4886 struct option_cache
*oc
;
4887 struct sockaddr_in6 unicast
, *dest_addr
= &DHCPv6DestAddr
;
4888 struct data_string ds
;
4889 struct client_state
*client
;
4890 struct dhc6_lease
*lease
;
4891 struct timeval elapsed
, tv
;
4892 int send_ret
, added
;
4894 client
= (struct client_state
*)input
;
4895 memset(&ds
, 0, sizeof(ds
));
4897 lease
= client
->active_lease
;
4898 if (lease
== NULL
) {
4899 log_error("Cannot renew without an active binding.");
4903 /* Ensure we're emitting a valid message type. */
4904 switch (client
->refresh_type
) {
4910 log_fatal("Internal inconsistency (%d) at %s:%d.",
4911 client
->refresh_type
, MDL
);
4915 * Start_time starts at the first transmission.
4917 if (client
->txcount
== 0) {
4918 client
->start_time
.tv_sec
= cur_tv
.tv_sec
;
4919 client
->start_time
.tv_usec
= cur_tv
.tv_usec
;
4922 /* elapsed = cur - start */
4923 elapsed
.tv_sec
= cur_tv
.tv_sec
- client
->start_time
.tv_sec
;
4924 elapsed
.tv_usec
= cur_tv
.tv_usec
- client
->start_time
.tv_usec
;
4925 if (elapsed
.tv_usec
< 0) {
4926 elapsed
.tv_sec
-= 1;
4927 elapsed
.tv_usec
+= 1000000;
4929 if (((client
->MRC
!= 0) && (client
->txcount
> client
->MRC
)) ||
4930 ((client
->MRD
!= 0) && (elapsed
.tv_sec
>= client
->MRD
))) {
4931 /* We're done. Move on to the next phase, if any. */
4932 dhc6_check_times(client
);
4937 * Check whether the server has sent a unicast option; if so, we can
4938 * use the address it specified for RENEWs.
4940 oc
= lookup_option(&dhcpv6_universe
, lease
->options
, D6O_UNICAST
);
4941 if (oc
&& evaluate_option_cache(&ds
, NULL
, NULL
, NULL
,
4942 lease
->options
, NULL
, &global_scope
,
4945 log_error("Invalid unicast option length %d.", ds
.len
);
4947 memset(&unicast
, 0, sizeof(DHCPv6DestAddr
));
4948 unicast
.sin6_family
= AF_INET6
;
4949 unicast
.sin6_port
= remote_port
;
4950 memcpy(&unicast
.sin6_addr
, ds
.data
, 16);
4951 if (client
->refresh_type
== DHCPV6_RENEW
) {
4952 dest_addr
= &unicast
;
4956 data_string_forget(&ds
, MDL
);
4959 /* Commence forming a renew packet. */
4960 memset(&ds
, 0, sizeof(ds
));
4961 if (!buffer_allocate(&ds
.buffer
, 4, MDL
)) {
4962 log_error("Unable to allocate memory for packet.");
4965 ds
.data
= ds
.buffer
->data
;
4968 ds
.buffer
->data
[0] = client
->refresh_type
;
4969 memcpy(ds
.buffer
->data
+ 1, client
->dhcpv6_transaction_id
, 3);
4971 /* Form an elapsed option. */
4972 /* Maximum value is 65535 1/100s coded as 0xffff. */
4973 if ((elapsed
.tv_sec
< 0) || (elapsed
.tv_sec
> 655) ||
4974 ((elapsed
.tv_sec
== 655) && (elapsed
.tv_usec
> 350000))) {
4975 client
->elapsed
= 0xffff;
4977 client
->elapsed
= elapsed
.tv_sec
* 100;
4978 client
->elapsed
+= elapsed
.tv_usec
/ 10000;
4981 if (client
->elapsed
== 0)
4982 log_debug("XMT: Forming %s, 0 ms elapsed.",
4983 dhcpv6_type_names
[client
->refresh_type
]);
4985 log_debug("XMT: Forming %s, %u0 ms elapsed.",
4986 dhcpv6_type_names
[client
->refresh_type
],
4987 (unsigned)client
->elapsed
);
4989 client
->elapsed
= htons(client
->elapsed
);
4991 make_client6_options(client
, &client
->sent_options
, lease
,
4992 client
->refresh_type
);
4994 /* Put in any options from the sent cache. */
4995 dhcpv6_universe
.encapsulate(&ds
, NULL
, NULL
, client
, NULL
,
4996 client
->sent_options
, &global_scope
,
4999 /* Now append any IA's, and within them any IAADDR/IAPREFIXs.
5000 * For each type of IA (na, ta, pd) we start with the ones for
5001 * which we already have addresses (dhc6_add_ia_xx) and then
5002 * if we still want more we add aditional IAs (dhc6_bare_ia_xx)
5005 ((dhc6_add_ia_na(client
, &ds
, lease
, client
->refresh_type
,
5006 wanted_ia_na
, &added
) != ISC_R_SUCCESS
) ||
5007 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_na
- added
,
5008 D6O_IA_NA
) != ISC_R_SUCCESS
))) {
5009 data_string_forget(&ds
, MDL
);
5013 ((dhc6_add_ia_pd(client
, &ds
, lease
, client
->refresh_type
,
5014 wanted_ia_pd
, &added
) != ISC_R_SUCCESS
) ||
5015 (dhc6_bare_ia_xx(client
, &ds
, wanted_ia_pd
- added
,
5016 D6O_IA_PD
) != ISC_R_SUCCESS
))) {
5017 data_string_forget(&ds
, MDL
);
5021 log_info("XMT: %s on %s, interval %ld0ms.",
5022 dhcpv6_type_names
[client
->refresh_type
],
5023 client
->name
? client
->name
: client
->interface
->name
,
5024 (long int)client
->RT
);
5026 send_ret
= send_packet6(client
->interface
, ds
.data
, ds
.len
, dest_addr
);
5028 if (send_ret
!= ds
.len
) {
5029 log_error("dhc6: send_packet6() sent %d of %d bytes",
5033 data_string_forget(&ds
, MDL
);
5036 tv
.tv_sec
= cur_tv
.tv_sec
+ client
->RT
/ 100;
5037 tv
.tv_usec
= cur_tv
.tv_usec
+ (client
->RT
% 100) * 10000;
5038 if (tv
.tv_usec
>= 1000000) {
5040 tv
.tv_usec
-= 1000000;
5042 add_timeout(&tv
, do_refresh6
, client
, NULL
, NULL
);
5044 dhc6_retrans_advance(client
);
5047 /* start_rebind6() gets us all set up to go and rebind a lease. Note that
5048 * client->next_MRD must be set before entering this function. In this case,
5049 * MRD must be set to the maximum time any address in the packet will
5053 start_rebind6(void *input
)
5055 struct client_state
*client
;
5057 client
= (struct client_state
*)input
;
5059 log_info("PRC: Rebinding lease on %s.",
5060 client
->name
? client
->name
: client
->interface
->name
);
5061 client
->state
= S_REBINDING
;
5063 client
->v6_handler
= reply_handler
;
5065 /* Times per RFC3315 section 18.1.4. */
5066 client
->IRT
= REB_TIMEOUT
* 100;
5067 client
->MRT
= REB_MAX_RT
* 100;
5069 /* MRD is special in rebind - it's determined by the timer
5072 client
->MRD
= client
->next_MRD
- cur_time
;
5074 dhc6_retrans_init(client
);
5076 client
->refresh_type
= DHCPV6_REBIND
;
5077 do_refresh6(client
);
5080 /* do_depref() runs through a given lease's addresses, for each that has
5081 * not yet been depreffed, shells out to the dhclient-script to inform it
5082 * of the status change. The dhclient-script should then do...something...
5083 * to encourage applications to move off the address and onto one of the
5084 * remaining 'preferred' addresses.
5087 do_depref(void *input
)
5089 struct client_state
*client
;
5090 struct dhc6_lease
*lease
;
5092 struct dhc6_addr
*addr
;
5094 client
= (struct client_state
*)input
;
5096 lease
= client
->active_lease
;
5100 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
5101 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
5102 if (addr
->flags
& DHC6_ADDR_DEPREFFED
)
5105 if (addr
->starts
+ addr
->preferred_life
<= cur_time
) {
5106 script_init(client
, "DEPREF6", NULL
);
5107 dhc6_marshall_values("cur_", client
, lease
,
5109 script_write_requested6(client
);
5112 addr
->flags
|= DHC6_ADDR_DEPREFFED
;
5114 if (ia
->ia_type
!= D6O_IA_PD
)
5115 log_info("PRC: Address %s depreferred.",
5116 piaddr(addr
->address
));
5118 log_info("PRC: Prefix %s/%u depreferred.",
5119 piaddr(addr
->address
),
5120 (unsigned) addr
->plen
);
5122 #if defined (NSUPDATE)
5123 /* Remove DDNS bindings at depref time. */
5124 if ((ia
->ia_type
== D6O_IA_NA
) &&
5125 client
->config
->do_forward_update
)
5126 client_dns_remove(client
,
5133 dhc6_check_times(client
);
5136 /* do_expire() searches through all the addresses on a given lease, and
5137 * expires/removes any addresses that are no longer valid.
5140 do_expire(void *input
)
5142 struct client_state
*client
;
5143 struct dhc6_lease
*lease
;
5144 struct dhc6_ia
*ia
, **tia
;
5145 struct dhc6_addr
*addr
;
5146 int has_addrs
= ISC_FALSE
;
5147 int ia_has_addrs
= ISC_FALSE
;
5149 client
= (struct client_state
*)input
;
5151 lease
= client
->active_lease
;
5155 for (ia
= lease
->bindings
, tia
= &lease
->bindings
; ia
!= NULL
; ) {
5156 ia_has_addrs
= ISC_FALSE
;
5157 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
5158 if (addr
->flags
& DHC6_ADDR_EXPIRED
)
5161 if (addr
->starts
+ addr
->max_life
<= cur_time
) {
5162 script_init(client
, "EXPIRE6", NULL
);
5163 dhc6_marshall_values("old_", client
, lease
,
5165 script_write_requested6(client
);
5168 addr
->flags
|= DHC6_ADDR_EXPIRED
;
5170 if (ia
->ia_type
!= D6O_IA_PD
)
5171 log_info("PRC: Address %s expired.",
5172 piaddr(addr
->address
));
5174 log_info("PRC: Prefix %s/%u expired.",
5175 piaddr(addr
->address
),
5176 (unsigned) addr
->plen
);
5178 #if defined (NSUPDATE)
5179 /* We remove DNS records at depref time, but
5180 * it is possible that we might get here
5181 * without depreffing.
5183 if ((ia
->ia_type
== D6O_IA_NA
) &&
5184 client
->config
->do_forward_update
&&
5185 !(addr
->flags
& DHC6_ADDR_DEPREFFED
))
5186 client_dns_remove(client
,
5193 ia_has_addrs
= ISC_TRUE
;
5194 has_addrs
= ISC_TRUE
;
5197 /* Update to the next ia and git rid of this ia
5198 * if it doesn't have any leases.
5200 if (ia_has_addrs
== ISC_TRUE
) {
5201 /* leases, just advance the list pointer */
5202 tia
= &(*tia
)->next
;
5204 /* no leases, update the list pointer
5208 dhc6_ia_destroy(&ia
, MDL
);
5210 /* lastly update the ia pointer to our new ia */
5214 /* Clean up empty leases. */
5215 if (has_addrs
== ISC_FALSE
) {
5216 log_info("PRC: Bound lease is devoid of active addresses."
5217 " Re-initializing.");
5219 dhc6_lease_destroy(&lease
, MDL
);
5220 client
->active_lease
= NULL
;
5222 start_init6(client
);
5226 /* Schedule the next run through. */
5227 dhc6_check_times(client
);
5231 * Run client script to unconfigure interface.
5232 * Called with reason STOP6 when dhclient -x is run, or with reason
5233 * RELEASE6 when server has replied to a Release message.
5234 * Stateless is a special case.
5237 unconfigure6(struct client_state
*client
, const char *reason
)
5240 struct dhc6_addr
*addr
;
5243 script_init(client
, reason
, NULL
);
5244 if (client
->active_lease
!= NULL
)
5245 script_write_params6(client
, "old_",
5246 client
->active_lease
->options
);
5247 script_write_requested6(client
);
5252 if (client
->active_lease
== NULL
)
5255 for (ia
= client
->active_lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
5256 if (ia
->ia_type
== D6O_IA_TA
)
5259 for (addr
= ia
->addrs
; addr
!= NULL
; addr
= addr
->next
) {
5260 script_init(client
, reason
, NULL
);
5261 dhc6_marshall_values("old_", client
,
5262 client
->active_lease
, ia
, addr
);
5263 script_write_requested6(client
);
5266 #if defined (NSUPDATE)
5267 if ((ia
->ia_type
== D6O_IA_NA
) &&
5268 client
->config
->do_forward_update
)
5269 client_dns_remove(client
, &addr
->address
);
5276 refresh_info_request6(void *input
)
5278 struct client_state
*client
;
5280 client
= (struct client_state
*)input
;
5281 start_info_request6(client
);
5284 /* Timeout for Information-Request (using the IRT option).
5287 dhc6_check_irt(struct client_state
*client
)
5289 struct option
**req
;
5290 struct option_cache
*oc
;
5291 TIME expire
= MAX_TIME
;
5294 isc_boolean_t found
= ISC_FALSE
;
5296 cancel_timeout(refresh_info_request6
, client
);
5298 req
= client
->config
->requested_options
;
5299 for (i
= 0; req
[i
] != NULL
; i
++) {
5300 if (req
[i
] == irt_option
) {
5305 /* Simply return gives a endless loop waiting for nothing. */
5309 oc
= lookup_option(&dhcpv6_universe
, client
->active_lease
->options
,
5310 D6O_INFORMATION_REFRESH_TIME
);
5312 struct data_string irt
;
5314 memset(&irt
, 0, sizeof(irt
));
5315 if (!evaluate_option_cache(&irt
, NULL
, NULL
, client
,
5316 client
->active_lease
->options
,
5317 NULL
, &global_scope
, oc
, MDL
) ||
5319 log_error("Can't evaluate IRT.");
5321 expire
= getULong(irt
.data
);
5322 if (expire
< IRT_MINIMUM
)
5323 expire
= IRT_MINIMUM
;
5324 if (expire
== 0xffffffff)
5327 data_string_forget(&irt
, MDL
);
5329 expire
= IRT_DEFAULT
;
5331 if (expire
!= MAX_TIME
) {
5332 log_debug("PRC: Refresh event scheduled in %u seconds.",
5334 tv
.tv_sec
= cur_time
+ expire
;
5336 add_timeout(&tv
, refresh_info_request6
, client
, NULL
, NULL
);
5340 /* We got a Reply. Give dhclient-script a tickle to inform it about
5341 * the new values, and then lay in wait for the next event.
5344 start_informed(struct client_state
*client
)
5346 client
->v6_handler
= informed_handler
;
5348 log_debug("PRC: Done.");
5350 client
->state
= S_BOUND
;
5352 script_init(client
, "RENEW6", NULL
);
5353 if (client
->old_lease
!= NULL
)
5354 script_write_params6(client
, "old_",
5355 client
->old_lease
->options
);
5356 script_write_params6(client
, "new_", client
->active_lease
->options
);
5357 script_write_requested6(client
);
5362 if (client
->old_lease
!= NULL
) {
5363 dhc6_lease_destroy(&client
->old_lease
, MDL
);
5364 client
->old_lease
= NULL
;
5367 /* Schedule events. */
5368 dhc6_check_irt(client
);
5371 /* While informed, ignore packets.
5374 informed_handler(struct packet
*packet
, struct client_state
*client
)
5376 log_debug("RCV: Input packets are ignored once bound.");
5379 /* make_client6_options() fetches option caches relevant to the client's
5380 * scope and places them into the sent_options cache. This cache is later
5381 * used to populate DHCPv6 output packets with options.
5384 make_client6_options(struct client_state
*client
, struct option_state
**op
,
5385 struct dhc6_lease
*lease
, u_int8_t message
)
5387 struct option_cache
*oc
;
5388 struct option
**req
;
5389 struct buffer
*buffer
;
5390 int buflen
, i
, oro_len
;
5392 if ((op
== NULL
) || (client
== NULL
))
5396 option_state_dereference(op
, MDL
);
5398 /* Create a cache to carry options to transmission. */
5399 option_state_allocate(op
, MDL
);
5401 /* Create and store an 'elapsed time' option in the cache. */
5403 if (option_cache_allocate(&oc
, MDL
)) {
5404 const unsigned char *cdata
;
5406 cdata
= (unsigned char *)&client
->elapsed
;
5408 if (make_const_data(&oc
->expression
, cdata
, 2, 0, 0, MDL
)) {
5409 option_reference(&oc
->option
, elapsed_option
, MDL
);
5410 save_option(&dhcpv6_universe
, *op
, oc
);
5413 option_cache_dereference(&oc
, MDL
);
5416 /* Bring in any configured options to send. */
5417 if (client
->config
->on_transmission
)
5418 execute_statements_in_scope(NULL
, NULL
, NULL
, client
,
5419 lease
? lease
->options
: NULL
,
5421 client
->config
->on_transmission
,
5424 /* Rapid-commit is only for SOLICITs. */
5425 if (message
!= DHCPV6_SOLICIT
)
5426 delete_option(&dhcpv6_universe
, *op
, D6O_RAPID_COMMIT
);
5428 /* See if the user configured a DUID in a relevant scope. If not,
5429 * introduce our default manufactured id.
5431 if ((oc
= lookup_option(&dhcpv6_universe
, *op
,
5432 D6O_CLIENTID
)) == NULL
) {
5433 if (!option_cache(&oc
, &default_duid
, NULL
, clientid_option
,
5435 log_fatal("Failure assembling a DUID.");
5437 save_option(&dhcpv6_universe
, *op
, oc
);
5438 option_cache_dereference(&oc
, MDL
);
5441 /* In cases where we're responding to a single server, put the
5442 * server's id in the response.
5444 * Note that lease is NULL for SOLICIT or INFO request messages,
5445 * and otherwise MUST be present.
5447 if (lease
== NULL
) {
5448 if ((message
!= DHCPV6_SOLICIT
) &&
5449 (message
!= DHCPV6_INFORMATION_REQUEST
))
5450 log_fatal("Impossible condition at %s:%d.", MDL
);
5451 } else if ((message
!= DHCPV6_REBIND
) &&
5452 (message
!= DHCPV6_CONFIRM
)) {
5453 oc
= lookup_option(&dhcpv6_universe
, lease
->options
,
5456 save_option(&dhcpv6_universe
, *op
, oc
);
5459 /* 'send dhcp6.oro foo;' syntax we used in 4.0.0a1/a2 has been
5460 * deprecated by adjustments to the 'request' syntax also used for
5463 if (lookup_option(&dhcpv6_universe
, *op
, D6O_ORO
) != NULL
)
5464 log_error("'send dhcp6.oro' syntax is deprecated, please "
5465 "use the 'request' syntax (\"man dhclient.conf\").");
5467 /* Construct and store an ORO (Option Request Option). It is a
5468 * fatal error to fail to send an ORO (of at least zero length).
5470 * Discussion: RFC3315 appears to be inconsistent in its statements
5471 * of whether or not the ORO is mandatory. In section 18.1.1
5472 * ("Creation and Transmission of Request Messages"):
5474 * The client MUST include an Option Request option (see section
5475 * 22.7) to indicate the options the client is interested in
5476 * receiving. The client MAY include options with data values as
5477 * hints to the server about parameter values the client would like
5480 * This MUST is missing from the creation/transmission of other
5481 * messages (such as Renew and Rebind), and the section 22.7 ("Option
5482 * Request Option" format and definition):
5484 * A client MAY include an Option Request option in a Solicit,
5485 * Request, Renew, Rebind, Confirm or Information-request message to
5486 * inform the server about options the client wants the server to
5487 * send to the client. A server MAY include an Option Request
5488 * option in a Reconfigure option to indicate which options the
5489 * client should request from the server.
5491 * seems to relax the requirement from MUST to MAY (and still other
5492 * language in RFC3315 supports this).
5494 * In lieu of a clarification of RFC3315, we will conform with the
5495 * MUST. Instead of an absent ORO, we will if there are no options
5496 * to request supply an empty ORO. Theoretically, an absent ORO is
5497 * difficult to interpret (does the client want all options or no
5498 * options?). A zero-length ORO is intuitively clear: requesting
5504 if (!buffer_allocate(&buffer
, buflen
, MDL
))
5505 log_fatal("Out of memory constructing DHCPv6 ORO.");
5506 req
= client
->config
->requested_options
;
5508 for (i
= 0 ; req
[i
] != NULL
; i
++) {
5509 if (buflen
== oro_len
) {
5510 struct buffer
*tmpbuf
= NULL
;
5515 buffer_reference(&tmpbuf
, buffer
, MDL
);
5516 buffer_dereference(&buffer
, MDL
);
5518 if (!buffer_allocate(&buffer
, buflen
, MDL
))
5519 log_fatal("Out of memory resizing "
5520 "DHCPv6 ORO buffer.");
5522 memcpy(buffer
->data
, tmpbuf
->data
, oro_len
);
5524 buffer_dereference(&tmpbuf
, MDL
);
5527 if (req
[i
]->universe
== &dhcpv6_universe
) {
5528 /* Append the code to the ORO. */
5529 putUShort(buffer
->data
+ oro_len
,
5537 if (make_const_option_cache(&oc
, &buffer
, NULL
, oro_len
,
5539 save_option(&dhcpv6_universe
, *op
, oc
);
5541 log_fatal("Unable to create ORO option cache.");
5545 * Note: make_const_option_cache() consumes the buffer, we do not
5546 * need to dereference it (XXX).
5548 option_cache_dereference(&oc
, MDL
);
5551 /* A clone of the DHCPv4 script_write_params() minus the DHCPv4-specific
5552 * filename, server-name, etc specifics.
5554 * Simply, store all values present in all universes of the option state
5555 * (probably derived from a DHCPv6 packet) into environment variables
5556 * named after the option names (and universe names) but with the 'prefix'
5559 * Later, dhclient-script may compare for example "new_time_servers" and
5560 * "old_time_servers" for differences, and only upon detecting a change
5561 * bother to rewrite ntp.conf and restart it. Or something along those
5565 script_write_params6(struct client_state
*client
, const char *prefix
,
5566 struct option_state
*options
)
5568 struct envadd_state es
;
5571 if (options
== NULL
)
5577 for (i
= 0 ; i
< options
->universe_count
; i
++) {
5578 option_space_foreach(NULL
, NULL
, client
, NULL
, options
,
5579 &global_scope
, universes
[i
], &es
,
5580 client_option_envadd
);
5585 * A clone of the DHCPv4 routine.
5586 * Write out the environment variables for the objects that the
5587 * client requested. If the object was requested the variable will be:
5588 * requested_<option_name>=1
5589 * If it wasn't requested there won't be a variable.
5591 static void script_write_requested6(client
)
5592 struct client_state
*client
;
5595 struct option
**req
;
5597 req
= client
->config
->requested_options
;
5602 for (i
= 0 ; req
[i
] != NULL
; i
++) {
5603 if ((req
[i
]->universe
== &dhcpv6_universe
) &&
5604 dhcp_option_ev_name (name
, sizeof(name
), req
[i
])) {
5605 client_envadd(client
, "requested_", name
, "%d", 1);
5611 * Check if there is something not fully defined in the active lease.
5613 static isc_boolean_t
5614 active_prefix(struct client_state
*client
)
5616 struct dhc6_lease
*lease
;
5618 struct dhc6_addr
*pref
;
5621 lease
= client
->active_lease
;
5624 memset(zeros
, 0, 16);
5625 for (ia
= lease
->bindings
; ia
!= NULL
; ia
= ia
->next
) {
5626 if (ia
->ia_type
!= D6O_IA_PD
)
5628 for (pref
= ia
->addrs
; pref
!= NULL
; pref
= pref
->next
) {
5629 if (pref
->plen
== 0)
5631 if (pref
->address
.len
!= 16)
5633 if (memcmp(pref
->address
.iabuf
, zeros
, 16) == 0)