2 * Copyright (C) 2006-2012 by Internet Systems Consortium, Inc. ("ISC")
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
22 * We use print_hex_1() to output DUID values. We could actually output
23 * the DUID with more information... MAC address if using type 1 or 3,
24 * and so on. However, RFC 3315 contains Grave Warnings against actually
25 * attempting to understand a DUID.
29 * TODO: gettext() or other method of localization for the messages
30 * for status codes (and probably for log formats eventually)
31 * TODO: refactoring (simplify, simplify, simplify)
32 * TODO: support multiple shared_networks on each interface (this
33 * will allow the server to issue multiple IPv6 addresses to
38 * DHCPv6 Reply workflow assist. A Reply packet is built by various
39 * different functions; this gives us one location where we keep state
43 /* root level persistent state */
44 struct shared_network
*shared
;
45 struct host_decl
*host
;
46 struct subnet
*subnet
; /* Used to match fixed-addrs to subnet scopes. */
47 struct option_state
*opt_state
;
48 struct packet
*packet
;
49 struct data_string client_id
;
51 /* IA level persistent state */
54 unsigned client_resources
;
55 isc_boolean_t resources_included
;
56 isc_boolean_t static_lease
;
57 unsigned static_prefixes
;
60 struct option_state
*reply_ia
;
61 struct data_string fixed
;
63 /* IAADDR/PREFIX level persistent state */
64 struct iasubopt
*lease
;
67 * "t1", "t2", preferred, and valid lifetimes records for calculating
68 * t1 and t2 (min/max).
70 u_int32_t renew
, rebind
, prefer
, valid
;
72 /* Client-requested valid and preferred lifetimes. */
73 u_int32_t client_valid
, client_prefer
;
75 /* Chosen values to transmit for valid and preferred lifetimes. */
76 u_int32_t send_valid
, send_prefer
;
78 /* Preferred prefix length (-1 is any). */
81 /* Index into the data field that has been consumed. */
85 unsigned char data
[65536];
86 struct dhcpv6_packet reply
;
91 * Prototypes local to this file.
93 static int get_encapsulated_IA_state(struct option_state
**enc_opt_state
,
94 struct data_string
*enc_opt_data
,
95 struct packet
*packet
,
96 struct option_cache
*oc
,
98 static void build_dhcpv6_reply(struct data_string
*, struct packet
*);
99 static isc_result_t
shared_network_from_packet6(struct shared_network
**shared
,
100 struct packet
*packet
);
101 static void seek_shared_host(struct host_decl
**hp
,
102 struct shared_network
*shared
);
103 static isc_boolean_t
fixed_matches_shared(struct host_decl
*host
,
104 struct shared_network
*shared
);
105 static isc_result_t
reply_process_ia_na(struct reply_state
*reply
,
106 struct option_cache
*ia
);
107 static isc_result_t
reply_process_ia_ta(struct reply_state
*reply
,
108 struct option_cache
*ia
);
109 static isc_result_t
reply_process_addr(struct reply_state
*reply
,
110 struct option_cache
*addr
);
111 static isc_boolean_t
address_is_owned(struct reply_state
*reply
,
113 static isc_boolean_t
temporary_is_available(struct reply_state
*reply
,
115 static isc_result_t
find_client_temporaries(struct reply_state
*reply
);
116 static isc_result_t
reply_process_try_addr(struct reply_state
*reply
,
118 static isc_result_t
find_client_address(struct reply_state
*reply
);
119 static isc_result_t
reply_process_is_addressed(struct reply_state
*reply
,
120 struct binding_scope
**scope
,
121 struct group
*group
);
122 static isc_result_t
reply_process_send_addr(struct reply_state
*reply
,
124 static struct iasubopt
*lease_compare(struct iasubopt
*alpha
,
125 struct iasubopt
*beta
);
126 static isc_result_t
reply_process_ia_pd(struct reply_state
*reply
,
127 struct option_cache
*ia_pd
);
128 static isc_result_t
reply_process_prefix(struct reply_state
*reply
,
129 struct option_cache
*pref
);
130 static isc_boolean_t
prefix_is_owned(struct reply_state
*reply
,
131 struct iaddrcidrnet
*pref
);
132 static isc_result_t
find_client_prefix(struct reply_state
*reply
);
133 static isc_result_t
reply_process_try_prefix(struct reply_state
*reply
,
134 struct iaddrcidrnet
*pref
);
135 static isc_result_t
reply_process_is_prefixed(struct reply_state
*reply
,
136 struct binding_scope
**scope
,
137 struct group
*group
);
138 static isc_result_t
reply_process_send_prefix(struct reply_state
*reply
,
139 struct iaddrcidrnet
*pref
);
140 static struct iasubopt
*prefix_compare(struct reply_state
*reply
,
141 struct iasubopt
*alpha
,
142 struct iasubopt
*beta
);
143 static int find_hosts_by_duid_chaddr(struct host_decl
**host
,
144 const struct data_string
*client_id
);
146 * This function returns the time since DUID time start for the
147 * given time_t value.
150 duid_time(time_t when
) {
152 * This time is modulo 2^32.
154 while ((when
- DUID_TIME_EPOCH
) > 4294967295u) {
155 /* use 2^31 to avoid spurious compiler warnings */
160 return when
- DUID_TIME_EPOCH
;
167 * This must remain the same for the lifetime of this server, because
168 * clients return the server DUID that we sent them in Request packets.
170 * We pick the server DUID like this:
172 * 1. Check dhcpd.conf - any value the administrator has configured
173 * overrides any possible values.
174 * 2. Check the leases.txt - we want to use the previous value if
176 * 3. Check if dhcpd.conf specifies a type of server DUID to use,
177 * and generate that type.
178 * 4. Generate a type 1 (time + hardware address) DUID.
180 static struct data_string server_duid
;
183 * Check if the server_duid has been set.
186 server_duid_isset(void) {
187 return (server_duid
.data
!= NULL
);
191 * Return the server_duid.
194 copy_server_duid(struct data_string
*ds
, const char *file
, int line
) {
195 data_string_copy(ds
, &server_duid
, file
, line
);
199 * Set the server DUID to a specified value. This is used when
200 * the server DUID is stored in persistent memory (basically the
204 set_server_duid(struct data_string
*new_duid
) {
205 /* INSIST(new_duid != NULL); */
206 /* INSIST(new_duid->data != NULL); */
208 if (server_duid_isset()) {
209 data_string_forget(&server_duid
, MDL
);
211 data_string_copy(&server_duid
, new_duid
, MDL
);
216 * Set the server DUID based on the D6O_SERVERID option. This handles
217 * the case where the administrator explicitly put it in the dhcpd.conf
221 set_server_duid_from_option(void) {
222 struct option_state
*opt_state
;
223 struct option_cache
*oc
;
224 struct data_string option_duid
;
225 isc_result_t ret_val
;
228 if (!option_state_allocate(&opt_state
, MDL
)) {
229 log_fatal("No memory for server DUID.");
232 execute_statements_in_scope(NULL
, NULL
, NULL
, NULL
, NULL
,
233 opt_state
, &global_scope
, root_group
, NULL
);
235 oc
= lookup_option(&dhcpv6_universe
, opt_state
, D6O_SERVERID
);
237 ret_val
= ISC_R_NOTFOUND
;
239 memset(&option_duid
, 0, sizeof(option_duid
));
240 if (!evaluate_option_cache(&option_duid
, NULL
, NULL
, NULL
,
241 opt_state
, NULL
, &global_scope
,
243 ret_val
= ISC_R_UNEXPECTED
;
245 set_server_duid(&option_duid
);
246 data_string_forget(&option_duid
, MDL
);
247 ret_val
= ISC_R_SUCCESS
;
251 option_state_dereference(&opt_state
, MDL
);
257 * DUID layout, as defined in RFC 3315, section 9.
259 * We support type 1 (hardware address plus time) and type 3 (hardware
262 * We can support type 2 for specific vendors in the future, if they
263 * publish the specification. And of course there may be additional
266 static int server_duid_type
= DUID_LLT
;
272 set_server_duid_type(int type
) {
273 server_duid_type
= type
;
277 * Generate a new server DUID. This is done if there was no DUID in
278 * the leases.txt or in the dhcpd.conf file.
281 generate_new_server_duid(void) {
282 struct interface_info
*p
;
284 struct data_string generated_duid
;
287 * Verify we have a type that we support.
289 if ((server_duid_type
!= DUID_LL
) && (server_duid_type
!= DUID_LLT
)) {
290 log_error("Invalid DUID type %d specified, "
291 "only LL and LLT types supported", server_duid_type
);
292 return DHCP_R_INVALIDARG
;
296 * Find an interface with a hardware address.
299 for (p
= interfaces
; p
!= NULL
; p
= p
->next
) {
300 if (p
->hw_address
.hlen
> 0) {
305 return ISC_R_UNEXPECTED
;
311 memset(&generated_duid
, 0, sizeof(generated_duid
));
312 if (server_duid_type
== DUID_LLT
) {
313 time_val
= duid_time(time(NULL
));
314 generated_duid
.len
= 8 + p
->hw_address
.hlen
- 1;
315 if (!buffer_allocate(&generated_duid
.buffer
,
316 generated_duid
.len
, MDL
)) {
317 log_fatal("No memory for server DUID.");
319 generated_duid
.data
= generated_duid
.buffer
->data
;
320 putUShort(generated_duid
.buffer
->data
, DUID_LLT
);
321 putUShort(generated_duid
.buffer
->data
+ 2,
322 p
->hw_address
.hbuf
[0]);
323 putULong(generated_duid
.buffer
->data
+ 4, time_val
);
324 memcpy(generated_duid
.buffer
->data
+ 8,
325 p
->hw_address
.hbuf
+1, p
->hw_address
.hlen
-1);
326 } else if (server_duid_type
== DUID_LL
) {
327 generated_duid
.len
= 4 + p
->hw_address
.hlen
- 1;
328 if (!buffer_allocate(&generated_duid
.buffer
,
329 generated_duid
.len
, MDL
)) {
330 log_fatal("No memory for server DUID.");
332 generated_duid
.data
= generated_duid
.buffer
->data
;
333 putUShort(generated_duid
.buffer
->data
, DUID_LL
);
334 putUShort(generated_duid
.buffer
->data
+ 2,
335 p
->hw_address
.hbuf
[0]);
336 memcpy(generated_duid
.buffer
->data
+ 4,
337 p
->hw_address
.hbuf
+1, p
->hw_address
.hlen
-1);
339 log_fatal("Unsupported server DUID type %d.", server_duid_type
);
342 set_server_duid(&generated_duid
);
343 data_string_forget(&generated_duid
, MDL
);
345 return ISC_R_SUCCESS
;
349 * Get the client identifier from the packet.
352 get_client_id(struct packet
*packet
, struct data_string
*client_id
) {
353 struct option_cache
*oc
;
356 * Verify our client_id structure is empty.
358 if ((client_id
->data
!= NULL
) || (client_id
->len
!= 0)) {
359 return DHCP_R_INVALIDARG
;
362 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_CLIENTID
);
364 return ISC_R_NOTFOUND
;
367 if (!evaluate_option_cache(client_id
, packet
, NULL
, NULL
,
368 packet
->options
, NULL
,
369 &global_scope
, oc
, MDL
)) {
370 return ISC_R_FAILURE
;
373 return ISC_R_SUCCESS
;
377 * Message validation, defined in RFC 3315, sections 15.2, 15.5, 15.7:
379 * Servers MUST discard any Solicit messages that do not include a
380 * Client Identifier option or that do include a Server Identifier
384 valid_client_msg(struct packet
*packet
, struct data_string
*client_id
) {
386 struct option_cache
*oc
;
387 struct data_string data
;
390 memset(client_id
, 0, sizeof(*client_id
));
391 memset(&data
, 0, sizeof(data
));
393 switch (get_client_id(packet
, client_id
)) {
397 log_debug("Discarding %s from %s; "
398 "client identifier missing",
399 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
400 piaddr(packet
->client_addr
));
403 log_error("Error processing %s from %s; "
404 "unable to evaluate Client Identifier",
405 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
406 piaddr(packet
->client_addr
));
411 * Required by RFC 3315, section 15.
413 if (packet
->unicast
) {
414 log_debug("Discarding %s from %s; packet sent unicast "
416 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
417 piaddr(packet
->client_addr
),
418 print_hex_1(client_id
->len
, client_id
->data
, 60));
423 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
425 if (evaluate_option_cache(&data
, packet
, NULL
, NULL
,
426 packet
->options
, NULL
,
427 &global_scope
, oc
, MDL
)) {
428 log_debug("Discarding %s from %s; "
429 "server identifier found "
430 "(CLIENTID %s, SERVERID %s)",
431 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
432 piaddr(packet
->client_addr
),
433 print_hex_1(client_id
->len
,
434 client_id
->data
, 60),
435 print_hex_2(data
.len
,
438 log_debug("Discarding %s from %s; "
439 "server identifier found "
441 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
442 print_hex_1(client_id
->len
,
443 client_id
->data
, 60),
444 piaddr(packet
->client_addr
));
454 data_string_forget(&data
, MDL
);
457 if (client_id
->len
> 0) {
458 data_string_forget(client_id
, MDL
);
465 * Response validation, defined in RFC 3315, sections 15.4, 15.6, 15.8,
466 * 15.9 (slightly different wording, but same meaning):
468 * Servers MUST discard any received Request message that meet any of
469 * the following conditions:
471 * - the message does not include a Server Identifier option.
472 * - the contents of the Server Identifier option do not match the
474 * - the message does not include a Client Identifier option.
477 valid_client_resp(struct packet
*packet
,
478 struct data_string
*client_id
,
479 struct data_string
*server_id
)
482 struct option_cache
*oc
;
484 /* INSIST((duid.data != NULL) && (duid.len > 0)); */
487 memset(client_id
, 0, sizeof(*client_id
));
488 memset(server_id
, 0, sizeof(*server_id
));
490 switch (get_client_id(packet
, client_id
)) {
494 log_debug("Discarding %s from %s; "
495 "client identifier missing",
496 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
497 piaddr(packet
->client_addr
));
500 log_error("Error processing %s from %s; "
501 "unable to evaluate Client Identifier",
502 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
503 piaddr(packet
->client_addr
));
507 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
509 log_debug("Discarding %s from %s: "
510 "server identifier missing (CLIENTID %s)",
511 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
512 piaddr(packet
->client_addr
),
513 print_hex_1(client_id
->len
, client_id
->data
, 60));
516 if (!evaluate_option_cache(server_id
, packet
, NULL
, NULL
,
517 packet
->options
, NULL
,
518 &global_scope
, oc
, MDL
)) {
519 log_error("Error processing %s from %s; "
520 "unable to evaluate Server Identifier (CLIENTID %s)",
521 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
522 piaddr(packet
->client_addr
),
523 print_hex_1(client_id
->len
, client_id
->data
, 60));
526 if ((server_duid
.len
!= server_id
->len
) ||
527 (memcmp(server_duid
.data
, server_id
->data
, server_duid
.len
) != 0)) {
528 log_debug("Discarding %s from %s; "
529 "not our server identifier "
530 "(CLIENTID %s, SERVERID %s, server DUID %s)",
531 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
532 piaddr(packet
->client_addr
),
533 print_hex_1(client_id
->len
, client_id
->data
, 60),
534 print_hex_2(server_id
->len
, server_id
->data
, 60),
535 print_hex_3(server_duid
.len
, server_duid
.data
, 60));
544 if (server_id
->len
> 0) {
545 data_string_forget(server_id
, MDL
);
547 if (client_id
->len
> 0) {
548 data_string_forget(client_id
, MDL
);
555 * Information request validation, defined in RFC 3315, section 15.12:
557 * Servers MUST discard any received Information-request message that
558 * meets any of the following conditions:
560 * - The message includes a Server Identifier option and the DUID in
561 * the option does not match the server's DUID.
563 * - The message includes an IA option.
566 valid_client_info_req(struct packet
*packet
, struct data_string
*server_id
) {
568 struct option_cache
*oc
;
569 struct data_string client_id
;
570 char client_id_str
[80]; /* print_hex_1() uses maximum 60 characters,
571 plus a few more for extra information */
574 memset(server_id
, 0, sizeof(*server_id
));
577 * Make a string that we can print out to give more
578 * information about the client if we need to.
580 * By RFC 3315, Section 18.1.5 clients SHOULD have a
581 * client-id on an Information-request packet, but it
582 * is not strictly necessary.
584 if (get_client_id(packet
, &client_id
) == ISC_R_SUCCESS
) {
585 snprintf(client_id_str
, sizeof(client_id_str
), " (CLIENTID %s)",
586 print_hex_1(client_id
.len
, client_id
.data
, 60));
587 data_string_forget(&client_id
, MDL
);
589 client_id_str
[0] = '\0';
593 * Required by RFC 3315, section 15.
595 if (packet
->unicast
) {
596 log_debug("Discarding %s from %s; packet sent unicast%s",
597 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
598 piaddr(packet
->client_addr
), client_id_str
);
602 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
604 log_debug("Discarding %s from %s; "
605 "IA_NA option present%s",
606 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
607 piaddr(packet
->client_addr
), client_id_str
);
610 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_TA
);
612 log_debug("Discarding %s from %s; "
613 "IA_TA option present%s",
614 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
615 piaddr(packet
->client_addr
), client_id_str
);
618 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_PD
);
620 log_debug("Discarding %s from %s; "
621 "IA_PD option present%s",
622 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
623 piaddr(packet
->client_addr
), client_id_str
);
627 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
629 if (!evaluate_option_cache(server_id
, packet
, NULL
, NULL
,
630 packet
->options
, NULL
,
631 &global_scope
, oc
, MDL
)) {
632 log_error("Error processing %s from %s; "
633 "unable to evaluate Server Identifier%s",
634 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
635 piaddr(packet
->client_addr
), client_id_str
);
638 if ((server_duid
.len
!= server_id
->len
) ||
639 (memcmp(server_duid
.data
, server_id
->data
,
640 server_duid
.len
) != 0)) {
641 log_debug("Discarding %s from %s; "
642 "not our server identifier "
643 "(SERVERID %s, server DUID %s)%s",
644 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
645 piaddr(packet
->client_addr
),
646 print_hex_1(server_id
->len
,
647 server_id
->data
, 60),
648 print_hex_2(server_duid
.len
,
649 server_duid
.data
, 60),
660 if (server_id
->len
> 0) {
661 data_string_forget(server_id
, MDL
);
668 * Options that we want to send, in addition to what was requested
671 static const int required_opts
[] = {
678 static const int required_opts_NAA
[] = {
684 static const int required_opts_solicit
[] = {
696 static const int required_opts_agent
[] = {
701 static const int required_opts_IA
[] = {
706 static const int required_opts_IA_PD
[] = {
711 static const int required_opts_STATUS_CODE
[] = {
717 * Extracts from packet contents an IA_* option, storing the IA structure
718 * in its entirety in enc_opt_data, and storing any decoded DHCPv6 options
719 * in enc_opt_state for later lookup and evaluation. The 'offset' indicates
720 * where in the IA_* the DHCPv6 options commence.
723 get_encapsulated_IA_state(struct option_state
**enc_opt_state
,
724 struct data_string
*enc_opt_data
,
725 struct packet
*packet
,
726 struct option_cache
*oc
,
730 * Get the raw data for the encapsulated options.
732 memset(enc_opt_data
, 0, sizeof(*enc_opt_data
));
733 if (!evaluate_option_cache(enc_opt_data
, packet
,
734 NULL
, NULL
, packet
->options
, NULL
,
735 &global_scope
, oc
, MDL
)) {
736 log_error("get_encapsulated_IA_state: "
737 "error evaluating raw option.");
740 if (enc_opt_data
->len
< offset
) {
741 log_error("get_encapsulated_IA_state: raw option too small.");
742 data_string_forget(enc_opt_data
, MDL
);
747 * Now create the option state structure, and pass it to the
748 * function that parses options.
750 *enc_opt_state
= NULL
;
751 if (!option_state_allocate(enc_opt_state
, MDL
)) {
752 log_error("get_encapsulated_IA_state: no memory for options.");
753 data_string_forget(enc_opt_data
, MDL
);
756 if (!parse_option_buffer(*enc_opt_state
,
757 enc_opt_data
->data
+ offset
,
758 enc_opt_data
->len
- offset
,
760 log_error("get_encapsulated_IA_state: error parsing options.");
761 option_state_dereference(enc_opt_state
, MDL
);
762 data_string_forget(enc_opt_data
, MDL
);
770 set_status_code(u_int16_t status_code
, const char *status_message
,
771 struct option_state
*opt_state
)
773 struct data_string d
;
776 memset(&d
, 0, sizeof(d
));
777 d
.len
= sizeof(status_code
) + strlen(status_message
);
778 if (!buffer_allocate(&d
.buffer
, d
.len
, MDL
)) {
779 log_fatal("set_status_code: no memory for status code.");
781 d
.data
= d
.buffer
->data
;
782 putUShort(d
.buffer
->data
, status_code
);
783 memcpy(d
.buffer
->data
+ sizeof(status_code
),
784 status_message
, d
.len
- sizeof(status_code
));
785 if (!save_option_buffer(&dhcpv6_universe
, opt_state
,
786 d
.buffer
, (unsigned char *)d
.data
, d
.len
,
787 D6O_STATUS_CODE
, 0)) {
788 log_error("set_status_code: error saving status code.");
793 data_string_forget(&d
, MDL
);
798 * We have a set of operations we do to set up the reply packet, which
799 * is the same for many message types.
802 start_reply(struct packet
*packet
,
803 const struct data_string
*client_id
,
804 const struct data_string
*server_id
,
805 struct option_state
**opt_state
,
806 struct dhcpv6_packet
*reply
)
808 struct option_cache
*oc
;
809 const unsigned char *server_id_data
;
813 * Build our option state for reply.
816 if (!option_state_allocate(opt_state
, MDL
)) {
817 log_error("start_reply: no memory for option_state.");
820 execute_statements_in_scope(NULL
, packet
, NULL
, NULL
,
821 packet
->options
, *opt_state
,
822 &global_scope
, root_group
, NULL
);
825 * A small bit of special handling for Solicit messages.
827 * We could move the logic into a flag, but for now just check
830 if (packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
) {
831 reply
->msg_type
= DHCPV6_ADVERTISE
;
835 * - this message type supports rapid commit (Solicit), and
836 * - the server is configured to supply a rapid commit, and
837 * - the client requests a rapid commit,
838 * Then we add a rapid commit option, and send Reply (instead
841 oc
= lookup_option(&dhcpv6_universe
,
842 *opt_state
, D6O_RAPID_COMMIT
);
844 oc
= lookup_option(&dhcpv6_universe
,
845 packet
->options
, D6O_RAPID_COMMIT
);
847 /* Rapid-commit in action. */
848 reply
->msg_type
= DHCPV6_REPLY
;
850 /* Don't want a rapid-commit in advertise. */
851 delete_option(&dhcpv6_universe
,
852 *opt_state
, D6O_RAPID_COMMIT
);
856 reply
->msg_type
= DHCPV6_REPLY
;
857 /* Delete the rapid-commit from the sent options. */
858 oc
= lookup_option(&dhcpv6_universe
,
859 *opt_state
, D6O_RAPID_COMMIT
);
861 delete_option(&dhcpv6_universe
,
862 *opt_state
, D6O_RAPID_COMMIT
);
867 * Use the client's transaction identifier for the reply.
869 memcpy(reply
->transaction_id
, packet
->dhcpv6_transaction_id
,
870 sizeof(reply
->transaction_id
));
873 * RFC 3315, section 18.2 says we need server identifier and
876 * If the server ID is defined via the configuration file, then
877 * it will already be present in the option state at this point,
878 * so we don't need to set it.
880 * If we have a server ID passed in from the caller,
881 * use that, otherwise use the global DUID.
883 oc
= lookup_option(&dhcpv6_universe
, *opt_state
, D6O_SERVERID
);
885 if (server_id
== NULL
) {
886 server_id_data
= server_duid
.data
;
887 server_id_len
= server_duid
.len
;
889 server_id_data
= server_id
->data
;
890 server_id_len
= server_id
->len
;
892 if (!save_option_buffer(&dhcpv6_universe
, *opt_state
,
893 NULL
, (unsigned char *)server_id_data
,
894 server_id_len
, D6O_SERVERID
, 0)) {
895 log_error("start_reply: "
896 "error saving server identifier.");
901 if (client_id
->buffer
!= NULL
) {
902 if (!save_option_buffer(&dhcpv6_universe
, *opt_state
,
904 (unsigned char *)client_id
->data
,
907 log_error("start_reply: error saving "
908 "client identifier.");
914 * If the client accepts reconfiguration, let it know that we
917 * Note: we don't actually do this yet, but DOCSIS requires we
920 oc
= lookup_option(&dhcpv6_universe
, packet
->options
,
923 if (!save_option_buffer(&dhcpv6_universe
, *opt_state
,
924 NULL
, (unsigned char *)"", 0,
925 D6O_RECONF_ACCEPT
, 0)) {
926 log_error("start_reply: "
927 "error saving RECONF_ACCEPT option.");
928 option_state_dereference(opt_state
, MDL
);
937 * Try to get the IPv6 address the client asked for from the
940 * addr is the result (should be a pointer to NULL on entry)
941 * pool is the pool to search in
942 * requested_addr is the address the client wants
945 try_client_v6_address(struct iasubopt
**addr
,
946 struct ipv6_pool
*pool
,
947 const struct data_string
*requested_addr
)
949 struct in6_addr tmp_addr
;
952 if (requested_addr
->len
< sizeof(tmp_addr
)) {
953 return DHCP_R_INVALIDARG
;
955 memcpy(&tmp_addr
, requested_addr
->data
, sizeof(tmp_addr
));
956 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr
)) {
957 return ISC_R_FAILURE
;
961 * The address is not covered by this (or possibly any) dynamic
964 if (!ipv6_in_pool(&tmp_addr
, pool
)) {
965 return ISC_R_ADDRNOTAVAIL
;
968 if (lease6_exists(pool
, &tmp_addr
)) {
969 return ISC_R_ADDRINUSE
;
972 result
= iasubopt_allocate(addr
, MDL
);
973 if (result
!= ISC_R_SUCCESS
) {
976 (*addr
)->addr
= tmp_addr
;
979 /* Default is soft binding for 2 minutes. */
980 result
= add_lease6(pool
, *addr
, cur_time
+ 120);
981 if (result
!= ISC_R_SUCCESS
) {
982 iasubopt_dereference(addr
, MDL
);
988 * Get an IPv6 address for the client.
990 * addr is the result (should be a pointer to NULL on entry)
991 * packet is the information about the packet from the client
992 * requested_iaaddr is a hint from the client
993 * client_id is the DUID for the client
996 pick_v6_address(struct iasubopt
**addr
, struct shared_network
*shared_network
,
997 const struct data_string
*client_id
)
1002 unsigned int attempts
;
1003 char tmp_buf
[INET6_ADDRSTRLEN
];
1006 * No address pools, we're done.
1008 if (shared_network
->ipv6_pools
== NULL
) {
1009 log_debug("Unable to pick client address: "
1010 "no IPv6 pools on this shared network");
1011 return ISC_R_NORESOURCES
;
1014 p
= shared_network
->ipv6_pools
[i
];
1016 log_debug("Unable to pick client address: "
1017 "no IPv6 address pools "
1018 "on this shared network");
1019 return ISC_R_NORESOURCES
;
1021 if (p
->pool_type
== D6O_IA_NA
) {
1027 * Otherwise try to get a lease from the first subnet possible.
1029 * We start looking at the last pool we allocated from, unless
1030 * it had a collision trying to allocate an address. This will
1031 * tend to move us into less-filled pools.
1033 start_pool
= shared_network
->last_ipv6_pool
;
1037 p
= shared_network
->ipv6_pools
[i
];
1038 if ((p
->pool_type
== D6O_IA_NA
) &&
1039 (create_lease6(p
, addr
, &attempts
, client_id
,
1040 cur_time
+ 120) == ISC_R_SUCCESS
)) {
1042 * Record the pool used (or next one if there
1047 if (shared_network
->ipv6_pools
[i
] == NULL
) {
1051 shared_network
->last_ipv6_pool
= i
;
1053 log_debug("Picking pool address %s",
1054 inet_ntop(AF_INET6
, &((*addr
)->addr
),
1055 tmp_buf
, sizeof(tmp_buf
)));
1056 return ISC_R_SUCCESS
;
1060 if (shared_network
->ipv6_pools
[i
] == NULL
) {
1063 } while (i
!= start_pool
);
1066 * If we failed to pick an IPv6 address from any of the subnets.
1067 * Presumably that means we have no addresses for the client.
1069 log_debug("Unable to pick client address: no addresses available");
1070 return ISC_R_NORESOURCES
;
1074 * Try to get the IPv6 prefix the client asked for from the
1077 * pref is the result (should be a pointer to NULL on entry)
1078 * pool is the prefix pool to search in
1079 * requested_pref is the address the client wants
1082 try_client_v6_prefix(struct iasubopt
**pref
,
1083 struct ipv6_pool
*pool
,
1084 const struct data_string
*requested_pref
)
1087 struct in6_addr tmp_pref
;
1089 isc_result_t result
;
1091 if (requested_pref
->len
< sizeof(tmp_plen
) + sizeof(tmp_pref
)) {
1092 return DHCP_R_INVALIDARG
;
1094 tmp_plen
= (int) requested_pref
->data
[0];
1095 if ((tmp_plen
< 3) || (tmp_plen
> 128) ||
1096 ((int)tmp_plen
!= pool
->units
)) {
1097 return ISC_R_FAILURE
;
1099 memcpy(&tmp_pref
, requested_pref
->data
+ 1, sizeof(tmp_pref
));
1100 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref
)) {
1101 return ISC_R_FAILURE
;
1104 memcpy(&ia
.iabuf
, &tmp_pref
, 16);
1105 if (!is_cidr_mask_valid(&ia
, (int) tmp_plen
)) {
1106 return ISC_R_FAILURE
;
1109 if (!ipv6_in_pool(&tmp_pref
, pool
)) {
1110 return ISC_R_ADDRNOTAVAIL
;
1113 if (prefix6_exists(pool
, &tmp_pref
, tmp_plen
)) {
1114 return ISC_R_ADDRINUSE
;
1117 result
= iasubopt_allocate(pref
, MDL
);
1118 if (result
!= ISC_R_SUCCESS
) {
1121 (*pref
)->addr
= tmp_pref
;
1122 (*pref
)->plen
= tmp_plen
;
1124 /* Default is soft binding for 2 minutes. */
1125 result
= add_lease6(pool
, *pref
, cur_time
+ 120);
1126 if (result
!= ISC_R_SUCCESS
) {
1127 iasubopt_dereference(pref
, MDL
);
1133 * Get an IPv6 prefix for the client.
1135 * pref is the result (should be a pointer to NULL on entry)
1136 * packet is the information about the packet from the client
1137 * requested_iaprefix is a hint from the client
1138 * plen is -1 or the requested prefix length
1139 * client_id is the DUID for the client
1142 pick_v6_prefix(struct iasubopt
**pref
, int plen
,
1143 struct shared_network
*shared_network
,
1144 const struct data_string
*client_id
)
1146 struct ipv6_pool
*p
;
1148 unsigned int attempts
;
1149 char tmp_buf
[INET6_ADDRSTRLEN
];
1152 * No prefix pools, we're done.
1154 if (shared_network
->ipv6_pools
== NULL
) {
1155 log_debug("Unable to pick client prefix: "
1156 "no IPv6 pools on this shared network");
1157 return ISC_R_NORESOURCES
;
1160 p
= shared_network
->ipv6_pools
[i
];
1162 log_debug("Unable to pick client prefix: "
1163 "no IPv6 prefix pools "
1164 "on this shared network");
1165 return ISC_R_NORESOURCES
;
1167 if (p
->pool_type
== D6O_IA_PD
) {
1173 * Otherwise try to get a prefix.
1176 p
= shared_network
->ipv6_pools
[i
];
1180 if (p
->pool_type
!= D6O_IA_PD
) {
1185 * Try only pools with the requested prefix length if any.
1187 if ((plen
>= 0) && (p
->units
!= plen
)) {
1191 if (create_prefix6(p
, pref
, &attempts
, client_id
,
1192 cur_time
+ 120) == ISC_R_SUCCESS
) {
1193 log_debug("Picking pool prefix %s/%u",
1194 inet_ntop(AF_INET6
, &((*pref
)->addr
),
1195 tmp_buf
, sizeof(tmp_buf
)),
1196 (unsigned) (*pref
)->plen
);
1197 return ISC_R_SUCCESS
;
1202 * If we failed to pick an IPv6 prefix
1203 * Presumably that means we have no prefixes for the client.
1205 log_debug("Unable to pick client prefix: no prefixes available");
1206 return ISC_R_NORESOURCES
;
1210 *! \file server/dhcpv6.c
1212 * \brief construct a reply containing information about a client's lease
1214 * lease_to_client() is called from several messages to construct a
1215 * reply that contains all that we know about the client's correct lease
1216 * (or projected lease).
1218 * Solicit - "Soft" binding, ignore unknown addresses or bindings, just
1219 * send what we "may" give them on a request.
1221 * Request - "Hard" binding, but ignore supplied addresses (just provide what
1222 * the client should really use).
1224 * Renew - "Hard" binding, but client-supplied addresses are 'real'. Error
1225 * Rebind out any "wrong" addresses the client sends. This means we send
1226 * an empty IA_NA with a status code of NoBinding or NotOnLink or
1227 * possibly send the address with zeroed lifetimes.
1229 * Information-Request - No binding.
1231 * The basic structure is to traverse the client-supplied data first, and
1232 * validate and echo back any contents that can be. If the client-supplied
1233 * data does not error out (on renew/rebind as above), but we did not send
1234 * any addresses, attempt to allocate one.
1236 * At the end of the this function we call commit_leases_timed() to
1237 * fsync and rotate the file as necessary. commit_leases_timed() will
1238 * check that we have written at least one lease to the file and that
1239 * some time has passed before doing any fsync or file rewrite so we
1240 * don't bother tracking if we did a write_ia during this function.
1242 /* TODO: look at client hints for lease times */
1245 lease_to_client(struct data_string
*reply_ret
,
1246 struct packet
*packet
,
1247 const struct data_string
*client_id
,
1248 const struct data_string
*server_id
)
1250 static struct reply_state reply
;
1251 struct option_cache
*oc
;
1252 struct data_string packet_oro
;
1253 #if defined (RFC3315_PRE_ERRATA_2010_08)
1254 isc_boolean_t no_resources_avail
= ISC_FALSE
;
1257 memset(&packet_oro
, 0, sizeof(packet_oro
));
1259 /* Locate the client. */
1260 if (shared_network_from_packet6(&reply
.shared
,
1261 packet
) != ISC_R_SUCCESS
)
1265 * Initialize the reply.
1267 packet_reference(&reply
.packet
, packet
, MDL
);
1268 data_string_copy(&reply
.client_id
, client_id
, MDL
);
1270 if (!start_reply(packet
, client_id
, server_id
, &reply
.opt_state
,
1274 /* Set the write cursor to just past the reply header. */
1275 reply
.cursor
= REPLY_OPTIONS_INDEX
;
1278 * Get the ORO from the packet, if any.
1280 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_ORO
);
1282 if (!evaluate_option_cache(&packet_oro
, packet
,
1284 packet
->options
, NULL
,
1285 &global_scope
, oc
, MDL
)) {
1286 log_error("lease_to_client: error evaluating ORO.");
1292 * Find a host record that matches from the packet, if any, and is
1293 * valid for the shared network the client is on.
1295 if (find_hosts_by_uid(&reply
.host
, client_id
->data
, client_id
->len
,
1297 seek_shared_host(&reply
.host
, reply
.shared
);
1299 if ((reply
.host
== NULL
) &&
1300 find_hosts_by_option(&reply
.host
, packet
, packet
->options
, MDL
))
1301 seek_shared_host(&reply
.host
, reply
.shared
);
1304 * Check for 'hardware' matches last, as some of the synthesis methods
1305 * are not considered to be as reliable.
1307 if ((reply
.host
== NULL
) &&
1308 find_hosts_by_duid_chaddr(&reply
.host
, client_id
))
1309 seek_shared_host(&reply
.host
, reply
.shared
);
1311 /* Process the client supplied IA's onto the reply buffer. */
1313 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
1315 for (; oc
!= NULL
; oc
= oc
->next
) {
1316 isc_result_t status
;
1318 /* Start counting resources (addresses) offered. */
1319 reply
.client_resources
= 0;
1320 reply
.resources_included
= ISC_FALSE
;
1322 status
= reply_process_ia_na(&reply
, oc
);
1325 * We continue to try other IA's whether we can address
1326 * this one or not. Any other result is an immediate fail.
1328 if ((status
!= ISC_R_SUCCESS
) &&
1329 (status
!= ISC_R_NORESOURCES
))
1332 #if defined (RFC3315_PRE_ERRATA_2010_08)
1334 * If any address cannot be given to any IA, then set the
1335 * NoAddrsAvail status code.
1337 if (reply
.client_resources
== 0)
1338 no_resources_avail
= ISC_TRUE
;
1341 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_TA
);
1342 for (; oc
!= NULL
; oc
= oc
->next
) {
1343 isc_result_t status
;
1345 /* Start counting resources (addresses) offered. */
1346 reply
.client_resources
= 0;
1347 reply
.resources_included
= ISC_FALSE
;
1349 status
= reply_process_ia_ta(&reply
, oc
);
1352 * We continue to try other IA's whether we can address
1353 * this one or not. Any other result is an immediate fail.
1355 if ((status
!= ISC_R_SUCCESS
) &&
1356 (status
!= ISC_R_NORESOURCES
))
1359 #if defined (RFC3315_PRE_ERRATA_2010_08)
1361 * If any address cannot be given to any IA, then set the
1362 * NoAddrsAvail status code.
1364 if (reply
.client_resources
== 0)
1365 no_resources_avail
= ISC_TRUE
;
1369 /* Same for IA_PD's. */
1371 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_PD
);
1372 for (; oc
!= NULL
; oc
= oc
->next
) {
1373 isc_result_t status
;
1375 /* Start counting resources (prefixes) offered. */
1376 reply
.client_resources
= 0;
1377 reply
.resources_included
= ISC_FALSE
;
1379 status
= reply_process_ia_pd(&reply
, oc
);
1382 * We continue to try other IA_PD's whether we can address
1383 * this one or not. Any other result is an immediate fail.
1385 if ((status
!= ISC_R_SUCCESS
) &&
1386 (status
!= ISC_R_NORESOURCES
))
1391 * Make no reply if we gave no resources and is not
1392 * for Information-Request.
1394 if ((reply
.ia_count
== 0) && (reply
.pd_count
== 0)) {
1395 if (reply
.packet
->dhcpv6_msg_type
!=
1396 DHCPV6_INFORMATION_REQUEST
)
1400 * Because we only execute statements on a per-IA basis,
1401 * we need to execute statements in any non-IA reply to
1402 * source configuration.
1404 execute_statements_in_scope(NULL
, reply
.packet
, NULL
, NULL
,
1405 reply
.packet
->options
,
1406 reply
.opt_state
, &global_scope
,
1407 reply
.shared
->group
, root_group
);
1409 /* Bring in any configuration from a host record. */
1410 if (reply
.host
!= NULL
)
1411 execute_statements_in_scope(NULL
, reply
.packet
, NULL
,
1412 NULL
, reply
.packet
->options
,
1416 reply
.shared
->group
);
1420 * RFC3315 section 17.2.2 (Solicit):
1422 * If the server will not assign any addresses to any IAs in a
1423 * subsequent Request from the client, the server MUST send an
1424 * Advertise message to the client that includes only a Status
1425 * Code option with code NoAddrsAvail and a status message for
1426 * the user, a Server Identifier option with the server's DUID,
1427 * and a Client Identifier option with the client's DUID.
1429 * Section 18.2.1 (Request):
1431 * If the server cannot assign any addresses to an IA in the
1432 * message from the client, the server MUST include the IA in
1433 * the Reply message with no addresses in the IA and a Status
1434 * Code option in the IA containing status code NoAddrsAvail.
1436 * Section 18.1.8 (Client Behavior):
1438 * Leave unchanged any information about addresses the client has
1439 * recorded in the IA but that were not included in the IA from
1441 * Sends a Renew/Rebind if the IA is not in the Reply message.
1443 #if defined (RFC3315_PRE_ERRATA_2010_08)
1444 if (no_resources_avail
&& (reply
.ia_count
!= 0) &&
1445 (reply
.packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
))
1447 /* Set the NoAddrsAvail status code. */
1448 if (!set_status_code(STATUS_NoAddrsAvail
,
1449 "No addresses available for this "
1450 "interface.", reply
.opt_state
)) {
1451 log_error("lease_to_client: Unable to set "
1452 "NoAddrsAvail status code.");
1456 /* Rewind the cursor to the start. */
1457 reply
.cursor
= REPLY_OPTIONS_INDEX
;
1460 * Produce an advertise that includes only:
1466 reply
.buf
.reply
.msg_type
= DHCPV6_ADVERTISE
;
1467 reply
.cursor
+= store_options6((char *)reply
.buf
.data
+
1471 reply
.opt_state
, reply
.packet
,
1476 * Having stored the client's IA's, store any options that
1477 * will fit in the remaining space.
1479 reply
.cursor
+= store_options6((char *)reply
.buf
.data
+
1483 reply
.opt_state
, reply
.packet
,
1484 required_opts_solicit
,
1487 #else /* defined (RFC3315_PRE_ERRATA_2010_08) */
1489 * Having stored the client's IA's, store any options that
1490 * will fit in the remaining space.
1492 reply
.cursor
+= store_options6((char *)reply
.buf
.data
+ reply
.cursor
,
1493 sizeof(reply
.buf
) - reply
.cursor
,
1494 reply
.opt_state
, reply
.packet
,
1495 required_opts_solicit
,
1497 #endif /* defined (RFC3315_PRE_ERRATA_2010_08) */
1499 /* Return our reply to the caller. */
1500 reply_ret
->len
= reply
.cursor
;
1501 reply_ret
->buffer
= NULL
;
1502 if (!buffer_allocate(&reply_ret
->buffer
, reply
.cursor
, MDL
)) {
1503 log_fatal("No memory to store Reply.");
1505 memcpy(reply_ret
->buffer
->data
, reply
.buf
.data
, reply
.cursor
);
1506 reply_ret
->data
= reply_ret
->buffer
->data
;
1508 /* If appropriate commit and rotate the lease file */
1509 (void) commit_leases_timed();
1513 if (reply
.shared
!= NULL
)
1514 shared_network_dereference(&reply
.shared
, MDL
);
1515 if (reply
.host
!= NULL
)
1516 host_dereference(&reply
.host
, MDL
);
1517 if (reply
.opt_state
!= NULL
)
1518 option_state_dereference(&reply
.opt_state
, MDL
);
1519 if (reply
.packet
!= NULL
)
1520 packet_dereference(&reply
.packet
, MDL
);
1521 if (reply
.client_id
.data
!= NULL
)
1522 data_string_forget(&reply
.client_id
, MDL
);
1523 if (packet_oro
.buffer
!= NULL
)
1524 data_string_forget(&packet_oro
, MDL
);
1525 reply
.renew
= reply
.rebind
= reply
.prefer
= reply
.valid
= 0;
1529 /* Process a client-supplied IA_NA. This may append options to the tail of
1530 * the reply packet being built in the reply_state structure.
1533 reply_process_ia_na(struct reply_state
*reply
, struct option_cache
*ia
) {
1534 isc_result_t status
= ISC_R_SUCCESS
;
1537 struct option_state
*packet_ia
;
1538 struct option_cache
*oc
;
1539 struct data_string ia_data
, data
;
1541 /* Initialize values that will get cleaned up on return. */
1543 memset(&ia_data
, 0, sizeof(ia_data
));
1544 memset(&data
, 0, sizeof(data
));
1546 * Note that find_client_address() may set reply->lease.
1549 /* Make sure there is at least room for the header. */
1550 if ((reply
->cursor
+ IA_NA_OFFSET
+ 4) > sizeof(reply
->buf
)) {
1551 log_error("reply_process_ia_na: Reply too long for IA.");
1552 return ISC_R_NOSPACE
;
1556 /* Fetch the IA_NA contents. */
1557 if (!get_encapsulated_IA_state(&packet_ia
, &ia_data
, reply
->packet
,
1558 ia
, IA_NA_OFFSET
)) {
1559 log_error("reply_process_ia_na: error evaluating ia");
1560 status
= ISC_R_FAILURE
;
1564 /* Extract IA_NA header contents. */
1565 iaid
= getULong(ia_data
.data
);
1566 reply
->renew
= getULong(ia_data
.data
+ 4);
1567 reply
->rebind
= getULong(ia_data
.data
+ 8);
1569 /* Create an IA_NA structure. */
1570 if (ia_allocate(&reply
->ia
, iaid
, (char *)reply
->client_id
.data
,
1571 reply
->client_id
.len
, MDL
) != ISC_R_SUCCESS
) {
1572 log_error("reply_process_ia_na: no memory for ia.");
1573 status
= ISC_R_NOMEMORY
;
1576 reply
->ia
->ia_type
= D6O_IA_NA
;
1578 /* Cache pre-existing IA, if any. */
1579 ia_hash_lookup(&reply
->old_ia
, ia_na_active
,
1580 (unsigned char *)reply
->ia
->iaid_duid
.data
,
1581 reply
->ia
->iaid_duid
.len
, MDL
);
1584 * Create an option cache to carry the IA_NA option contents, and
1585 * execute any user-supplied values into it.
1587 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
1588 status
= ISC_R_NOMEMORY
;
1592 /* Check & cache the fixed host record. */
1593 if ((reply
->host
!= NULL
) && (reply
->host
->fixed_addr
!= NULL
)) {
1594 struct iaddr tmp_addr
;
1596 if (!evaluate_option_cache(&reply
->fixed
, NULL
, NULL
, NULL
,
1597 NULL
, NULL
, &global_scope
,
1598 reply
->host
->fixed_addr
, MDL
)) {
1599 log_error("reply_process_ia_na: unable to evaluate "
1601 status
= ISC_R_FAILURE
;
1605 if (reply
->fixed
.len
< 16) {
1606 log_error("reply_process_ia_na: invalid fixed address.");
1607 status
= DHCP_R_INVALIDARG
;
1611 /* Find the static lease's subnet. */
1613 memcpy(tmp_addr
.iabuf
, reply
->fixed
.data
, 16);
1615 if (find_grouped_subnet(&reply
->subnet
, reply
->shared
,
1616 tmp_addr
, MDL
) == 0)
1617 log_fatal("Impossible condition at %s:%d.", MDL
);
1619 reply
->static_lease
= ISC_TRUE
;
1621 reply
->static_lease
= ISC_FALSE
;
1624 * Save the cursor position at the start of the IA, so we can
1625 * set length and adjust t1/t2 values later. We write a temporary
1626 * header out now just in case we decide to adjust the packet
1627 * within sub-process functions.
1629 ia_cursor
= reply
->cursor
;
1631 /* Initialize the IA_NA header. First the code. */
1632 putUShort(reply
->buf
.data
+ reply
->cursor
, (unsigned)D6O_IA_NA
);
1635 /* Then option length. */
1636 putUShort(reply
->buf
.data
+ reply
->cursor
, 0x0Cu
);
1639 /* Then IA_NA header contents; IAID. */
1640 putULong(reply
->buf
.data
+ reply
->cursor
, iaid
);
1643 /* We store the client's t1 for now, and may over-ride it later. */
1644 putULong(reply
->buf
.data
+ reply
->cursor
, reply
->renew
);
1647 /* We store the client's t2 for now, and may over-ride it later. */
1648 putULong(reply
->buf
.data
+ reply
->cursor
, reply
->rebind
);
1652 * For each address in this IA_NA, decide what to do about it.
1656 * The client leaves unchanged any information about addresses
1657 * it has recorded but are not included ("cancel/break" below).
1658 * A not included IA ("cleanup" below) could give a Renew/Rebind.
1660 oc
= lookup_option(&dhcpv6_universe
, packet_ia
, D6O_IAADDR
);
1661 reply
->valid
= reply
->prefer
= 0xffffffff;
1662 reply
->client_valid
= reply
->client_prefer
= 0;
1663 for (; oc
!= NULL
; oc
= oc
->next
) {
1664 status
= reply_process_addr(reply
, oc
);
1667 * Canceled means we did not allocate addresses to the
1668 * client, but we're "done" with this IA - we set a status
1669 * code. So transmit this reply, e.g., move on to the next
1672 if (status
== ISC_R_CANCELED
)
1675 if ((status
!= ISC_R_SUCCESS
) &&
1676 (status
!= ISC_R_ADDRINUSE
) &&
1677 (status
!= ISC_R_ADDRNOTAVAIL
))
1684 * If we fell through the above and never gave the client
1685 * an address, give it one now.
1687 if ((status
!= ISC_R_CANCELED
) && (reply
->client_resources
== 0)) {
1688 status
= find_client_address(reply
);
1690 if (status
== ISC_R_NORESOURCES
) {
1691 switch (reply
->packet
->dhcpv6_msg_type
) {
1692 case DHCPV6_SOLICIT
:
1694 * No address for any IA is handled
1699 case DHCPV6_REQUEST
:
1700 /* Section 18.2.1 (Request):
1702 * If the server cannot assign any addresses to
1703 * an IA in the message from the client, the
1704 * server MUST include the IA in the Reply
1705 * message with no addresses in the IA and a
1706 * Status Code option in the IA containing
1707 * status code NoAddrsAvail.
1709 option_state_dereference(&reply
->reply_ia
, MDL
);
1710 if (!option_state_allocate(&reply
->reply_ia
,
1713 log_error("reply_process_ia_na: No "
1714 "memory for option state "
1716 status
= ISC_R_NOMEMORY
;
1720 if (!set_status_code(STATUS_NoAddrsAvail
,
1721 "No addresses available "
1722 "for this interface.",
1724 log_error("reply_process_ia_na: Unable "
1725 "to set NoAddrsAvail status "
1727 status
= ISC_R_FAILURE
;
1731 status
= ISC_R_SUCCESS
;
1736 * RFC 3315 does not tell us to emit a status
1737 * code in this condition, or anything else.
1739 * If we included non-allocated addresses
1740 * (zeroed lifetimes) in an IA, then the client
1741 * will deconfigure them.
1743 * So we want to include the IA even if we
1744 * can't give it a new address if it includes
1745 * zeroed lifetime addresses.
1747 * We don't want to include the IA if we
1748 * provide zero addresses including zeroed
1751 if (reply
->resources_included
)
1752 status
= ISC_R_SUCCESS
;
1759 if (status
!= ISC_R_SUCCESS
)
1763 reply
->cursor
+= store_options6((char *)reply
->buf
.data
+ reply
->cursor
,
1764 sizeof(reply
->buf
) - reply
->cursor
,
1765 reply
->reply_ia
, reply
->packet
,
1766 required_opts_IA
, NULL
);
1768 /* Reset the length of this IA to match what was just written. */
1769 putUShort(reply
->buf
.data
+ ia_cursor
+ 2,
1770 reply
->cursor
- (ia_cursor
+ 4));
1773 * T1/T2 time selection is kind of weird. We actually use DHCP
1774 * (v4) scoped options as handy existing places where these might
1775 * be configured by an administrator. A value of zero tells the
1776 * client it may choose its own renewal time.
1779 oc
= lookup_option(&dhcp_universe
, reply
->opt_state
,
1780 DHO_DHCP_RENEWAL_TIME
);
1782 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
1783 reply
->packet
->options
,
1784 reply
->opt_state
, &global_scope
,
1787 log_error("Invalid renewal time.");
1789 reply
->renew
= getULong(data
.data
);
1792 if (data
.data
!= NULL
)
1793 data_string_forget(&data
, MDL
);
1795 putULong(reply
->buf
.data
+ ia_cursor
+ 8, reply
->renew
);
1799 oc
= lookup_option(&dhcp_universe
, reply
->opt_state
,
1800 DHO_DHCP_REBINDING_TIME
);
1802 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
1803 reply
->packet
->options
,
1804 reply
->opt_state
, &global_scope
,
1807 log_error("Invalid rebinding time.");
1809 reply
->rebind
= getULong(data
.data
);
1812 if (data
.data
!= NULL
)
1813 data_string_forget(&data
, MDL
);
1815 putULong(reply
->buf
.data
+ ia_cursor
+ 12, reply
->rebind
);
1818 * If this is not a 'soft' binding, consume the new changes into
1819 * the database (if any have been attached to the ia_na).
1821 * Loop through the assigned dynamic addresses, referencing the
1822 * leases onto this IA_NA rather than any old ones, and updating
1823 * pool timers for each (if any).
1825 if ((status
!= ISC_R_CANCELED
) && !reply
->static_lease
&&
1826 (reply
->buf
.reply
.msg_type
== DHCPV6_REPLY
) &&
1827 (reply
->ia
->num_iasubopt
!= 0)) {
1828 struct iasubopt
*tmp
;
1829 struct data_string
*ia_id
;
1832 for (i
= 0 ; i
< reply
->ia
->num_iasubopt
; i
++) {
1833 tmp
= reply
->ia
->iasubopt
[i
];
1835 if (tmp
->ia
!= NULL
)
1836 ia_dereference(&tmp
->ia
, MDL
);
1837 ia_reference(&tmp
->ia
, reply
->ia
, MDL
);
1839 /* Commit 'hard' bindings. */
1840 tmp
->hard_lifetime_end_time
=
1841 tmp
->soft_lifetime_end_time
;
1842 tmp
->soft_lifetime_end_time
= 0;
1843 renew_lease6(tmp
->ipv6_pool
, tmp
);
1844 schedule_lease_timeout(tmp
->ipv6_pool
);
1846 #if defined (NSUPDATE)
1848 * Perform ddns updates.
1850 oc
= lookup_option(&server_universe
, reply
->opt_state
,
1853 evaluate_boolean_option_cache(NULL
, reply
->packet
,
1855 reply
->packet
->options
,
1859 ddns_updates(reply
->packet
, NULL
, NULL
,
1860 tmp
, NULL
, reply
->opt_state
);
1865 /* Remove any old ia from the hash. */
1866 if (reply
->old_ia
!= NULL
) {
1867 ia_id
= &reply
->old_ia
->iaid_duid
;
1868 ia_hash_delete(ia_na_active
,
1869 (unsigned char *)ia_id
->data
,
1871 ia_dereference(&reply
->old_ia
, MDL
);
1874 /* Put new ia into the hash. */
1875 reply
->ia
->cltt
= cur_time
;
1876 ia_id
= &reply
->ia
->iaid_duid
;
1877 ia_hash_add(ia_na_active
, (unsigned char *)ia_id
->data
,
1878 ia_id
->len
, reply
->ia
, MDL
);
1880 write_ia(reply
->ia
);
1884 if (packet_ia
!= NULL
)
1885 option_state_dereference(&packet_ia
, MDL
);
1886 if (reply
->reply_ia
!= NULL
)
1887 option_state_dereference(&reply
->reply_ia
, MDL
);
1888 if (ia_data
.data
!= NULL
)
1889 data_string_forget(&ia_data
, MDL
);
1890 if (data
.data
!= NULL
)
1891 data_string_forget(&data
, MDL
);
1892 if (reply
->ia
!= NULL
)
1893 ia_dereference(&reply
->ia
, MDL
);
1894 if (reply
->old_ia
!= NULL
)
1895 ia_dereference(&reply
->old_ia
, MDL
);
1896 if (reply
->lease
!= NULL
)
1897 iasubopt_dereference(&reply
->lease
, MDL
);
1898 if (reply
->fixed
.data
!= NULL
)
1899 data_string_forget(&reply
->fixed
, MDL
);
1900 if (reply
->subnet
!= NULL
)
1901 subnet_dereference(&reply
->subnet
, MDL
);
1904 * ISC_R_CANCELED is a status code used by the addr processing to
1905 * indicate we're replying with a status code. This is still a
1906 * success at higher layers.
1908 return((status
== ISC_R_CANCELED
) ? ISC_R_SUCCESS
: status
);
1912 * Process an IAADDR within a given IA_xA, storing any IAADDR reply contents
1913 * into the reply's current ia-scoped option cache. Returns ISC_R_CANCELED
1914 * in the event we are replying with a status code and do not wish to process
1915 * more IAADDRs within this IA.
1918 reply_process_addr(struct reply_state
*reply
, struct option_cache
*addr
) {
1919 u_int32_t pref_life
, valid_life
;
1920 struct binding_scope
**scope
;
1921 struct group
*group
;
1922 struct subnet
*subnet
;
1923 struct iaddr tmp_addr
;
1924 struct option_cache
*oc
;
1925 struct data_string iaaddr
, data
;
1926 isc_result_t status
= ISC_R_SUCCESS
;
1928 /* Initializes values that will be cleaned up. */
1929 memset(&iaaddr
, 0, sizeof(iaaddr
));
1930 memset(&data
, 0, sizeof(data
));
1931 /* Note that reply->lease may be set by address_is_owned() */
1934 * There is no point trying to process an incoming address if there
1935 * is no room for an outgoing address.
1937 if ((reply
->cursor
+ 28) > sizeof(reply
->buf
)) {
1938 log_error("reply_process_addr: Out of room for address.");
1939 return ISC_R_NOSPACE
;
1942 /* Extract this IAADDR option. */
1943 if (!evaluate_option_cache(&iaaddr
, reply
->packet
, NULL
, NULL
,
1944 reply
->packet
->options
, NULL
, &global_scope
,
1946 (iaaddr
.len
< IAADDR_OFFSET
)) {
1947 log_error("reply_process_addr: error evaluating IAADDR.");
1948 status
= ISC_R_FAILURE
;
1952 /* The first 16 bytes are the IPv6 address. */
1953 pref_life
= getULong(iaaddr
.data
+ 16);
1954 valid_life
= getULong(iaaddr
.data
+ 20);
1956 if ((reply
->client_valid
== 0) ||
1957 (reply
->client_valid
> valid_life
))
1958 reply
->client_valid
= valid_life
;
1960 if ((reply
->client_prefer
== 0) ||
1961 (reply
->client_prefer
> pref_life
))
1962 reply
->client_prefer
= pref_life
;
1965 * Clients may choose to send :: as an address, with the idea to give
1966 * hints about preferred-lifetime or valid-lifetime.
1969 memset(tmp_addr
.iabuf
, 0, 16);
1970 if (!memcmp(iaaddr
.data
, tmp_addr
.iabuf
, 16)) {
1971 /* Status remains success; we just ignore this one. */
1975 /* tmp_addr len remains 16 */
1976 memcpy(tmp_addr
.iabuf
, iaaddr
.data
, 16);
1979 * Verify that this address is on the client's network.
1981 for (subnet
= reply
->shared
->subnets
; subnet
!= NULL
;
1982 subnet
= subnet
->next_sibling
) {
1983 if (addr_eq(subnet_number(tmp_addr
, subnet
->netmask
),
1988 /* Address not found on shared network. */
1989 if (subnet
== NULL
) {
1990 /* Ignore this address on 'soft' bindings. */
1991 if (reply
->packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
) {
1992 /* disable rapid commit */
1993 reply
->buf
.reply
.msg_type
= DHCPV6_ADVERTISE
;
1994 delete_option(&dhcpv6_universe
,
1997 /* status remains success */
2002 * RFC3315 section 18.2.1:
2004 * If the server finds that the prefix on one or more IP
2005 * addresses in any IA in the message from the client is not
2006 * appropriate for the link to which the client is connected,
2007 * the server MUST return the IA to the client with a Status
2008 * Code option with the value NotOnLink.
2010 if (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REQUEST
) {
2011 /* Rewind the IA_NA to empty. */
2012 option_state_dereference(&reply
->reply_ia
, MDL
);
2013 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
2014 log_error("reply_process_addr: No memory for "
2015 "option state wipe.");
2016 status
= ISC_R_NOMEMORY
;
2020 /* Append a NotOnLink status code. */
2021 if (!set_status_code(STATUS_NotOnLink
,
2022 "Address not for use on this "
2023 "link.", reply
->reply_ia
)) {
2024 log_error("reply_process_addr: Failure "
2025 "setting status code.");
2026 status
= ISC_R_FAILURE
;
2030 /* Fin (no more IAADDRs). */
2031 status
= ISC_R_CANCELED
;
2036 * RFC3315 sections 18.2.3 and 18.2.4 have identical language:
2038 * If the server finds that any of the addresses are not
2039 * appropriate for the link to which the client is attached,
2040 * the server returns the address to the client with lifetimes
2043 if ((reply
->packet
->dhcpv6_msg_type
!= DHCPV6_RENEW
) &&
2044 (reply
->packet
->dhcpv6_msg_type
!= DHCPV6_REBIND
)) {
2045 log_error("It is impossible to lease a client that is "
2046 "not sending a solicit, request, renew, or "
2048 status
= ISC_R_FAILURE
;
2052 reply
->send_prefer
= reply
->send_valid
= 0;
2056 /* Verify the address belongs to the client. */
2057 if (!address_is_owned(reply
, &tmp_addr
)) {
2059 * For solicit and request, any addresses included are
2060 * 'requested' addresses. For rebind, we actually have
2061 * no direction on what to do from 3315 section 18.2.4!
2062 * So I think the best bet is to try and give it out, and if
2063 * we can't, zero lifetimes.
2065 if ((reply
->packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
) ||
2066 (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REQUEST
) ||
2067 (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REBIND
)) {
2068 status
= reply_process_try_addr(reply
, &tmp_addr
);
2071 * If the address is in use, or isn't in any dynamic
2072 * range, continue as normal. If any other error was
2075 if ((status
!= ISC_R_SUCCESS
) &&
2076 (status
!= ISC_R_ADDRINUSE
) &&
2077 (status
!= ISC_R_ADDRNOTAVAIL
))
2081 * If we didn't honor this lease, for solicit and
2082 * request we simply omit it from our answer. For
2083 * rebind, we send it with zeroed lifetimes.
2085 if (reply
->lease
== NULL
) {
2086 if (reply
->packet
->dhcpv6_msg_type
==
2088 reply
->send_prefer
= 0;
2089 reply
->send_valid
= 0;
2093 /* status remains success - ignore */
2097 * RFC3315 section 18.2.3:
2099 * If the server cannot find a client entry for the IA the
2100 * server returns the IA containing no addresses with a Status
2101 * Code option set to NoBinding in the Reply message.
2103 * On mismatch we (ab)use this pretending we have not the IA
2104 * as soon as we have not an address.
2106 } else if (reply
->packet
->dhcpv6_msg_type
== DHCPV6_RENEW
) {
2107 /* Rewind the IA_NA to empty. */
2108 option_state_dereference(&reply
->reply_ia
, MDL
);
2109 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
2110 log_error("reply_process_addr: No memory for "
2111 "option state wipe.");
2112 status
= ISC_R_NOMEMORY
;
2116 /* Append a NoBinding status code. */
2117 if (!set_status_code(STATUS_NoBinding
,
2118 "Address not bound to this "
2119 "interface.", reply
->reply_ia
)) {
2120 log_error("reply_process_addr: Unable to "
2121 "attach status code.");
2122 status
= ISC_R_FAILURE
;
2126 /* Fin (no more IAADDRs). */
2127 status
= ISC_R_CANCELED
;
2130 log_error("It is impossible to lease a client that is "
2131 "not sending a solicit, request, renew, or "
2133 status
= ISC_R_FAILURE
;
2138 if (reply
->static_lease
) {
2139 if (reply
->host
== NULL
)
2140 log_fatal("Impossible condition at %s:%d.", MDL
);
2142 scope
= &global_scope
;
2143 group
= reply
->subnet
->group
;
2145 if (reply
->lease
== NULL
)
2146 log_fatal("Impossible condition at %s:%d.", MDL
);
2148 scope
= &reply
->lease
->scope
;
2149 group
= reply
->lease
->ipv6_pool
->subnet
->group
;
2153 * If client_resources is nonzero, then the reply_process_is_addressed
2154 * function has executed configuration state into the reply option
2155 * cache. We will use that valid cache to derive configuration for
2156 * whether or not to engage in additional addresses, and similar.
2158 if (reply
->client_resources
!= 0) {
2162 * Does this client have "enough" addresses already? Default
2163 * to one. Everybody gets one, and one should be enough for
2166 oc
= lookup_option(&server_universe
, reply
->opt_state
,
2167 SV_LIMIT_ADDRS_PER_IA
);
2169 if (!evaluate_option_cache(&data
, reply
->packet
,
2171 reply
->packet
->options
,
2175 log_error("reply_process_addr: unable to "
2176 "evaluate addrs-per-ia value.");
2177 status
= ISC_R_FAILURE
;
2181 limit
= getULong(data
.data
);
2182 data_string_forget(&data
, MDL
);
2186 * If we wish to limit the client to a certain number of
2187 * addresses, then omit the address from the reply.
2189 if (reply
->client_resources
>= limit
)
2193 status
= reply_process_is_addressed(reply
, scope
, group
);
2194 if (status
!= ISC_R_SUCCESS
)
2198 status
= reply_process_send_addr(reply
, &tmp_addr
);
2201 if (iaaddr
.data
!= NULL
)
2202 data_string_forget(&iaaddr
, MDL
);
2203 if (data
.data
!= NULL
)
2204 data_string_forget(&data
, MDL
);
2205 if (reply
->lease
!= NULL
)
2206 iasubopt_dereference(&reply
->lease
, MDL
);
2212 * Verify the address belongs to the client. If we've got a host
2213 * record with a fixed address, it has to be the assigned address
2214 * (fault out all else). Otherwise it's a dynamic address, so lookup
2215 * that address and make sure it belongs to this DUID:IAID pair.
2217 static isc_boolean_t
2218 address_is_owned(struct reply_state
*reply
, struct iaddr
*addr
) {
2222 * This faults out addresses that don't match fixed addresses.
2224 if (reply
->static_lease
) {
2225 if (reply
->fixed
.data
== NULL
)
2226 log_fatal("Impossible condition at %s:%d.", MDL
);
2228 if (memcmp(addr
->iabuf
, reply
->fixed
.data
, 16) == 0)
2234 if ((reply
->old_ia
== NULL
) || (reply
->old_ia
->num_iasubopt
== 0))
2237 for (i
= 0 ; i
< reply
->old_ia
->num_iasubopt
; i
++) {
2238 struct iasubopt
*tmp
;
2240 tmp
= reply
->old_ia
->iasubopt
[i
];
2242 if (memcmp(addr
->iabuf
, &tmp
->addr
, 16) == 0) {
2243 if (lease6_usable(tmp
) == ISC_FALSE
) {
2246 iasubopt_reference(&reply
->lease
, tmp
, MDL
);
2254 /* Process a client-supplied IA_TA. This may append options to the tail of
2255 * the reply packet being built in the reply_state structure.
2258 reply_process_ia_ta(struct reply_state
*reply
, struct option_cache
*ia
) {
2259 isc_result_t status
= ISC_R_SUCCESS
;
2262 struct option_state
*packet_ia
;
2263 struct option_cache
*oc
;
2264 struct data_string ia_data
, data
;
2265 struct data_string iaaddr
;
2266 u_int32_t pref_life
, valid_life
;
2267 struct iaddr tmp_addr
;
2269 /* Initialize values that will get cleaned up on return. */
2271 memset(&ia_data
, 0, sizeof(ia_data
));
2272 memset(&data
, 0, sizeof(data
));
2273 memset(&iaaddr
, 0, sizeof(iaaddr
));
2275 /* Make sure there is at least room for the header. */
2276 if ((reply
->cursor
+ IA_TA_OFFSET
+ 4) > sizeof(reply
->buf
)) {
2277 log_error("reply_process_ia_ta: Reply too long for IA.");
2278 return ISC_R_NOSPACE
;
2282 /* Fetch the IA_TA contents. */
2283 if (!get_encapsulated_IA_state(&packet_ia
, &ia_data
, reply
->packet
,
2284 ia
, IA_TA_OFFSET
)) {
2285 log_error("reply_process_ia_ta: error evaluating ia");
2286 status
= ISC_R_FAILURE
;
2290 /* Extract IA_TA header contents. */
2291 iaid
= getULong(ia_data
.data
);
2293 /* Create an IA_TA structure. */
2294 if (ia_allocate(&reply
->ia
, iaid
, (char *)reply
->client_id
.data
,
2295 reply
->client_id
.len
, MDL
) != ISC_R_SUCCESS
) {
2296 log_error("reply_process_ia_ta: no memory for ia.");
2297 status
= ISC_R_NOMEMORY
;
2300 reply
->ia
->ia_type
= D6O_IA_TA
;
2302 /* Cache pre-existing IA, if any. */
2303 ia_hash_lookup(&reply
->old_ia
, ia_ta_active
,
2304 (unsigned char *)reply
->ia
->iaid_duid
.data
,
2305 reply
->ia
->iaid_duid
.len
, MDL
);
2308 * Create an option cache to carry the IA_TA option contents, and
2309 * execute any user-supplied values into it.
2311 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
2312 status
= ISC_R_NOMEMORY
;
2317 * Temporary leases are dynamic by definition.
2319 reply
->static_lease
= ISC_FALSE
;
2322 * Save the cursor position at the start of the IA, so we can
2323 * set length later. We write a temporary
2324 * header out now just in case we decide to adjust the packet
2325 * within sub-process functions.
2327 ia_cursor
= reply
->cursor
;
2329 /* Initialize the IA_TA header. First the code. */
2330 putUShort(reply
->buf
.data
+ reply
->cursor
, (unsigned)D6O_IA_TA
);
2333 /* Then option length. */
2334 putUShort(reply
->buf
.data
+ reply
->cursor
, 0x04u
);
2337 /* Then IA_TA header contents; IAID. */
2338 putULong(reply
->buf
.data
+ reply
->cursor
, iaid
);
2342 * Deal with an IAADDR for lifetimes.
2343 * For all or none, process IAADDRs as hints.
2345 reply
->valid
= reply
->prefer
= 0xffffffff;
2346 reply
->client_valid
= reply
->client_prefer
= 0;
2347 oc
= lookup_option(&dhcpv6_universe
, packet_ia
, D6O_IAADDR
);
2348 for (; oc
!= NULL
; oc
= oc
->next
) {
2349 memset(&iaaddr
, 0, sizeof(iaaddr
));
2350 if (!evaluate_option_cache(&iaaddr
, reply
->packet
,
2352 reply
->packet
->options
, NULL
,
2353 &global_scope
, oc
, MDL
) ||
2354 (iaaddr
.len
< IAADDR_OFFSET
)) {
2355 log_error("reply_process_ia_ta: error "
2356 "evaluating IAADDR.");
2357 status
= ISC_R_FAILURE
;
2360 /* The first 16 bytes are the IPv6 address. */
2361 pref_life
= getULong(iaaddr
.data
+ 16);
2362 valid_life
= getULong(iaaddr
.data
+ 20);
2364 if ((reply
->client_valid
== 0) ||
2365 (reply
->client_valid
> valid_life
))
2366 reply
->client_valid
= valid_life
;
2368 if ((reply
->client_prefer
== 0) ||
2369 (reply
->client_prefer
> pref_life
))
2370 reply
->client_prefer
= pref_life
;
2372 /* Nothing more if something has failed. */
2373 if (status
== ISC_R_CANCELED
)
2377 memcpy(tmp_addr
.iabuf
, iaaddr
.data
, 16);
2378 if (!temporary_is_available(reply
, &tmp_addr
))
2380 status
= reply_process_is_addressed(reply
,
2381 &reply
->lease
->scope
,
2382 reply
->shared
->group
);
2383 if (status
!= ISC_R_SUCCESS
)
2385 status
= reply_process_send_addr(reply
, &tmp_addr
);
2386 if (status
!= ISC_R_SUCCESS
)
2388 if (reply
->lease
!= NULL
)
2389 iasubopt_dereference(&reply
->lease
, MDL
);
2393 /* Rewind the IA_TA to empty. */
2394 option_state_dereference(&reply
->reply_ia
, MDL
);
2395 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
2396 status
= ISC_R_NOMEMORY
;
2399 status
= ISC_R_CANCELED
;
2400 reply
->client_resources
= 0;
2401 reply
->resources_included
= ISC_FALSE
;
2402 if (reply
->lease
!= NULL
)
2403 iasubopt_dereference(&reply
->lease
, MDL
);
2408 * Give the client temporary addresses.
2410 if (reply
->client_resources
!= 0)
2412 status
= find_client_temporaries(reply
);
2413 if (status
== ISC_R_NORESOURCES
) {
2414 switch (reply
->packet
->dhcpv6_msg_type
) {
2415 case DHCPV6_SOLICIT
:
2417 * No address for any IA is handled
2422 case DHCPV6_REQUEST
:
2423 /* Section 18.2.1 (Request):
2425 * If the server cannot assign any addresses to
2426 * an IA in the message from the client, the
2427 * server MUST include the IA in the Reply
2428 * message with no addresses in the IA and a
2429 * Status Code option in the IA containing
2430 * status code NoAddrsAvail.
2432 option_state_dereference(&reply
->reply_ia
, MDL
);
2433 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
2434 log_error("reply_process_ia_ta: No "
2435 "memory for option state wipe.");
2436 status
= ISC_R_NOMEMORY
;
2440 if (!set_status_code(STATUS_NoAddrsAvail
,
2441 "No addresses available "
2442 "for this interface.",
2444 log_error("reply_process_ia_ta: Unable "
2445 "to set NoAddrsAvail status code.");
2446 status
= ISC_R_FAILURE
;
2450 status
= ISC_R_SUCCESS
;
2455 * We don't want to include the IA if we
2456 * provide zero addresses including zeroed
2459 if (reply
->resources_included
)
2460 status
= ISC_R_SUCCESS
;
2465 } else if (status
!= ISC_R_SUCCESS
)
2469 reply
->cursor
+= store_options6((char *)reply
->buf
.data
+ reply
->cursor
,
2470 sizeof(reply
->buf
) - reply
->cursor
,
2471 reply
->reply_ia
, reply
->packet
,
2472 required_opts_IA
, NULL
);
2474 /* Reset the length of this IA to match what was just written. */
2475 putUShort(reply
->buf
.data
+ ia_cursor
+ 2,
2476 reply
->cursor
- (ia_cursor
+ 4));
2479 * Consume the new changes into the database (if any have been
2480 * attached to the ia_ta).
2482 * Loop through the assigned dynamic addresses, referencing the
2483 * leases onto this IA_TA rather than any old ones, and updating
2484 * pool timers for each (if any).
2486 if ((status
!= ISC_R_CANCELED
) &&
2487 (reply
->buf
.reply
.msg_type
== DHCPV6_REPLY
) &&
2488 (reply
->ia
->num_iasubopt
!= 0)) {
2489 struct iasubopt
*tmp
;
2490 struct data_string
*ia_id
;
2493 for (i
= 0 ; i
< reply
->ia
->num_iasubopt
; i
++) {
2494 tmp
= reply
->ia
->iasubopt
[i
];
2496 if (tmp
->ia
!= NULL
)
2497 ia_dereference(&tmp
->ia
, MDL
);
2498 ia_reference(&tmp
->ia
, reply
->ia
, MDL
);
2500 /* Commit 'hard' bindings. */
2501 tmp
->hard_lifetime_end_time
=
2502 tmp
->soft_lifetime_end_time
;
2503 tmp
->soft_lifetime_end_time
= 0;
2504 renew_lease6(tmp
->ipv6_pool
, tmp
);
2505 schedule_lease_timeout(tmp
->ipv6_pool
);
2507 #if defined (NSUPDATE)
2509 * Perform ddns updates.
2511 oc
= lookup_option(&server_universe
, reply
->opt_state
,
2514 evaluate_boolean_option_cache(NULL
, reply
->packet
,
2516 reply
->packet
->options
,
2520 ddns_updates(reply
->packet
, NULL
, NULL
,
2521 tmp
, NULL
, reply
->opt_state
);
2526 /* Remove any old ia from the hash. */
2527 if (reply
->old_ia
!= NULL
) {
2528 ia_id
= &reply
->old_ia
->iaid_duid
;
2529 ia_hash_delete(ia_ta_active
,
2530 (unsigned char *)ia_id
->data
,
2532 ia_dereference(&reply
->old_ia
, MDL
);
2535 /* Put new ia into the hash. */
2536 reply
->ia
->cltt
= cur_time
;
2537 ia_id
= &reply
->ia
->iaid_duid
;
2538 ia_hash_add(ia_ta_active
, (unsigned char *)ia_id
->data
,
2539 ia_id
->len
, reply
->ia
, MDL
);
2541 write_ia(reply
->ia
);
2545 if (packet_ia
!= NULL
)
2546 option_state_dereference(&packet_ia
, MDL
);
2547 if (iaaddr
.data
!= NULL
)
2548 data_string_forget(&iaaddr
, MDL
);
2549 if (reply
->reply_ia
!= NULL
)
2550 option_state_dereference(&reply
->reply_ia
, MDL
);
2551 if (ia_data
.data
!= NULL
)
2552 data_string_forget(&ia_data
, MDL
);
2553 if (data
.data
!= NULL
)
2554 data_string_forget(&data
, MDL
);
2555 if (reply
->ia
!= NULL
)
2556 ia_dereference(&reply
->ia
, MDL
);
2557 if (reply
->old_ia
!= NULL
)
2558 ia_dereference(&reply
->old_ia
, MDL
);
2559 if (reply
->lease
!= NULL
)
2560 iasubopt_dereference(&reply
->lease
, MDL
);
2563 * ISC_R_CANCELED is a status code used by the addr processing to
2564 * indicate we're replying with other addresses. This is still a
2565 * success at higher layers.
2567 return((status
== ISC_R_CANCELED
) ? ISC_R_SUCCESS
: status
);
2571 * Verify the temporary address is available.
2573 static isc_boolean_t
2574 temporary_is_available(struct reply_state
*reply
, struct iaddr
*addr
) {
2575 struct in6_addr tmp_addr
;
2576 struct subnet
*subnet
;
2577 struct ipv6_pool
*pool
;
2580 memcpy(&tmp_addr
, addr
->iabuf
, sizeof(tmp_addr
));
2582 * Clients may choose to send :: as an address, with the idea to give
2583 * hints about preferred-lifetime or valid-lifetime.
2584 * So this is not a request for this address.
2586 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr
))
2590 * Verify that this address is on the client's network.
2592 for (subnet
= reply
->shared
->subnets
; subnet
!= NULL
;
2593 subnet
= subnet
->next_sibling
) {
2594 if (addr_eq(subnet_number(*addr
, subnet
->netmask
),
2599 /* Address not found on shared network. */
2604 * Check if this address is owned (must be before next step).
2606 if (address_is_owned(reply
, addr
))
2610 * Verify that this address is in a temporary pool and try to get it.
2612 if (reply
->shared
->ipv6_pools
== NULL
)
2614 for (i
= 0 ; (pool
= reply
->shared
->ipv6_pools
[i
]) != NULL
; i
++) {
2615 if (pool
->pool_type
!= D6O_IA_TA
)
2617 if (ipv6_in_pool(&tmp_addr
, pool
))
2622 if (lease6_exists(pool
, &tmp_addr
))
2624 if (iasubopt_allocate(&reply
->lease
, MDL
) != ISC_R_SUCCESS
)
2626 reply
->lease
->addr
= tmp_addr
;
2627 reply
->lease
->plen
= 0;
2628 /* Default is soft binding for 2 minutes. */
2629 if (add_lease6(pool
, reply
->lease
, cur_time
+ 120) != ISC_R_SUCCESS
)
2636 * Get a temporary address per prefix.
2639 find_client_temporaries(struct reply_state
*reply
) {
2640 struct shared_network
*shared
;
2642 struct ipv6_pool
*p
;
2643 isc_result_t status
;
2644 unsigned int attempts
;
2645 struct iaddr send_addr
;
2648 * No pools, we're done.
2650 shared
= reply
->shared
;
2651 if (shared
->ipv6_pools
== NULL
) {
2652 log_debug("Unable to get client addresses: "
2653 "no IPv6 pools on this shared network");
2654 return ISC_R_NORESOURCES
;
2657 status
= ISC_R_NORESOURCES
;
2659 p
= shared
->ipv6_pools
[i
];
2663 if (p
->pool_type
!= D6O_IA_TA
) {
2668 * Get an address in this temporary pool.
2670 status
= create_lease6(p
, &reply
->lease
, &attempts
,
2671 &reply
->client_id
, cur_time
+ 120);
2672 if (status
!= ISC_R_SUCCESS
) {
2673 log_debug("Unable to get a temporary address.");
2677 status
= reply_process_is_addressed(reply
,
2678 &reply
->lease
->scope
,
2679 reply
->lease
->ipv6_pool
->subnet
->group
);
2680 if (status
!= ISC_R_SUCCESS
) {
2684 memcpy(send_addr
.iabuf
, &reply
->lease
->addr
, 16);
2685 status
= reply_process_send_addr(reply
, &send_addr
);
2686 if (status
!= ISC_R_SUCCESS
) {
2689 if (reply
->lease
!= NULL
) {
2690 iasubopt_dereference(&reply
->lease
, MDL
);
2695 if (reply
->lease
!= NULL
) {
2696 iasubopt_dereference(&reply
->lease
, MDL
);
2702 * This function only returns failure on 'hard' failures. If it succeeds,
2703 * it will leave a lease structure behind.
2706 reply_process_try_addr(struct reply_state
*reply
, struct iaddr
*addr
) {
2707 isc_result_t status
= ISC_R_ADDRNOTAVAIL
;
2708 struct ipv6_pool
*pool
;
2710 struct data_string data_addr
;
2712 if ((reply
== NULL
) || (reply
->shared
== NULL
) ||
2713 (addr
== NULL
) || (reply
->lease
!= NULL
))
2714 return (DHCP_R_INVALIDARG
);
2716 if (reply
->shared
->ipv6_pools
== NULL
)
2717 return (ISC_R_ADDRNOTAVAIL
);
2719 memset(&data_addr
, 0, sizeof(data_addr
));
2720 data_addr
.len
= addr
->len
;
2721 data_addr
.data
= addr
->iabuf
;
2723 for (i
= 0 ; (pool
= reply
->shared
->ipv6_pools
[i
]) != NULL
; i
++) {
2724 if (pool
->pool_type
!= D6O_IA_NA
)
2726 status
= try_client_v6_address(&reply
->lease
, pool
,
2728 if (status
== ISC_R_SUCCESS
)
2732 /* Note that this is just pedantry. There is no allocation to free. */
2733 data_string_forget(&data_addr
, MDL
);
2734 /* Return just the most recent status... */
2738 /* Look around for an address to give the client. First, look through the
2739 * old IA for addresses we can extend. Second, try to allocate a new address.
2740 * Finally, actually add that address into the current reply IA.
2743 find_client_address(struct reply_state
*reply
) {
2744 struct iaddr send_addr
;
2745 isc_result_t status
= ISC_R_NORESOURCES
;
2746 struct iasubopt
*lease
, *best_lease
= NULL
;
2747 struct binding_scope
**scope
;
2748 struct group
*group
;
2751 if (reply
->static_lease
) {
2752 if (reply
->host
== NULL
)
2753 return DHCP_R_INVALIDARG
;
2756 memcpy(send_addr
.iabuf
, reply
->fixed
.data
, 16);
2758 status
= ISC_R_SUCCESS
;
2759 scope
= &global_scope
;
2760 group
= reply
->subnet
->group
;
2764 if (reply
->old_ia
!= NULL
) {
2765 for (i
= 0 ; i
< reply
->old_ia
->num_iasubopt
; i
++) {
2766 struct shared_network
*candidate_shared
;
2768 lease
= reply
->old_ia
->iasubopt
[i
];
2769 candidate_shared
= lease
->ipv6_pool
->shared_network
;
2772 * Look for the best lease on the client's shared
2775 if ((candidate_shared
== reply
->shared
) &&
2776 (lease6_usable(lease
) == ISC_TRUE
)) {
2777 best_lease
= lease_compare(lease
, best_lease
);
2782 /* Try to pick a new address if we didn't find one, or if we found an
2785 if ((best_lease
== NULL
) || (best_lease
->state
== FTS_ABANDONED
)) {
2786 status
= pick_v6_address(&reply
->lease
, reply
->shared
,
2787 &reply
->ia
->iaid_duid
);
2788 } else if (best_lease
!= NULL
) {
2789 iasubopt_reference(&reply
->lease
, best_lease
, MDL
);
2790 status
= ISC_R_SUCCESS
;
2793 /* Pick the abandoned lease as a last resort. */
2794 if ((status
== ISC_R_NORESOURCES
) && (best_lease
!= NULL
)) {
2795 /* I don't see how this is supposed to be done right now. */
2796 log_error("Reclaiming abandoned addresses is not yet "
2797 "supported. Treating this as an out of space "
2799 /* iasubopt_reference(&reply->lease, best_lease, MDL); */
2802 /* Give up now if we didn't find a lease. */
2803 if (status
!= ISC_R_SUCCESS
)
2806 if (reply
->lease
== NULL
)
2807 log_fatal("Impossible condition at %s:%d.", MDL
);
2809 /* Draw binding scopes from the lease's binding scope, and config
2810 * from the lease's containing subnet and higher. Note that it may
2811 * be desirable to place the group attachment directly in the pool.
2813 scope
= &reply
->lease
->scope
;
2814 group
= reply
->lease
->ipv6_pool
->subnet
->group
;
2817 memcpy(send_addr
.iabuf
, &reply
->lease
->addr
, 16);
2820 status
= reply_process_is_addressed(reply
, scope
, group
);
2821 if (status
!= ISC_R_SUCCESS
)
2824 status
= reply_process_send_addr(reply
, &send_addr
);
2828 /* Once an address is found for a client, perform several common functions;
2829 * Calculate and store valid and preferred lease times, draw client options
2830 * into the option state.
2833 reply_process_is_addressed(struct reply_state
*reply
,
2834 struct binding_scope
**scope
, struct group
*group
)
2836 isc_result_t status
= ISC_R_SUCCESS
;
2837 struct data_string data
;
2838 struct option_cache
*oc
;
2840 /* Initialize values we will cleanup. */
2841 memset(&data
, 0, sizeof(data
));
2844 * Bring configured options into the root packet level cache - start
2845 * with the lease's closest enclosing group (passed in by the caller
2848 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
2849 reply
->packet
->options
, reply
->opt_state
,
2850 scope
, group
, root_group
);
2853 * If there is a host record, over-ride with values configured there,
2854 * without re-evaluating configuration from the previously executed
2855 * group or its common enclosers.
2857 if (reply
->host
!= NULL
)
2858 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
2859 reply
->packet
->options
,
2860 reply
->opt_state
, scope
,
2861 reply
->host
->group
, group
);
2863 /* Determine valid lifetime. */
2864 if (reply
->client_valid
== 0)
2865 reply
->send_valid
= DEFAULT_DEFAULT_LEASE_TIME
;
2867 reply
->send_valid
= reply
->client_valid
;
2869 oc
= lookup_option(&server_universe
, reply
->opt_state
,
2870 SV_DEFAULT_LEASE_TIME
);
2872 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
2873 reply
->packet
->options
,
2877 log_error("reply_process_is_addressed: unable to "
2878 "evaluate default lease time");
2879 status
= ISC_R_FAILURE
;
2883 reply
->send_valid
= getULong(data
.data
);
2884 data_string_forget(&data
, MDL
);
2887 if (reply
->client_prefer
== 0)
2888 reply
->send_prefer
= reply
->send_valid
;
2890 reply
->send_prefer
= reply
->client_prefer
;
2892 if (reply
->send_prefer
>= reply
->send_valid
)
2893 reply
->send_prefer
= (reply
->send_valid
/ 2) +
2894 (reply
->send_valid
/ 8);
2896 oc
= lookup_option(&server_universe
, reply
->opt_state
,
2897 SV_PREFER_LIFETIME
);
2899 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
2900 reply
->packet
->options
,
2904 log_error("reply_process_is_addressed: unable to "
2905 "evaluate preferred lease time");
2906 status
= ISC_R_FAILURE
;
2910 reply
->send_prefer
= getULong(data
.data
);
2911 data_string_forget(&data
, MDL
);
2914 /* Note lowest values for later calculation of renew/rebind times. */
2915 if (reply
->prefer
> reply
->send_prefer
)
2916 reply
->prefer
= reply
->send_prefer
;
2918 if (reply
->valid
> reply
->send_valid
)
2919 reply
->valid
= reply
->send_valid
;
2923 * XXX: Old 4.0.0 alpha code would change the host {} record
2924 * XXX: uid upon lease assignment. This was intended to cover the
2925 * XXX: case where a client first identifies itself using vendor
2926 * XXX: options in a solicit, or request, but later neglects to include
2927 * XXX: these options in a Renew or Rebind. It is not clear that this
2928 * XXX: is required, and has some startling ramifications (such as
2929 * XXX: how to recover this dynamic host {} state across restarts).
2931 if (reply
->host
!= NULL
)
2932 change_host_uid(host
, reply
->client_id
->data
,
2933 reply
->client_id
->len
);
2936 /* Perform dynamic lease related update work. */
2937 if (reply
->lease
!= NULL
) {
2938 /* Cached lifetimes */
2939 reply
->lease
->prefer
= reply
->send_prefer
;
2940 reply
->lease
->valid
= reply
->send_valid
;
2942 /* Advance (or rewind) the valid lifetime. */
2943 if (reply
->buf
.reply
.msg_type
== DHCPV6_REPLY
) {
2944 reply
->lease
->soft_lifetime_end_time
=
2945 cur_time
+ reply
->send_valid
;
2946 /* Wait before renew! */
2949 status
= ia_add_iasubopt(reply
->ia
, reply
->lease
, MDL
);
2950 if (status
!= ISC_R_SUCCESS
) {
2951 log_fatal("reply_process_is_addressed: Unable to "
2952 "attach lease to new IA: %s",
2953 isc_result_totext(status
));
2957 * If this is a new lease, make sure it is attached somewhere.
2959 if (reply
->lease
->ia
== NULL
) {
2960 ia_reference(&reply
->lease
->ia
, reply
->ia
, MDL
);
2964 /* Bring a copy of the relevant options into the IA scope. */
2965 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
2966 reply
->packet
->options
, reply
->reply_ia
,
2967 scope
, group
, root_group
);
2970 * And bring in host record configuration, if any, but not to overlap
2971 * the previous group or its common enclosers.
2973 if (reply
->host
!= NULL
)
2974 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
2975 reply
->packet
->options
,
2976 reply
->reply_ia
, scope
,
2977 reply
->host
->group
, group
);
2980 if (data
.data
!= NULL
)
2981 data_string_forget(&data
, MDL
);
2983 if (status
== ISC_R_SUCCESS
)
2984 reply
->client_resources
++;
2989 /* Simply send an IAADDR within the IA scope as described. */
2991 reply_process_send_addr(struct reply_state
*reply
, struct iaddr
*addr
) {
2992 isc_result_t status
= ISC_R_SUCCESS
;
2993 struct data_string data
;
2995 memset(&data
, 0, sizeof(data
));
2997 /* Now append the lease. */
2998 data
.len
= IAADDR_OFFSET
;
2999 if (!buffer_allocate(&data
.buffer
, data
.len
, MDL
)) {
3000 log_error("reply_process_send_addr: out of memory"
3001 "allocating new IAADDR buffer.");
3002 status
= ISC_R_NOMEMORY
;
3005 data
.data
= data
.buffer
->data
;
3007 memcpy(data
.buffer
->data
, addr
->iabuf
, 16);
3008 putULong(data
.buffer
->data
+ 16, reply
->send_prefer
);
3009 putULong(data
.buffer
->data
+ 20, reply
->send_valid
);
3011 if (!append_option_buffer(&dhcpv6_universe
, reply
->reply_ia
,
3012 data
.buffer
, data
.buffer
->data
,
3013 data
.len
, D6O_IAADDR
, 0)) {
3014 log_error("reply_process_send_addr: unable "
3015 "to save IAADDR option");
3016 status
= ISC_R_FAILURE
;
3020 reply
->resources_included
= ISC_TRUE
;
3023 if (data
.data
!= NULL
)
3024 data_string_forget(&data
, MDL
);
3029 /* Choose the better of two leases. */
3030 static struct iasubopt
*
3031 lease_compare(struct iasubopt
*alpha
, struct iasubopt
*beta
) {
3037 switch(alpha
->state
) {
3039 switch(beta
->state
) {
3041 /* Choose the lease with the longest lifetime (most
3042 * likely the most recently allocated).
3044 if (alpha
->hard_lifetime_end_time
<
3045 beta
->hard_lifetime_end_time
)
3055 log_fatal("Impossible condition at %s:%d.", MDL
);
3060 switch (beta
->state
) {
3065 /* Choose the most recently expired lease. */
3066 if (alpha
->hard_lifetime_end_time
<
3067 beta
->hard_lifetime_end_time
)
3069 else if ((alpha
->hard_lifetime_end_time
==
3070 beta
->hard_lifetime_end_time
) &&
3071 (alpha
->soft_lifetime_end_time
<
3072 beta
->soft_lifetime_end_time
))
3081 log_fatal("Impossible condition at %s:%d.", MDL
);
3086 switch (beta
->state
) {
3092 /* Choose the lease that was abandoned longest ago. */
3093 if (alpha
->hard_lifetime_end_time
<
3094 beta
->hard_lifetime_end_time
)
3098 log_fatal("Impossible condition at %s:%d.", MDL
);
3103 log_fatal("Impossible condition at %s:%d.", MDL
);
3106 log_fatal("Triple impossible condition at %s:%d.", MDL
);
3110 /* Process a client-supplied IA_PD. This may append options to the tail of
3111 * the reply packet being built in the reply_state structure.
3114 reply_process_ia_pd(struct reply_state
*reply
, struct option_cache
*ia
) {
3115 isc_result_t status
= ISC_R_SUCCESS
;
3118 struct option_state
*packet_ia
;
3119 struct option_cache
*oc
;
3120 struct data_string ia_data
, data
;
3122 /* Initialize values that will get cleaned up on return. */
3124 memset(&ia_data
, 0, sizeof(ia_data
));
3125 memset(&data
, 0, sizeof(data
));
3127 * Note that find_client_prefix() may set reply->lease.
3130 /* Make sure there is at least room for the header. */
3131 if ((reply
->cursor
+ IA_PD_OFFSET
+ 4) > sizeof(reply
->buf
)) {
3132 log_error("reply_process_ia_pd: Reply too long for IA.");
3133 return ISC_R_NOSPACE
;
3137 /* Fetch the IA_PD contents. */
3138 if (!get_encapsulated_IA_state(&packet_ia
, &ia_data
, reply
->packet
,
3139 ia
, IA_PD_OFFSET
)) {
3140 log_error("reply_process_ia_pd: error evaluating ia");
3141 status
= ISC_R_FAILURE
;
3145 /* Extract IA_PD header contents. */
3146 iaid
= getULong(ia_data
.data
);
3147 reply
->renew
= getULong(ia_data
.data
+ 4);
3148 reply
->rebind
= getULong(ia_data
.data
+ 8);
3150 /* Create an IA_PD structure. */
3151 if (ia_allocate(&reply
->ia
, iaid
, (char *)reply
->client_id
.data
,
3152 reply
->client_id
.len
, MDL
) != ISC_R_SUCCESS
) {
3153 log_error("reply_process_ia_pd: no memory for ia.");
3154 status
= ISC_R_NOMEMORY
;
3157 reply
->ia
->ia_type
= D6O_IA_PD
;
3159 /* Cache pre-existing IA_PD, if any. */
3160 ia_hash_lookup(&reply
->old_ia
, ia_pd_active
,
3161 (unsigned char *)reply
->ia
->iaid_duid
.data
,
3162 reply
->ia
->iaid_duid
.len
, MDL
);
3165 * Create an option cache to carry the IA_PD option contents, and
3166 * execute any user-supplied values into it.
3168 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
3169 status
= ISC_R_NOMEMORY
;
3173 /* Check & count the fixed prefix host records. */
3174 reply
->static_prefixes
= 0;
3175 if ((reply
->host
!= NULL
) && (reply
->host
->fixed_prefix
!= NULL
)) {
3176 struct iaddrcidrnetlist
*fp
;
3178 for (fp
= reply
->host
->fixed_prefix
; fp
!= NULL
;
3180 reply
->static_prefixes
+= 1;
3185 * Save the cursor position at the start of the IA_PD, so we can
3186 * set length and adjust t1/t2 values later. We write a temporary
3187 * header out now just in case we decide to adjust the packet
3188 * within sub-process functions.
3190 ia_cursor
= reply
->cursor
;
3192 /* Initialize the IA_PD header. First the code. */
3193 putUShort(reply
->buf
.data
+ reply
->cursor
, (unsigned)D6O_IA_PD
);
3196 /* Then option length. */
3197 putUShort(reply
->buf
.data
+ reply
->cursor
, 0x0Cu
);
3200 /* Then IA_PD header contents; IAID. */
3201 putULong(reply
->buf
.data
+ reply
->cursor
, iaid
);
3204 /* We store the client's t1 for now, and may over-ride it later. */
3205 putULong(reply
->buf
.data
+ reply
->cursor
, reply
->renew
);
3208 /* We store the client's t2 for now, and may over-ride it later. */
3209 putULong(reply
->buf
.data
+ reply
->cursor
, reply
->rebind
);
3213 * For each prefix in this IA_PD, decide what to do about it.
3215 oc
= lookup_option(&dhcpv6_universe
, packet_ia
, D6O_IAPREFIX
);
3216 reply
->valid
= reply
->prefer
= 0xffffffff;
3217 reply
->client_valid
= reply
->client_prefer
= 0;
3218 reply
->preflen
= -1;
3219 for (; oc
!= NULL
; oc
= oc
->next
) {
3220 status
= reply_process_prefix(reply
, oc
);
3223 * Canceled means we did not allocate prefixes to the
3224 * client, but we're "done" with this IA - we set a status
3225 * code. So transmit this reply, e.g., move on to the next
3228 if (status
== ISC_R_CANCELED
)
3231 if ((status
!= ISC_R_SUCCESS
) &&
3232 (status
!= ISC_R_ADDRINUSE
) &&
3233 (status
!= ISC_R_ADDRNOTAVAIL
))
3240 * If we fell through the above and never gave the client
3241 * a prefix, give it one now.
3243 if ((status
!= ISC_R_CANCELED
) && (reply
->client_resources
== 0)) {
3244 status
= find_client_prefix(reply
);
3246 if (status
== ISC_R_NORESOURCES
) {
3247 switch (reply
->packet
->dhcpv6_msg_type
) {
3248 case DHCPV6_SOLICIT
:
3250 * No prefix for any IA is handled
3255 case DHCPV6_REQUEST
:
3256 /* Same than for addresses. */
3257 option_state_dereference(&reply
->reply_ia
, MDL
);
3258 if (!option_state_allocate(&reply
->reply_ia
,
3261 log_error("reply_process_ia_pd: No "
3262 "memory for option state "
3264 status
= ISC_R_NOMEMORY
;
3268 if (!set_status_code(STATUS_NoPrefixAvail
,
3269 "No prefixes available "
3270 "for this interface.",
3272 log_error("reply_process_ia_pd: "
3274 "NoPrefixAvail status "
3276 status
= ISC_R_FAILURE
;
3280 status
= ISC_R_SUCCESS
;
3284 if (reply
->resources_included
)
3285 status
= ISC_R_SUCCESS
;
3292 if (status
!= ISC_R_SUCCESS
)
3296 reply
->cursor
+= store_options6((char *)reply
->buf
.data
+ reply
->cursor
,
3297 sizeof(reply
->buf
) - reply
->cursor
,
3298 reply
->reply_ia
, reply
->packet
,
3299 required_opts_IA_PD
, NULL
);
3301 /* Reset the length of this IA_PD to match what was just written. */
3302 putUShort(reply
->buf
.data
+ ia_cursor
+ 2,
3303 reply
->cursor
- (ia_cursor
+ 4));
3306 * T1/T2 time selection is kind of weird. We actually use DHCP
3307 * (v4) scoped options as handy existing places where these might
3308 * be configured by an administrator. A value of zero tells the
3309 * client it may choose its own renewal time.
3312 oc
= lookup_option(&dhcp_universe
, reply
->opt_state
,
3313 DHO_DHCP_RENEWAL_TIME
);
3315 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
3316 reply
->packet
->options
,
3317 reply
->opt_state
, &global_scope
,
3320 log_error("Invalid renewal time.");
3322 reply
->renew
= getULong(data
.data
);
3325 if (data
.data
!= NULL
)
3326 data_string_forget(&data
, MDL
);
3328 putULong(reply
->buf
.data
+ ia_cursor
+ 8, reply
->renew
);
3332 oc
= lookup_option(&dhcp_universe
, reply
->opt_state
,
3333 DHO_DHCP_REBINDING_TIME
);
3335 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
3336 reply
->packet
->options
,
3337 reply
->opt_state
, &global_scope
,
3340 log_error("Invalid rebinding time.");
3342 reply
->rebind
= getULong(data
.data
);
3345 if (data
.data
!= NULL
)
3346 data_string_forget(&data
, MDL
);
3348 putULong(reply
->buf
.data
+ ia_cursor
+ 12, reply
->rebind
);
3351 * If this is not a 'soft' binding, consume the new changes into
3352 * the database (if any have been attached to the ia_pd).
3354 * Loop through the assigned dynamic prefixes, referencing the
3355 * prefixes onto this IA_PD rather than any old ones, and updating
3356 * prefix pool timers for each (if any).
3358 if ((status
!= ISC_R_CANCELED
) && (reply
->static_prefixes
== 0) &&
3359 (reply
->buf
.reply
.msg_type
== DHCPV6_REPLY
) &&
3360 (reply
->ia
->num_iasubopt
!= 0)) {
3361 struct iasubopt
*tmp
;
3362 struct data_string
*ia_id
;
3365 for (i
= 0 ; i
< reply
->ia
->num_iasubopt
; i
++) {
3366 tmp
= reply
->ia
->iasubopt
[i
];
3368 if (tmp
->ia
!= NULL
)
3369 ia_dereference(&tmp
->ia
, MDL
);
3370 ia_reference(&tmp
->ia
, reply
->ia
, MDL
);
3372 /* Commit 'hard' bindings. */
3373 tmp
->hard_lifetime_end_time
=
3374 tmp
->soft_lifetime_end_time
;
3375 tmp
->soft_lifetime_end_time
= 0;
3376 renew_lease6(tmp
->ipv6_pool
, tmp
);
3377 schedule_lease_timeout(tmp
->ipv6_pool
);
3380 /* Remove any old ia from the hash. */
3381 if (reply
->old_ia
!= NULL
) {
3382 ia_id
= &reply
->old_ia
->iaid_duid
;
3383 ia_hash_delete(ia_pd_active
,
3384 (unsigned char *)ia_id
->data
,
3386 ia_dereference(&reply
->old_ia
, MDL
);
3389 /* Put new ia into the hash. */
3390 reply
->ia
->cltt
= cur_time
;
3391 ia_id
= &reply
->ia
->iaid_duid
;
3392 ia_hash_add(ia_pd_active
, (unsigned char *)ia_id
->data
,
3393 ia_id
->len
, reply
->ia
, MDL
);
3395 write_ia(reply
->ia
);
3399 if (packet_ia
!= NULL
)
3400 option_state_dereference(&packet_ia
, MDL
);
3401 if (reply
->reply_ia
!= NULL
)
3402 option_state_dereference(&reply
->reply_ia
, MDL
);
3403 if (ia_data
.data
!= NULL
)
3404 data_string_forget(&ia_data
, MDL
);
3405 if (data
.data
!= NULL
)
3406 data_string_forget(&data
, MDL
);
3407 if (reply
->ia
!= NULL
)
3408 ia_dereference(&reply
->ia
, MDL
);
3409 if (reply
->old_ia
!= NULL
)
3410 ia_dereference(&reply
->old_ia
, MDL
);
3411 if (reply
->lease
!= NULL
)
3412 iasubopt_dereference(&reply
->lease
, MDL
);
3415 * ISC_R_CANCELED is a status code used by the prefix processing to
3416 * indicate we're replying with a status code. This is still a
3417 * success at higher layers.
3419 return((status
== ISC_R_CANCELED
) ? ISC_R_SUCCESS
: status
);
3423 * Process an IAPREFIX within a given IA_PD, storing any IAPREFIX reply
3424 * contents into the reply's current ia_pd-scoped option cache. Returns
3425 * ISC_R_CANCELED in the event we are replying with a status code and do
3426 * not wish to process more IAPREFIXes within this IA_PD.
3429 reply_process_prefix(struct reply_state
*reply
, struct option_cache
*pref
) {
3430 u_int32_t pref_life
, valid_life
;
3431 struct binding_scope
**scope
;
3432 struct iaddrcidrnet tmp_pref
;
3433 struct option_cache
*oc
;
3434 struct data_string iapref
, data
;
3435 isc_result_t status
= ISC_R_SUCCESS
;
3437 /* Initializes values that will be cleaned up. */
3438 memset(&iapref
, 0, sizeof(iapref
));
3439 memset(&data
, 0, sizeof(data
));
3440 /* Note that reply->lease may be set by prefix_is_owned() */
3443 * There is no point trying to process an incoming prefix if there
3444 * is no room for an outgoing prefix.
3446 if ((reply
->cursor
+ 29) > sizeof(reply
->buf
)) {
3447 log_error("reply_process_prefix: Out of room for prefix.");
3448 return ISC_R_NOSPACE
;
3451 /* Extract this IAPREFIX option. */
3452 if (!evaluate_option_cache(&iapref
, reply
->packet
, NULL
, NULL
,
3453 reply
->packet
->options
, NULL
, &global_scope
,
3455 (iapref
.len
< IAPREFIX_OFFSET
)) {
3456 log_error("reply_process_prefix: error evaluating IAPREFIX.");
3457 status
= ISC_R_FAILURE
;
3462 * Layout: preferred and valid lifetimes followed by the prefix
3463 * length and the IPv6 address.
3465 pref_life
= getULong(iapref
.data
);
3466 valid_life
= getULong(iapref
.data
+ 4);
3468 if ((reply
->client_valid
== 0) ||
3469 (reply
->client_valid
> valid_life
))
3470 reply
->client_valid
= valid_life
;
3472 if ((reply
->client_prefer
== 0) ||
3473 (reply
->client_prefer
> pref_life
))
3474 reply
->client_prefer
= pref_life
;
3477 * Clients may choose to send ::/0 as a prefix, with the idea to give
3478 * hints about preferred-lifetime or valid-lifetime.
3480 tmp_pref
.lo_addr
.len
= 16;
3481 memset(tmp_pref
.lo_addr
.iabuf
, 0, 16);
3482 if ((iapref
.data
[8] == 0) &&
3483 (memcmp(iapref
.data
+ 9, tmp_pref
.lo_addr
.iabuf
, 16) == 0)) {
3484 /* Status remains success; we just ignore this one. */
3489 * Clients may choose to send ::/X as a prefix to specify a
3490 * preferred/requested prefix length. Note X is never zero here.
3492 tmp_pref
.bits
= (int) iapref
.data
[8];
3493 if (reply
->preflen
< 0) {
3494 /* Cache the first preferred prefix length. */
3495 reply
->preflen
= tmp_pref
.bits
;
3497 if (memcmp(iapref
.data
+ 9, tmp_pref
.lo_addr
.iabuf
, 16) == 0) {
3501 memcpy(tmp_pref
.lo_addr
.iabuf
, iapref
.data
+ 9, 16);
3503 /* Verify the prefix belongs to the client. */
3504 if (!prefix_is_owned(reply
, &tmp_pref
)) {
3505 /* Same than for addresses. */
3506 if ((reply
->packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
) ||
3507 (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REQUEST
) ||
3508 (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REBIND
)) {
3509 status
= reply_process_try_prefix(reply
, &tmp_pref
);
3511 /* Either error out or skip this prefix. */
3512 if ((status
!= ISC_R_SUCCESS
) &&
3513 (status
!= ISC_R_ADDRINUSE
) &&
3514 (status
!= ISC_R_ADDRNOTAVAIL
))
3517 if (reply
->lease
== NULL
) {
3518 if (reply
->packet
->dhcpv6_msg_type
==
3520 reply
->send_prefer
= 0;
3521 reply
->send_valid
= 0;
3525 /* status remains success - ignore */
3529 * RFC3633 section 18.2.3:
3531 * If the delegating router cannot find a binding
3532 * for the requesting router's IA_PD the delegating
3533 * router returns the IA_PD containing no prefixes
3534 * with a Status Code option set to NoBinding in the
3537 * On mismatch we (ab)use this pretending we have not the IA
3538 * as soon as we have not a prefix.
3540 } else if (reply
->packet
->dhcpv6_msg_type
== DHCPV6_RENEW
) {
3541 /* Rewind the IA_PD to empty. */
3542 option_state_dereference(&reply
->reply_ia
, MDL
);
3543 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
3544 log_error("reply_process_prefix: No memory "
3545 "for option state wipe.");
3546 status
= ISC_R_NOMEMORY
;
3550 /* Append a NoBinding status code. */
3551 if (!set_status_code(STATUS_NoBinding
,
3552 "Prefix not bound to this "
3553 "interface.", reply
->reply_ia
)) {
3554 log_error("reply_process_prefix: Unable to "
3555 "attach status code.");
3556 status
= ISC_R_FAILURE
;
3560 /* Fin (no more IAPREFIXes). */
3561 status
= ISC_R_CANCELED
;
3564 log_error("It is impossible to lease a client that is "
3565 "not sending a solicit, request, renew, or "
3567 status
= ISC_R_FAILURE
;
3572 if (reply
->static_prefixes
> 0) {
3573 if (reply
->host
== NULL
)
3574 log_fatal("Impossible condition at %s:%d.", MDL
);
3576 scope
= &global_scope
;
3578 if (reply
->lease
== NULL
)
3579 log_fatal("Impossible condition at %s:%d.", MDL
);
3581 scope
= &reply
->lease
->scope
;
3585 * If client_resources is nonzero, then the reply_process_is_prefixed
3586 * function has executed configuration state into the reply option
3587 * cache. We will use that valid cache to derive configuration for
3588 * whether or not to engage in additional prefixes, and similar.
3590 if (reply
->client_resources
!= 0) {
3594 * Does this client have "enough" prefixes already? Default
3595 * to one. Everybody gets one, and one should be enough for
3598 oc
= lookup_option(&server_universe
, reply
->opt_state
,
3599 SV_LIMIT_PREFS_PER_IA
);
3601 if (!evaluate_option_cache(&data
, reply
->packet
,
3603 reply
->packet
->options
,
3607 log_error("reply_process_prefix: unable to "
3608 "evaluate prefs-per-ia value.");
3609 status
= ISC_R_FAILURE
;
3613 limit
= getULong(data
.data
);
3614 data_string_forget(&data
, MDL
);
3618 * If we wish to limit the client to a certain number of
3619 * prefixes, then omit the prefix from the reply.
3621 if (reply
->client_resources
>= limit
)
3625 status
= reply_process_is_prefixed(reply
, scope
, reply
->shared
->group
);
3626 if (status
!= ISC_R_SUCCESS
)
3630 status
= reply_process_send_prefix(reply
, &tmp_pref
);
3633 if (iapref
.data
!= NULL
)
3634 data_string_forget(&iapref
, MDL
);
3635 if (data
.data
!= NULL
)
3636 data_string_forget(&data
, MDL
);
3637 if (reply
->lease
!= NULL
)
3638 iasubopt_dereference(&reply
->lease
, MDL
);
3644 * Verify the prefix belongs to the client. If we've got a host
3645 * record with fixed prefixes, it has to be an assigned prefix
3646 * (fault out all else). Otherwise it's a dynamic prefix, so lookup
3647 * that prefix and make sure it belongs to this DUID:IAID pair.
3649 static isc_boolean_t
3650 prefix_is_owned(struct reply_state
*reply
, struct iaddrcidrnet
*pref
) {
3651 struct iaddrcidrnetlist
*l
;
3655 * This faults out prefixes that don't match fixed prefixes.
3657 if (reply
->static_prefixes
> 0) {
3658 for (l
= reply
->host
->fixed_prefix
; l
!= NULL
; l
= l
->next
) {
3659 if ((pref
->bits
== l
->cidrnet
.bits
) &&
3660 (memcmp(pref
->lo_addr
.iabuf
,
3661 l
->cidrnet
.lo_addr
.iabuf
, 16) == 0))
3667 if ((reply
->old_ia
== NULL
) ||
3668 (reply
->old_ia
->num_iasubopt
== 0))
3671 for (i
= 0 ; i
< reply
->old_ia
->num_iasubopt
; i
++) {
3672 struct iasubopt
*tmp
;
3674 tmp
= reply
->old_ia
->iasubopt
[i
];
3676 if ((pref
->bits
== (int) tmp
->plen
) &&
3677 (memcmp(pref
->lo_addr
.iabuf
, &tmp
->addr
, 16) == 0)) {
3678 if (lease6_usable(tmp
) == ISC_FALSE
) {
3681 iasubopt_reference(&reply
->lease
, tmp
, MDL
);
3690 * This function only returns failure on 'hard' failures. If it succeeds,
3691 * it will leave a prefix structure behind.
3694 reply_process_try_prefix(struct reply_state
*reply
,
3695 struct iaddrcidrnet
*pref
) {
3696 isc_result_t status
= ISC_R_ADDRNOTAVAIL
;
3697 struct ipv6_pool
*pool
;
3699 struct data_string data_pref
;
3701 if ((reply
== NULL
) || (reply
->shared
== NULL
) ||
3702 (pref
== NULL
) || (reply
->lease
!= NULL
))
3703 return (DHCP_R_INVALIDARG
);
3705 if (reply
->shared
->ipv6_pools
== NULL
)
3706 return (ISC_R_ADDRNOTAVAIL
);
3708 memset(&data_pref
, 0, sizeof(data_pref
));
3710 if (!buffer_allocate(&data_pref
.buffer
, data_pref
.len
, MDL
)) {
3711 log_error("reply_process_try_prefix: out of memory.");
3712 return (ISC_R_NOMEMORY
);
3714 data_pref
.data
= data_pref
.buffer
->data
;
3715 data_pref
.buffer
->data
[0] = (u_int8_t
) pref
->bits
;
3716 memcpy(data_pref
.buffer
->data
+ 1, pref
->lo_addr
.iabuf
, 16);
3718 for (i
= 0 ; (pool
= reply
->shared
->ipv6_pools
[i
]) != NULL
; i
++) {
3719 if (pool
->pool_type
!= D6O_IA_PD
)
3721 status
= try_client_v6_prefix(&reply
->lease
, pool
,
3723 /* If we found it in this pool (either in use or available),
3724 there is no need to look further. */
3725 if ( (status
== ISC_R_SUCCESS
) || (status
== ISC_R_ADDRINUSE
) )
3729 data_string_forget(&data_pref
, MDL
);
3730 /* Return just the most recent status... */
3734 /* Look around for a prefix to give the client. First, look through the old
3735 * IA_PD for prefixes we can extend. Second, try to allocate a new prefix.
3736 * Finally, actually add that prefix into the current reply IA_PD.
3739 find_client_prefix(struct reply_state
*reply
) {
3740 struct iaddrcidrnet send_pref
;
3741 isc_result_t status
= ISC_R_NORESOURCES
;
3742 struct iasubopt
*prefix
, *best_prefix
= NULL
;
3743 struct binding_scope
**scope
;
3746 if (reply
->static_prefixes
> 0) {
3747 struct iaddrcidrnetlist
*l
;
3749 if (reply
->host
== NULL
)
3750 return DHCP_R_INVALIDARG
;
3752 for (l
= reply
->host
->fixed_prefix
; l
!= NULL
; l
= l
->next
) {
3753 if (l
->cidrnet
.bits
== reply
->preflen
)
3758 * If no fixed prefix has the preferred length,
3759 * get the first one.
3761 l
= reply
->host
->fixed_prefix
;
3763 memcpy(&send_pref
, &l
->cidrnet
, sizeof(send_pref
));
3765 status
= ISC_R_SUCCESS
;
3766 scope
= &global_scope
;
3770 if (reply
->old_ia
!= NULL
) {
3771 for (i
= 0 ; i
< reply
->old_ia
->num_iasubopt
; i
++) {
3772 struct shared_network
*candidate_shared
;
3774 prefix
= reply
->old_ia
->iasubopt
[i
];
3775 candidate_shared
= prefix
->ipv6_pool
->shared_network
;
3778 * Consider this prefix if it is in a global pool or
3779 * if it is scoped in a pool under the client's shared
3782 if (((candidate_shared
== NULL
) ||
3783 (candidate_shared
== reply
->shared
)) &&
3784 (lease6_usable(prefix
) == ISC_TRUE
)) {
3785 best_prefix
= prefix_compare(reply
, prefix
,
3791 /* Try to pick a new prefix if we didn't find one, or if we found an
3794 if ((best_prefix
== NULL
) || (best_prefix
->state
== FTS_ABANDONED
)) {
3795 status
= pick_v6_prefix(&reply
->lease
, reply
->preflen
,
3796 reply
->shared
, &reply
->client_id
);
3797 } else if (best_prefix
!= NULL
) {
3798 iasubopt_reference(&reply
->lease
, best_prefix
, MDL
);
3799 status
= ISC_R_SUCCESS
;
3802 /* Pick the abandoned prefix as a last resort. */
3803 if ((status
== ISC_R_NORESOURCES
) && (best_prefix
!= NULL
)) {
3804 /* I don't see how this is supposed to be done right now. */
3805 log_error("Reclaiming abandoned prefixes is not yet "
3806 "supported. Treating this as an out of space "
3808 /* iasubopt_reference(&reply->lease, best_prefix, MDL); */
3811 /* Give up now if we didn't find a prefix. */
3812 if (status
!= ISC_R_SUCCESS
)
3815 if (reply
->lease
== NULL
)
3816 log_fatal("Impossible condition at %s:%d.", MDL
);
3818 scope
= &reply
->lease
->scope
;
3820 send_pref
.lo_addr
.len
= 16;
3821 memcpy(send_pref
.lo_addr
.iabuf
, &reply
->lease
->addr
, 16);
3822 send_pref
.bits
= (int) reply
->lease
->plen
;
3825 status
= reply_process_is_prefixed(reply
, scope
, reply
->shared
->group
);
3826 if (status
!= ISC_R_SUCCESS
)
3829 status
= reply_process_send_prefix(reply
, &send_pref
);
3833 /* Once a prefix is found for a client, perform several common functions;
3834 * Calculate and store valid and preferred prefix times, draw client options
3835 * into the option state.
3838 reply_process_is_prefixed(struct reply_state
*reply
,
3839 struct binding_scope
**scope
, struct group
*group
)
3841 isc_result_t status
= ISC_R_SUCCESS
;
3842 struct data_string data
;
3843 struct option_cache
*oc
;
3845 /* Initialize values we will cleanup. */
3846 memset(&data
, 0, sizeof(data
));
3849 * Bring configured options into the root packet level cache - start
3850 * with the lease's closest enclosing group (passed in by the caller
3853 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
3854 reply
->packet
->options
, reply
->opt_state
,
3855 scope
, group
, root_group
);
3858 * If there is a host record, over-ride with values configured there,
3859 * without re-evaluating configuration from the previously executed
3860 * group or its common enclosers.
3862 if (reply
->host
!= NULL
)
3863 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
3864 reply
->packet
->options
,
3865 reply
->opt_state
, scope
,
3866 reply
->host
->group
, group
);
3868 /* Determine valid lifetime. */
3869 if (reply
->client_valid
== 0)
3870 reply
->send_valid
= DEFAULT_DEFAULT_LEASE_TIME
;
3872 reply
->send_valid
= reply
->client_valid
;
3874 oc
= lookup_option(&server_universe
, reply
->opt_state
,
3875 SV_DEFAULT_LEASE_TIME
);
3877 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
3878 reply
->packet
->options
,
3882 log_error("reply_process_is_prefixed: unable to "
3883 "evaluate default prefix time");
3884 status
= ISC_R_FAILURE
;
3888 reply
->send_valid
= getULong(data
.data
);
3889 data_string_forget(&data
, MDL
);
3892 if (reply
->client_prefer
== 0)
3893 reply
->send_prefer
= reply
->send_valid
;
3895 reply
->send_prefer
= reply
->client_prefer
;
3897 if (reply
->send_prefer
>= reply
->send_valid
)
3898 reply
->send_prefer
= (reply
->send_valid
/ 2) +
3899 (reply
->send_valid
/ 8);
3901 oc
= lookup_option(&server_universe
, reply
->opt_state
,
3902 SV_PREFER_LIFETIME
);
3904 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
3905 reply
->packet
->options
,
3909 log_error("reply_process_is_prefixed: unable to "
3910 "evaluate preferred prefix time");
3911 status
= ISC_R_FAILURE
;
3915 reply
->send_prefer
= getULong(data
.data
);
3916 data_string_forget(&data
, MDL
);
3919 /* Note lowest values for later calculation of renew/rebind times. */
3920 if (reply
->prefer
> reply
->send_prefer
)
3921 reply
->prefer
= reply
->send_prefer
;
3923 if (reply
->valid
> reply
->send_valid
)
3924 reply
->valid
= reply
->send_valid
;
3926 /* Perform dynamic prefix related update work. */
3927 if (reply
->lease
!= NULL
) {
3928 /* Cached lifetimes */
3929 reply
->lease
->prefer
= reply
->send_prefer
;
3930 reply
->lease
->valid
= reply
->send_valid
;
3932 /* Advance (or rewind) the valid lifetime. */
3933 if (reply
->buf
.reply
.msg_type
== DHCPV6_REPLY
) {
3934 reply
->lease
->soft_lifetime_end_time
=
3935 cur_time
+ reply
->send_valid
;
3936 /* Wait before renew! */
3939 status
= ia_add_iasubopt(reply
->ia
, reply
->lease
, MDL
);
3940 if (status
!= ISC_R_SUCCESS
) {
3941 log_fatal("reply_process_is_prefixed: Unable to "
3942 "attach prefix to new IA_PD: %s",
3943 isc_result_totext(status
));
3947 * If this is a new prefix, make sure it is attached somewhere.
3949 if (reply
->lease
->ia
== NULL
) {
3950 ia_reference(&reply
->lease
->ia
, reply
->ia
, MDL
);
3954 /* Bring a copy of the relevant options into the IA_PD scope. */
3955 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
3956 reply
->packet
->options
, reply
->reply_ia
,
3957 scope
, group
, root_group
);
3960 * And bring in host record configuration, if any, but not to overlap
3961 * the previous group or its common enclosers.
3963 if (reply
->host
!= NULL
)
3964 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
3965 reply
->packet
->options
,
3966 reply
->reply_ia
, scope
,
3967 reply
->host
->group
, group
);
3970 if (data
.data
!= NULL
)
3971 data_string_forget(&data
, MDL
);
3973 if (status
== ISC_R_SUCCESS
)
3974 reply
->client_resources
++;
3979 /* Simply send an IAPREFIX within the IA_PD scope as described. */
3981 reply_process_send_prefix(struct reply_state
*reply
,
3982 struct iaddrcidrnet
*pref
) {
3983 isc_result_t status
= ISC_R_SUCCESS
;
3984 struct data_string data
;
3986 memset(&data
, 0, sizeof(data
));
3988 /* Now append the prefix. */
3989 data
.len
= IAPREFIX_OFFSET
;
3990 if (!buffer_allocate(&data
.buffer
, data
.len
, MDL
)) {
3991 log_error("reply_process_send_prefix: out of memory"
3992 "allocating new IAPREFIX buffer.");
3993 status
= ISC_R_NOMEMORY
;
3996 data
.data
= data
.buffer
->data
;
3998 putULong(data
.buffer
->data
, reply
->send_prefer
);
3999 putULong(data
.buffer
->data
+ 4, reply
->send_valid
);
4000 data
.buffer
->data
[8] = pref
->bits
;
4001 memcpy(data
.buffer
->data
+ 9, pref
->lo_addr
.iabuf
, 16);
4003 if (!append_option_buffer(&dhcpv6_universe
, reply
->reply_ia
,
4004 data
.buffer
, data
.buffer
->data
,
4005 data
.len
, D6O_IAPREFIX
, 0)) {
4006 log_error("reply_process_send_prefix: unable "
4007 "to save IAPREFIX option");
4008 status
= ISC_R_FAILURE
;
4012 reply
->resources_included
= ISC_TRUE
;
4015 if (data
.data
!= NULL
)
4016 data_string_forget(&data
, MDL
);
4021 /* Choose the better of two prefixes. */
4022 static struct iasubopt
*
4023 prefix_compare(struct reply_state
*reply
,
4024 struct iasubopt
*alpha
, struct iasubopt
*beta
) {
4030 if (reply
->preflen
>= 0) {
4031 if ((alpha
->plen
== reply
->preflen
) &&
4032 (beta
->plen
!= reply
->preflen
))
4034 if ((beta
->plen
== reply
->preflen
) &&
4035 (alpha
->plen
!= reply
->preflen
))
4039 switch(alpha
->state
) {
4041 switch(beta
->state
) {
4043 /* Choose the prefix with the longest lifetime (most
4044 * likely the most recently allocated).
4046 if (alpha
->hard_lifetime_end_time
<
4047 beta
->hard_lifetime_end_time
)
4057 log_fatal("Impossible condition at %s:%d.", MDL
);
4062 switch (beta
->state
) {
4067 /* Choose the most recently expired prefix. */
4068 if (alpha
->hard_lifetime_end_time
<
4069 beta
->hard_lifetime_end_time
)
4071 else if ((alpha
->hard_lifetime_end_time
==
4072 beta
->hard_lifetime_end_time
) &&
4073 (alpha
->soft_lifetime_end_time
<
4074 beta
->soft_lifetime_end_time
))
4083 log_fatal("Impossible condition at %s:%d.", MDL
);
4088 switch (beta
->state
) {
4094 /* Choose the prefix that was abandoned longest ago. */
4095 if (alpha
->hard_lifetime_end_time
<
4096 beta
->hard_lifetime_end_time
)
4100 log_fatal("Impossible condition at %s:%d.", MDL
);
4105 log_fatal("Impossible condition at %s:%d.", MDL
);
4108 log_fatal("Triple impossible condition at %s:%d.", MDL
);
4113 * Solicit is how a client starts requesting addresses.
4115 * If the client asks for rapid commit, and we support it, we will
4116 * allocate the addresses and reply.
4118 * Otherwise we will send an advertise message.
4122 dhcpv6_solicit(struct data_string
*reply_ret
, struct packet
*packet
) {
4123 struct data_string client_id
;
4126 * Validate our input.
4128 if (!valid_client_msg(packet
, &client_id
)) {
4132 lease_to_client(reply_ret
, packet
, &client_id
, NULL
);
4137 data_string_forget(&client_id
, MDL
);
4141 * Request is how a client actually requests addresses.
4143 * Very similar to Solicit handling, except the server DUID is required.
4146 /* TODO: reject unicast messages, unless we set unicast option */
4148 dhcpv6_request(struct data_string
*reply_ret
, struct packet
*packet
) {
4149 struct data_string client_id
;
4150 struct data_string server_id
;
4153 * Validate our input.
4155 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
4162 lease_to_client(reply_ret
, packet
, &client_id
, &server_id
);
4167 data_string_forget(&client_id
, MDL
);
4168 data_string_forget(&server_id
, MDL
);
4171 /* Find a DHCPv6 packet's shared network from hints in the packet.
4174 shared_network_from_packet6(struct shared_network
**shared
,
4175 struct packet
*packet
)
4177 const struct packet
*chk_packet
;
4178 const struct in6_addr
*link_addr
, *first_link_addr
;
4179 struct iaddr tmp_addr
;
4180 struct subnet
*subnet
;
4181 isc_result_t status
;
4183 if ((shared
== NULL
) || (*shared
!= NULL
) || (packet
== NULL
))
4184 return DHCP_R_INVALIDARG
;
4187 * First, find the link address where the packet from the client
4188 * first appeared (if this packet was relayed).
4190 first_link_addr
= NULL
;
4191 chk_packet
= packet
->dhcpv6_container_packet
;
4192 while (chk_packet
!= NULL
) {
4193 link_addr
= &chk_packet
->dhcpv6_link_address
;
4194 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr
) &&
4195 !IN6_IS_ADDR_LINKLOCAL(link_addr
)) {
4196 first_link_addr
= link_addr
;
4199 chk_packet
= chk_packet
->dhcpv6_container_packet
;
4203 * If there is a relayed link address, find the subnet associated
4204 * with that, and use that to get the appropriate
4207 if (first_link_addr
!= NULL
) {
4208 tmp_addr
.len
= sizeof(*first_link_addr
);
4209 memcpy(tmp_addr
.iabuf
,
4210 first_link_addr
, sizeof(*first_link_addr
));
4212 if (!find_subnet(&subnet
, tmp_addr
, MDL
)) {
4213 log_debug("No subnet found for link-address %s.",
4215 return ISC_R_NOTFOUND
;
4217 status
= shared_network_reference(shared
,
4218 subnet
->shared_network
, MDL
);
4219 subnet_dereference(&subnet
, MDL
);
4222 * If there is no link address, we will use the interface
4223 * that this packet came in on to pick the shared_network.
4225 } else if (packet
->interface
!= NULL
) {
4226 status
= shared_network_reference(shared
,
4227 packet
->interface
->shared_network
,
4229 if (packet
->dhcpv6_container_packet
!= NULL
) {
4230 log_info("[L2 Relay] No link address in relay packet "
4231 "assuming L2 relay and using receiving "
4237 * We shouldn't be able to get here but if there is no link
4238 * address and no interface we don't know where to get the
4239 * pool from log an error and return an error.
4241 log_error("No interface and no link address "
4242 "can't determine pool");
4243 status
= DHCP_R_INVALIDARG
;
4250 * When a client thinks it might be on a new link, it sends a
4253 * From RFC3315 section 18.2.2:
4255 * When the server receives a Confirm message, the server determines
4256 * whether the addresses in the Confirm message are appropriate for the
4257 * link to which the client is attached. If all of the addresses in the
4258 * Confirm message pass this test, the server returns a status of
4259 * Success. If any of the addresses do not pass this test, the server
4260 * returns a status of NotOnLink. If the server is unable to perform
4261 * this test (for example, the server does not have information about
4262 * prefixes on the link to which the client is connected), or there were
4263 * no addresses in any of the IAs sent by the client, the server MUST
4264 * NOT send a reply to the client.
4268 dhcpv6_confirm(struct data_string
*reply_ret
, struct packet
*packet
) {
4269 struct shared_network
*shared
;
4270 struct subnet
*subnet
;
4271 struct option_cache
*ia
, *ta
, *oc
;
4272 struct data_string cli_enc_opt_data
, iaaddr
, client_id
, packet_oro
;
4273 struct option_state
*cli_enc_opt_state
, *opt_state
;
4274 struct iaddr cli_addr
;
4276 isc_boolean_t inappropriate
, has_addrs
;
4277 char reply_data
[65536];
4278 struct dhcpv6_packet
*reply
= (struct dhcpv6_packet
*)reply_data
;
4279 int reply_ofs
= (int)(offsetof(struct dhcpv6_packet
, options
));
4282 * Basic client message validation.
4284 memset(&client_id
, 0, sizeof(client_id
));
4285 if (!valid_client_msg(packet
, &client_id
)) {
4290 * Do not process Confirms that do not have IA's we do not recognize.
4292 ia
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
4293 ta
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_TA
);
4294 if ((ia
== NULL
) && (ta
== NULL
))
4298 * IA_PD's are simply ignored.
4300 delete_option(&dhcpv6_universe
, packet
->options
, D6O_IA_PD
);
4303 * Bit of variable initialization.
4305 opt_state
= cli_enc_opt_state
= NULL
;
4306 memset(&cli_enc_opt_data
, 0, sizeof(cli_enc_opt_data
));
4307 memset(&iaaddr
, 0, sizeof(iaaddr
));
4308 memset(&packet_oro
, 0, sizeof(packet_oro
));
4310 /* Determine what shared network the client is connected to. We
4311 * must not respond if we don't have any information about the
4312 * network the client is on.
4315 if ((shared_network_from_packet6(&shared
, packet
) != ISC_R_SUCCESS
) ||
4319 /* If there are no recorded subnets, then we have no
4320 * information about this subnet - ignore Confirms.
4322 subnet
= shared
->subnets
;
4326 /* Are the addresses in all the IA's appropriate for that link? */
4327 has_addrs
= inappropriate
= ISC_FALSE
;
4329 while(!inappropriate
) {
4330 /* If we've reached the end of the IA_NA pass, move to the
4333 if ((pass
== D6O_IA_NA
) && (ia
== NULL
)) {
4338 /* If we've reached the end of all passes, we're done. */
4342 if (((pass
== D6O_IA_NA
) &&
4343 !get_encapsulated_IA_state(&cli_enc_opt_state
,
4345 packet
, ia
, IA_NA_OFFSET
)) ||
4346 ((pass
== D6O_IA_TA
) &&
4347 !get_encapsulated_IA_state(&cli_enc_opt_state
,
4349 packet
, ia
, IA_TA_OFFSET
))) {
4353 oc
= lookup_option(&dhcpv6_universe
, cli_enc_opt_state
,
4356 for ( ; oc
!= NULL
; oc
= oc
->next
) {
4357 if (!evaluate_option_cache(&iaaddr
, packet
, NULL
, NULL
,
4358 packet
->options
, NULL
,
4359 &global_scope
, oc
, MDL
) ||
4360 (iaaddr
.len
< IAADDR_OFFSET
)) {
4361 log_error("dhcpv6_confirm: "
4362 "error evaluating IAADDR.");
4366 /* Copy out the IPv6 address for processing. */
4368 memcpy(cli_addr
.iabuf
, iaaddr
.data
, 16);
4370 data_string_forget(&iaaddr
, MDL
);
4372 /* Record that we've processed at least one address. */
4373 has_addrs
= ISC_TRUE
;
4375 /* Find out if any subnets cover this address. */
4376 for (subnet
= shared
->subnets
; subnet
!= NULL
;
4377 subnet
= subnet
->next_sibling
) {
4378 if (addr_eq(subnet_number(cli_addr
,
4384 /* If we reach the end of the subnet list, and no
4385 * subnet matches the client address, then it must
4386 * be inappropriate to the link (so far as our
4387 * configuration says). Once we've found one
4388 * inappropriate address, there is no reason to
4389 * continue searching.
4391 if (subnet
== NULL
) {
4392 inappropriate
= ISC_TRUE
;
4397 option_state_dereference(&cli_enc_opt_state
, MDL
);
4398 data_string_forget(&cli_enc_opt_data
, MDL
);
4400 /* Advance to the next IA_*. */
4404 /* If the client supplied no addresses, do not reply. */
4411 if (!start_reply(packet
, &client_id
, NULL
, &opt_state
, reply
)) {
4418 if (inappropriate
) {
4419 if (!set_status_code(STATUS_NotOnLink
,
4420 "Some of the addresses are not on link.",
4425 if (!set_status_code(STATUS_Success
,
4426 "All addresses still on link.",
4433 * Only one option: add it.
4435 reply_ofs
+= store_options6(reply_data
+reply_ofs
,
4436 sizeof(reply_data
)-reply_ofs
,
4438 required_opts
, &packet_oro
);
4441 * Return our reply to the caller.
4443 reply_ret
->len
= reply_ofs
;
4444 reply_ret
->buffer
= NULL
;
4445 if (!buffer_allocate(&reply_ret
->buffer
, reply_ofs
, MDL
)) {
4446 log_fatal("No memory to store reply.");
4448 reply_ret
->data
= reply_ret
->buffer
->data
;
4449 memcpy(reply_ret
->buffer
->data
, reply
, reply_ofs
);
4452 /* Cleanup any stale data strings. */
4453 if (cli_enc_opt_data
.buffer
!= NULL
)
4454 data_string_forget(&cli_enc_opt_data
, MDL
);
4455 if (iaaddr
.buffer
!= NULL
)
4456 data_string_forget(&iaaddr
, MDL
);
4457 if (client_id
.buffer
!= NULL
)
4458 data_string_forget(&client_id
, MDL
);
4459 if (packet_oro
.buffer
!= NULL
)
4460 data_string_forget(&packet_oro
, MDL
);
4462 /* Release any stale option states. */
4463 if (cli_enc_opt_state
!= NULL
)
4464 option_state_dereference(&cli_enc_opt_state
, MDL
);
4465 if (opt_state
!= NULL
)
4466 option_state_dereference(&opt_state
, MDL
);
4470 * Renew is when a client wants to extend its lease/prefix, at time T1.
4472 * We handle this the same as if the client wants a new lease/prefix,
4473 * except for the error code of when addresses don't match.
4476 /* TODO: reject unicast messages, unless we set unicast option */
4478 dhcpv6_renew(struct data_string
*reply
, struct packet
*packet
) {
4479 struct data_string client_id
;
4480 struct data_string server_id
;
4483 * Validate the request.
4485 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
4492 lease_to_client(reply
, packet
, &client_id
, &server_id
);
4497 data_string_forget(&server_id
, MDL
);
4498 data_string_forget(&client_id
, MDL
);
4502 * Rebind is when a client wants to extend its lease, at time T2.
4504 * We handle this the same as if the client wants a new lease, except
4505 * for the error code of when addresses don't match.
4509 dhcpv6_rebind(struct data_string
*reply
, struct packet
*packet
) {
4510 struct data_string client_id
;
4512 if (!valid_client_msg(packet
, &client_id
)) {
4516 lease_to_client(reply
, packet
, &client_id
, NULL
);
4518 data_string_forget(&client_id
, MDL
);
4522 ia_na_match_decline(const struct data_string
*client_id
,
4523 const struct data_string
*iaaddr
,
4524 struct iasubopt
*lease
)
4526 char tmp_addr
[INET6_ADDRSTRLEN
];
4528 log_error("Client %s reports address %s is "
4529 "already in use by another host!",
4530 print_hex_1(client_id
->len
, client_id
->data
, 60),
4531 inet_ntop(AF_INET6
, iaaddr
->data
,
4532 tmp_addr
, sizeof(tmp_addr
)));
4533 if (lease
!= NULL
) {
4534 decline_lease6(lease
->ipv6_pool
, lease
);
4535 lease
->ia
->cltt
= cur_time
;
4536 write_ia(lease
->ia
);
4541 ia_na_nomatch_decline(const struct data_string
*client_id
,
4542 const struct data_string
*iaaddr
,
4543 u_int32_t
*ia_na_id
,
4544 struct packet
*packet
,
4549 char tmp_addr
[INET6_ADDRSTRLEN
];
4550 struct option_state
*host_opt_state
;
4553 log_info("Client %s declines address %s, which is not offered to it.",
4554 print_hex_1(client_id
->len
, client_id
->data
, 60),
4555 inet_ntop(AF_INET6
, iaaddr
->data
, tmp_addr
, sizeof(tmp_addr
)));
4558 * Create state for this IA_NA.
4560 host_opt_state
= NULL
;
4561 if (!option_state_allocate(&host_opt_state
, MDL
)) {
4562 log_error("ia_na_nomatch_decline: out of memory "
4563 "allocating option_state.");
4567 if (!set_status_code(STATUS_NoBinding
, "Decline for unknown address.",
4573 * Insure we have enough space
4575 if (reply_len
< (*reply_ofs
+ 16)) {
4576 log_error("ia_na_nomatch_decline: "
4577 "out of space for reply packet.");
4582 * Put our status code into the reply packet.
4584 len
= store_options6(reply_data
+(*reply_ofs
)+16,
4585 reply_len
-(*reply_ofs
)-16,
4586 host_opt_state
, packet
,
4587 required_opts_STATUS_CODE
, NULL
);
4590 * Store the non-encapsulated option data for this
4591 * IA_NA into our reply packet. Defined in RFC 3315,
4595 putUShort((unsigned char *)reply_data
+(*reply_ofs
), D6O_IA_NA
);
4597 putUShort((unsigned char *)reply_data
+(*reply_ofs
)+2, len
+ 12);
4598 /* IA_NA, copied from the client */
4599 memcpy(reply_data
+(*reply_ofs
)+4, ia_na_id
, 4);
4600 /* t1 and t2, odd that we need them, but here it is */
4601 putULong((unsigned char *)reply_data
+(*reply_ofs
)+8, 0);
4602 putULong((unsigned char *)reply_data
+(*reply_ofs
)+12, 0);
4605 * Get ready for next IA_NA.
4607 *reply_ofs
+= (len
+ 16);
4610 option_state_dereference(&host_opt_state
, MDL
);
4614 iterate_over_ia_na(struct data_string
*reply_ret
,
4615 struct packet
*packet
,
4616 const struct data_string
*client_id
,
4617 const struct data_string
*server_id
,
4618 const char *packet_type
,
4619 void (*ia_na_match
)(),
4620 void (*ia_na_nomatch
)())
4622 struct option_state
*opt_state
;
4623 struct host_decl
*packet_host
;
4624 struct option_cache
*ia
;
4625 struct option_cache
*oc
;
4626 /* cli_enc_... variables come from the IA_NA/IA_TA options */
4627 struct data_string cli_enc_opt_data
;
4628 struct option_state
*cli_enc_opt_state
;
4629 struct host_decl
*host
;
4630 struct option_state
*host_opt_state
;
4631 struct data_string iaaddr
;
4632 struct data_string fixed_addr
;
4633 char reply_data
[65536];
4634 struct dhcpv6_packet
*reply
= (struct dhcpv6_packet
*)reply_data
;
4635 int reply_ofs
= (int)(offsetof(struct dhcpv6_packet
, options
));
4636 char status_msg
[32];
4637 struct iasubopt
*lease
;
4638 struct ia_xx
*existing_ia_na
;
4640 struct data_string key
;
4644 * Initialize to empty values, in case we have to exit early.
4647 memset(&cli_enc_opt_data
, 0, sizeof(cli_enc_opt_data
));
4648 cli_enc_opt_state
= NULL
;
4649 memset(&iaaddr
, 0, sizeof(iaaddr
));
4650 memset(&fixed_addr
, 0, sizeof(fixed_addr
));
4651 host_opt_state
= NULL
;
4655 * Find the host record that matches from the packet, if any.
4658 if (!find_hosts_by_uid(&packet_host
,
4659 client_id
->data
, client_id
->len
, MDL
)) {
4662 * Note: In general, we don't expect a client to provide
4663 * enough information to match by option for these
4664 * types of messages, but if we don't have a UID
4665 * match we can check anyway.
4667 if (!find_hosts_by_option(&packet_host
,
4668 packet
, packet
->options
, MDL
)) {
4671 if (!find_hosts_by_duid_chaddr(&packet_host
,
4678 * Set our reply information.
4680 reply
->msg_type
= DHCPV6_REPLY
;
4681 memcpy(reply
->transaction_id
, packet
->dhcpv6_transaction_id
,
4682 sizeof(reply
->transaction_id
));
4685 * Build our option state for reply.
4688 if (!option_state_allocate(&opt_state
, MDL
)) {
4689 log_error("iterate_over_ia_na: no memory for option_state.");
4692 execute_statements_in_scope(NULL
, packet
, NULL
, NULL
,
4693 packet
->options
, opt_state
,
4694 &global_scope
, root_group
, NULL
);
4697 * RFC 3315, section 18.2.7 tells us which options to include.
4699 oc
= lookup_option(&dhcpv6_universe
, opt_state
, D6O_SERVERID
);
4701 if (!save_option_buffer(&dhcpv6_universe
, opt_state
, NULL
,
4702 (unsigned char *)server_duid
.data
,
4703 server_duid
.len
, D6O_SERVERID
, 0)) {
4704 log_error("iterate_over_ia_na: "
4705 "error saving server identifier.");
4710 if (!save_option_buffer(&dhcpv6_universe
, opt_state
,
4712 (unsigned char *)client_id
->data
,
4715 log_error("iterate_over_ia_na: "
4716 "error saving client identifier.");
4720 snprintf(status_msg
, sizeof(status_msg
), "%s received.", packet_type
);
4721 if (!set_status_code(STATUS_Success
, status_msg
, opt_state
)) {
4726 * Add our options that are not associated with any IA_NA or IA_TA.
4728 reply_ofs
+= store_options6(reply_data
+reply_ofs
,
4729 sizeof(reply_data
)-reply_ofs
,
4731 required_opts
, NULL
);
4734 * Loop through the IA_NA reported by the client, and deal with
4735 * addresses reported as already in use.
4737 for (ia
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
4738 ia
!= NULL
; ia
= ia
->next
) {
4740 if (!get_encapsulated_IA_state(&cli_enc_opt_state
,
4742 packet
, ia
, IA_NA_OFFSET
)) {
4746 iaid
= getULong(cli_enc_opt_data
.data
);
4749 * XXX: It is possible that we can get multiple addresses
4750 * sent by the client. We don't send multiple
4751 * addresses, so this indicates a client error.
4752 * We should check for multiple IAADDR options, log
4753 * if found, and set as an error.
4755 oc
= lookup_option(&dhcpv6_universe
, cli_enc_opt_state
,
4758 /* no address given for this IA, ignore */
4759 option_state_dereference(&cli_enc_opt_state
, MDL
);
4760 data_string_forget(&cli_enc_opt_data
, MDL
);
4764 memset(&iaaddr
, 0, sizeof(iaaddr
));
4765 if (!evaluate_option_cache(&iaaddr
, packet
, NULL
, NULL
,
4766 packet
->options
, NULL
,
4767 &global_scope
, oc
, MDL
)) {
4768 log_error("iterate_over_ia_na: "
4769 "error evaluating IAADDR.");
4774 * Now we need to figure out which host record matches
4775 * this IA_NA and IAADDR (encapsulated option contents
4776 * matching a host record by option).
4778 * XXX: We don't currently track IA_NA separately, but
4779 * we will need to do this!
4782 if (!find_hosts_by_option(&host
, packet
,
4783 cli_enc_opt_state
, MDL
)) {
4784 if (packet_host
!= NULL
) {
4790 while (host
!= NULL
) {
4791 if (host
->fixed_addr
!= NULL
) {
4792 if (!evaluate_option_cache(&fixed_addr
, NULL
,
4794 NULL
, &global_scope
,
4797 log_error("iterate_over_ia_na: error "
4798 "evaluating host address.");
4801 if ((iaaddr
.len
>= 16) &&
4802 !memcmp(fixed_addr
.data
, iaaddr
.data
, 16)) {
4803 data_string_forget(&fixed_addr
, MDL
);
4806 data_string_forget(&fixed_addr
, MDL
);
4808 host
= host
->n_ipaddr
;
4811 if ((host
== NULL
) && (iaaddr
.len
>= IAADDR_OFFSET
)) {
4813 * Find existing IA_NA.
4815 if (ia_make_key(&key
, iaid
,
4816 (char *)client_id
->data
,
4818 MDL
) != ISC_R_SUCCESS
) {
4819 log_fatal("iterate_over_ia_na: no memory for "
4823 existing_ia_na
= NULL
;
4824 if (ia_hash_lookup(&existing_ia_na
, ia_na_active
,
4825 (unsigned char *)key
.data
,
4828 * Make sure this address is in the IA_NA.
4830 for (i
=0; i
<existing_ia_na
->num_iasubopt
; i
++) {
4831 struct iasubopt
*tmp
;
4832 struct in6_addr
*in6_addr
;
4834 tmp
= existing_ia_na
->iasubopt
[i
];
4835 in6_addr
= &tmp
->addr
;
4836 if (memcmp(in6_addr
,
4837 iaaddr
.data
, 16) == 0) {
4838 iasubopt_reference(&lease
,
4845 data_string_forget(&key
, MDL
);
4848 if ((host
!= NULL
) || (lease
!= NULL
)) {
4849 ia_na_match(client_id
, &iaaddr
, lease
);
4851 ia_na_nomatch(client_id
, &iaaddr
,
4852 (u_int32_t
*)cli_enc_opt_data
.data
,
4853 packet
, reply_data
, &reply_ofs
,
4854 sizeof(reply_data
));
4857 if (lease
!= NULL
) {
4858 iasubopt_dereference(&lease
, MDL
);
4861 data_string_forget(&iaaddr
, MDL
);
4862 option_state_dereference(&cli_enc_opt_state
, MDL
);
4863 data_string_forget(&cli_enc_opt_data
, MDL
);
4867 * Return our reply to the caller.
4869 reply_ret
->len
= reply_ofs
;
4870 reply_ret
->buffer
= NULL
;
4871 if (!buffer_allocate(&reply_ret
->buffer
, reply_ofs
, MDL
)) {
4872 log_fatal("No memory to store reply.");
4874 reply_ret
->data
= reply_ret
->buffer
->data
;
4875 memcpy(reply_ret
->buffer
->data
, reply
, reply_ofs
);
4878 if (lease
!= NULL
) {
4879 iasubopt_dereference(&lease
, MDL
);
4881 if (host_opt_state
!= NULL
) {
4882 option_state_dereference(&host_opt_state
, MDL
);
4884 if (fixed_addr
.buffer
!= NULL
) {
4885 data_string_forget(&fixed_addr
, MDL
);
4887 if (iaaddr
.buffer
!= NULL
) {
4888 data_string_forget(&iaaddr
, MDL
);
4890 if (cli_enc_opt_state
!= NULL
) {
4891 option_state_dereference(&cli_enc_opt_state
, MDL
);
4893 if (cli_enc_opt_data
.buffer
!= NULL
) {
4894 data_string_forget(&cli_enc_opt_data
, MDL
);
4896 if (opt_state
!= NULL
) {
4897 option_state_dereference(&opt_state
, MDL
);
4902 * Decline means a client has detected that something else is using an
4903 * address we gave it.
4905 * Since we're only dealing with fixed leases for now, there's not
4906 * much we can do, other that log the occurrence.
4908 * When we start issuing addresses from pools, then we will have to
4909 * record our declined addresses and issue another. In general with
4910 * IPv6 there is no worry about DoS by clients exhausting space, but
4911 * we still need to be aware of this possibility.
4914 /* TODO: reject unicast messages, unless we set unicast option */
4917 dhcpv6_decline(struct data_string
*reply
, struct packet
*packet
) {
4918 struct data_string client_id
;
4919 struct data_string server_id
;
4922 * Validate our input.
4924 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
4929 * Undefined for IA_PD.
4931 delete_option(&dhcpv6_universe
, packet
->options
, D6O_IA_PD
);
4934 * And operate on each IA_NA in this packet.
4936 iterate_over_ia_na(reply
, packet
, &client_id
, &server_id
, "Decline",
4937 ia_na_match_decline
, ia_na_nomatch_decline
);
4939 data_string_forget(&server_id
, MDL
);
4940 data_string_forget(&client_id
, MDL
);
4944 ia_na_match_release(const struct data_string
*client_id
,
4945 const struct data_string
*iaaddr
,
4946 struct iasubopt
*lease
)
4948 char tmp_addr
[INET6_ADDRSTRLEN
];
4950 log_info("Client %s releases address %s",
4951 print_hex_1(client_id
->len
, client_id
->data
, 60),
4952 inet_ntop(AF_INET6
, iaaddr
->data
, tmp_addr
, sizeof(tmp_addr
)));
4953 if (lease
!= NULL
) {
4954 release_lease6(lease
->ipv6_pool
, lease
);
4955 lease
->ia
->cltt
= cur_time
;
4956 write_ia(lease
->ia
);
4961 ia_na_nomatch_release(const struct data_string
*client_id
,
4962 const struct data_string
*iaaddr
,
4963 u_int32_t
*ia_na_id
,
4964 struct packet
*packet
,
4969 char tmp_addr
[INET6_ADDRSTRLEN
];
4970 struct option_state
*host_opt_state
;
4973 log_info("Client %s releases address %s, which is not leased to it.",
4974 print_hex_1(client_id
->len
, client_id
->data
, 60),
4975 inet_ntop(AF_INET6
, iaaddr
->data
, tmp_addr
, sizeof(tmp_addr
)));
4978 * Create state for this IA_NA.
4980 host_opt_state
= NULL
;
4981 if (!option_state_allocate(&host_opt_state
, MDL
)) {
4982 log_error("ia_na_nomatch_release: out of memory "
4983 "allocating option_state.");
4987 if (!set_status_code(STATUS_NoBinding
,
4988 "Release for non-leased address.",
4994 * Insure we have enough space
4996 if (reply_len
< (*reply_ofs
+ 16)) {
4997 log_error("ia_na_nomatch_release: "
4998 "out of space for reply packet.");
5003 * Put our status code into the reply packet.
5005 len
= store_options6(reply_data
+(*reply_ofs
)+16,
5006 reply_len
-(*reply_ofs
)-16,
5007 host_opt_state
, packet
,
5008 required_opts_STATUS_CODE
, NULL
);
5011 * Store the non-encapsulated option data for this
5012 * IA_NA into our reply packet. Defined in RFC 3315,
5016 putUShort((unsigned char *)reply_data
+(*reply_ofs
), D6O_IA_NA
);
5018 putUShort((unsigned char *)reply_data
+(*reply_ofs
)+2, len
+ 12);
5019 /* IA_NA, copied from the client */
5020 memcpy(reply_data
+(*reply_ofs
)+4, ia_na_id
, 4);
5021 /* t1 and t2, odd that we need them, but here it is */
5022 putULong((unsigned char *)reply_data
+(*reply_ofs
)+8, 0);
5023 putULong((unsigned char *)reply_data
+(*reply_ofs
)+12, 0);
5026 * Get ready for next IA_NA.
5028 *reply_ofs
+= (len
+ 16);
5031 option_state_dereference(&host_opt_state
, MDL
);
5035 ia_pd_match_release(const struct data_string
*client_id
,
5036 const struct data_string
*iapref
,
5037 struct iasubopt
*prefix
)
5039 char tmp_addr
[INET6_ADDRSTRLEN
];
5041 log_info("Client %s releases prefix %s/%u",
5042 print_hex_1(client_id
->len
, client_id
->data
, 60),
5043 inet_ntop(AF_INET6
, iapref
->data
+ 9,
5044 tmp_addr
, sizeof(tmp_addr
)),
5045 (unsigned) getUChar(iapref
->data
+ 8));
5046 if (prefix
!= NULL
) {
5047 release_lease6(prefix
->ipv6_pool
, prefix
);
5048 prefix
->ia
->cltt
= cur_time
;
5049 write_ia(prefix
->ia
);
5054 ia_pd_nomatch_release(const struct data_string
*client_id
,
5055 const struct data_string
*iapref
,
5056 u_int32_t
*ia_pd_id
,
5057 struct packet
*packet
,
5062 char tmp_addr
[INET6_ADDRSTRLEN
];
5063 struct option_state
*host_opt_state
;
5066 log_info("Client %s releases prefix %s/%u, which is not leased to it.",
5067 print_hex_1(client_id
->len
, client_id
->data
, 60),
5068 inet_ntop(AF_INET6
, iapref
->data
+ 9,
5069 tmp_addr
, sizeof(tmp_addr
)),
5070 (unsigned) getUChar(iapref
->data
+ 8));
5073 * Create state for this IA_PD.
5075 host_opt_state
= NULL
;
5076 if (!option_state_allocate(&host_opt_state
, MDL
)) {
5077 log_error("ia_pd_nomatch_release: out of memory "
5078 "allocating option_state.");
5082 if (!set_status_code(STATUS_NoBinding
,
5083 "Release for non-leased prefix.",
5089 * Insure we have enough space
5091 if (reply_len
< (*reply_ofs
+ 16)) {
5092 log_error("ia_pd_nomatch_release: "
5093 "out of space for reply packet.");
5098 * Put our status code into the reply packet.
5100 len
= store_options6(reply_data
+(*reply_ofs
)+16,
5101 reply_len
-(*reply_ofs
)-16,
5102 host_opt_state
, packet
,
5103 required_opts_STATUS_CODE
, NULL
);
5106 * Store the non-encapsulated option data for this
5107 * IA_PD into our reply packet. Defined in RFC 3315,
5111 putUShort((unsigned char *)reply_data
+(*reply_ofs
), D6O_IA_PD
);
5113 putUShort((unsigned char *)reply_data
+(*reply_ofs
)+2, len
+ 12);
5114 /* IA_PD, copied from the client */
5115 memcpy(reply_data
+(*reply_ofs
)+4, ia_pd_id
, 4);
5116 /* t1 and t2, odd that we need them, but here it is */
5117 putULong((unsigned char *)reply_data
+(*reply_ofs
)+8, 0);
5118 putULong((unsigned char *)reply_data
+(*reply_ofs
)+12, 0);
5121 * Get ready for next IA_PD.
5123 *reply_ofs
+= (len
+ 16);
5126 option_state_dereference(&host_opt_state
, MDL
);
5130 iterate_over_ia_pd(struct data_string
*reply_ret
,
5131 struct packet
*packet
,
5132 const struct data_string
*client_id
,
5133 const struct data_string
*server_id
,
5134 const char *packet_type
,
5135 void (*ia_pd_match
)(),
5136 void (*ia_pd_nomatch
)())
5138 struct data_string reply_new
;
5140 struct option_state
*opt_state
;
5141 struct host_decl
*packet_host
;
5142 struct option_cache
*ia
;
5143 struct option_cache
*oc
;
5144 /* cli_enc_... variables come from the IA_PD options */
5145 struct data_string cli_enc_opt_data
;
5146 struct option_state
*cli_enc_opt_state
;
5147 struct host_decl
*host
;
5148 struct option_state
*host_opt_state
;
5149 struct data_string iaprefix
;
5150 char reply_data
[65536];
5152 struct iasubopt
*prefix
;
5153 struct ia_xx
*existing_ia_pd
;
5155 struct data_string key
;
5159 * Initialize to empty values, in case we have to exit early.
5161 memset(&reply_new
, 0, sizeof(reply_new
));
5163 memset(&cli_enc_opt_data
, 0, sizeof(cli_enc_opt_data
));
5164 cli_enc_opt_state
= NULL
;
5165 memset(&iaprefix
, 0, sizeof(iaprefix
));
5166 host_opt_state
= NULL
;
5170 * Compute the available length for the reply.
5172 reply_len
= sizeof(reply_data
) - reply_ret
->len
;
5176 * Find the host record that matches from the packet, if any.
5179 if (!find_hosts_by_uid(&packet_host
,
5180 client_id
->data
, client_id
->len
, MDL
)) {
5183 * Note: In general, we don't expect a client to provide
5184 * enough information to match by option for these
5185 * types of messages, but if we don't have a UID
5186 * match we can check anyway.
5188 if (!find_hosts_by_option(&packet_host
,
5189 packet
, packet
->options
, MDL
)) {
5192 if (!find_hosts_by_duid_chaddr(&packet_host
,
5199 * Build our option state for reply.
5202 if (!option_state_allocate(&opt_state
, MDL
)) {
5203 log_error("iterate_over_ia_pd: no memory for option_state.");
5206 execute_statements_in_scope(NULL
, packet
, NULL
, NULL
,
5207 packet
->options
, opt_state
,
5208 &global_scope
, root_group
, NULL
);
5211 * Loop through the IA_PD reported by the client, and deal with
5212 * prefixes reported as already in use.
5214 for (ia
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_PD
);
5215 ia
!= NULL
; ia
= ia
->next
) {
5217 if (!get_encapsulated_IA_state(&cli_enc_opt_state
,
5219 packet
, ia
, IA_PD_OFFSET
)) {
5223 iaid
= getULong(cli_enc_opt_data
.data
);
5225 oc
= lookup_option(&dhcpv6_universe
, cli_enc_opt_state
,
5228 /* no prefix given for this IA_PD, ignore */
5229 option_state_dereference(&cli_enc_opt_state
, MDL
);
5230 data_string_forget(&cli_enc_opt_data
, MDL
);
5234 for (; oc
!= NULL
; oc
= oc
->next
) {
5235 memset(&iaprefix
, 0, sizeof(iaprefix
));
5236 if (!evaluate_option_cache(&iaprefix
, packet
, NULL
, NULL
,
5237 packet
->options
, NULL
,
5238 &global_scope
, oc
, MDL
)) {
5239 log_error("iterate_over_ia_pd: "
5240 "error evaluating IAPREFIX.");
5245 * Now we need to figure out which host record matches
5246 * this IA_PD and IAPREFIX (encapsulated option contents
5247 * matching a host record by option).
5249 * XXX: We don't currently track IA_PD separately, but
5250 * we will need to do this!
5253 if (!find_hosts_by_option(&host
, packet
,
5254 cli_enc_opt_state
, MDL
)) {
5255 if (packet_host
!= NULL
) {
5261 while (host
!= NULL
) {
5262 if (host
->fixed_prefix
!= NULL
) {
5263 struct iaddrcidrnetlist
*l
;
5264 int plen
= (int) getUChar(iaprefix
.data
+ 8);
5266 for (l
= host
->fixed_prefix
; l
!= NULL
;
5268 if (plen
!= l
->cidrnet
.bits
)
5270 if (memcmp(iaprefix
.data
+ 9,
5271 l
->cidrnet
.lo_addr
.iabuf
,
5275 if ((l
!= NULL
) && (iaprefix
.len
>= 17))
5278 host
= host
->n_ipaddr
;
5281 if ((host
== NULL
) && (iaprefix
.len
>= IAPREFIX_OFFSET
)) {
5283 * Find existing IA_PD.
5285 if (ia_make_key(&key
, iaid
,
5286 (char *)client_id
->data
,
5288 MDL
) != ISC_R_SUCCESS
) {
5289 log_fatal("iterate_over_ia_pd: no memory for "
5293 existing_ia_pd
= NULL
;
5294 if (ia_hash_lookup(&existing_ia_pd
, ia_pd_active
,
5295 (unsigned char *)key
.data
,
5298 * Make sure this prefix is in the IA_PD.
5301 i
< existing_ia_pd
->num_iasubopt
;
5303 struct iasubopt
*tmp
;
5306 plen
= getUChar(iaprefix
.data
+ 8);
5307 tmp
= existing_ia_pd
->iasubopt
[i
];
5308 if ((tmp
->plen
== plen
) &&
5312 iasubopt_reference(&prefix
,
5319 data_string_forget(&key
, MDL
);
5322 if ((host
!= NULL
) || (prefix
!= NULL
)) {
5323 ia_pd_match(client_id
, &iaprefix
, prefix
);
5325 ia_pd_nomatch(client_id
, &iaprefix
,
5326 (u_int32_t
*)cli_enc_opt_data
.data
,
5327 packet
, reply_data
, &reply_ofs
,
5328 reply_len
- reply_ofs
);
5331 if (prefix
!= NULL
) {
5332 iasubopt_dereference(&prefix
, MDL
);
5335 data_string_forget(&iaprefix
, MDL
);
5338 option_state_dereference(&cli_enc_opt_state
, MDL
);
5339 data_string_forget(&cli_enc_opt_data
, MDL
);
5343 * Return our reply to the caller.
5344 * The IA_NA routine has already filled at least the header.
5346 reply_new
.len
= reply_ret
->len
+ reply_ofs
;
5347 if (!buffer_allocate(&reply_new
.buffer
, reply_new
.len
, MDL
)) {
5348 log_fatal("No memory to store reply.");
5350 reply_new
.data
= reply_new
.buffer
->data
;
5351 memcpy(reply_new
.buffer
->data
,
5352 reply_ret
->buffer
->data
, reply_ret
->len
);
5353 memcpy(reply_new
.buffer
->data
+ reply_ret
->len
,
5354 reply_data
, reply_ofs
);
5355 data_string_forget(reply_ret
, MDL
);
5356 data_string_copy(reply_ret
, &reply_new
, MDL
);
5357 data_string_forget(&reply_new
, MDL
);
5360 if (prefix
!= NULL
) {
5361 iasubopt_dereference(&prefix
, MDL
);
5363 if (host_opt_state
!= NULL
) {
5364 option_state_dereference(&host_opt_state
, MDL
);
5366 if (iaprefix
.buffer
!= NULL
) {
5367 data_string_forget(&iaprefix
, MDL
);
5369 if (cli_enc_opt_state
!= NULL
) {
5370 option_state_dereference(&cli_enc_opt_state
, MDL
);
5372 if (cli_enc_opt_data
.buffer
!= NULL
) {
5373 data_string_forget(&cli_enc_opt_data
, MDL
);
5375 if (opt_state
!= NULL
) {
5376 option_state_dereference(&opt_state
, MDL
);
5381 * Release means a client is done with the leases.
5384 /* TODO: reject unicast messages, unless we set unicast option */
5386 dhcpv6_release(struct data_string
*reply
, struct packet
*packet
) {
5387 struct data_string client_id
;
5388 struct data_string server_id
;
5391 * Validate our input.
5393 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
5398 * And operate on each IA_NA in this packet.
5400 iterate_over_ia_na(reply
, packet
, &client_id
, &server_id
, "Release",
5401 ia_na_match_release
, ia_na_nomatch_release
);
5404 * And operate on each IA_PD in this packet.
5406 iterate_over_ia_pd(reply
, packet
, &client_id
, &server_id
, "Release",
5407 ia_pd_match_release
, ia_pd_nomatch_release
);
5409 data_string_forget(&server_id
, MDL
);
5410 data_string_forget(&client_id
, MDL
);
5414 * Information-Request is used by clients who have obtained an address
5415 * from other means, but want configuration information from the server.
5419 dhcpv6_information_request(struct data_string
*reply
, struct packet
*packet
) {
5420 struct data_string client_id
;
5421 struct data_string server_id
;
5424 * Validate our input.
5426 if (!valid_client_info_req(packet
, &server_id
)) {
5431 * Get our client ID, if there is one.
5433 memset(&client_id
, 0, sizeof(client_id
));
5434 if (get_client_id(packet
, &client_id
) != ISC_R_SUCCESS
) {
5435 data_string_forget(&client_id
, MDL
);
5439 * Use the lease_to_client() function. This will work fine,
5440 * because the valid_client_info_req() insures that we
5441 * don't have any IA that would cause us to allocate
5442 * resources to the client.
5444 lease_to_client(reply
, packet
, &client_id
,
5445 server_id
.data
!= NULL
? &server_id
: NULL
);
5450 if (client_id
.data
!= NULL
) {
5451 data_string_forget(&client_id
, MDL
);
5453 data_string_forget(&server_id
, MDL
);
5457 * The Relay-forw message is sent by relays. It typically contains a
5458 * single option, which encapsulates an entire packet.
5460 * We need to build an encapsulated reply.
5463 /* XXX: this is very, very similar to do_packet6(), and should probably
5464 be combined in a clever way */
5466 dhcpv6_relay_forw(struct data_string
*reply_ret
, struct packet
*packet
) {
5467 struct option_cache
*oc
;
5468 struct data_string enc_opt_data
;
5469 struct packet
*enc_packet
;
5470 unsigned char msg_type
;
5471 const struct dhcpv6_packet
*msg
;
5472 const struct dhcpv6_relay_packet
*relay
;
5473 struct data_string enc_reply
;
5474 char link_addr
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5475 char peer_addr
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5476 struct data_string a_opt
, packet_ero
;
5477 struct option_state
*opt_state
;
5478 static char reply_data
[65536];
5479 struct dhcpv6_relay_packet
*reply
;
5483 * Initialize variables for early exit.
5486 memset(&a_opt
, 0, sizeof(a_opt
));
5487 memset(&packet_ero
, 0, sizeof(packet_ero
));
5488 memset(&enc_reply
, 0, sizeof(enc_reply
));
5489 memset(&enc_opt_data
, 0, sizeof(enc_opt_data
));
5493 * Get our encapsulated relay message.
5495 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_RELAY_MSG
);
5497 inet_ntop(AF_INET6
, &packet
->dhcpv6_link_address
,
5498 link_addr
, sizeof(link_addr
));
5499 inet_ntop(AF_INET6
, &packet
->dhcpv6_peer_address
,
5500 peer_addr
, sizeof(peer_addr
));
5501 log_info("Relay-forward from %s with link address=%s and "
5502 "peer address=%s missing Relay Message option.",
5503 piaddr(packet
->client_addr
), link_addr
, peer_addr
);
5507 if (!evaluate_option_cache(&enc_opt_data
, NULL
, NULL
, NULL
,
5508 NULL
, NULL
, &global_scope
, oc
, MDL
)) {
5509 log_error("dhcpv6_forw_relay: error evaluating "
5510 "relayed message.");
5514 if (!packet6_len_okay((char *)enc_opt_data
.data
, enc_opt_data
.len
)) {
5515 log_error("dhcpv6_forw_relay: encapsulated packet too short.");
5520 * Build a packet structure from this encapsulated packet.
5523 if (!packet_allocate(&enc_packet
, MDL
)) {
5524 log_error("dhcpv6_forw_relay: "
5525 "no memory for encapsulated packet.");
5529 if (!option_state_allocate(&enc_packet
->options
, MDL
)) {
5530 log_error("dhcpv6_forw_relay: "
5531 "no memory for encapsulated packet's options.");
5535 enc_packet
->client_port
= packet
->client_port
;
5536 enc_packet
->client_addr
= packet
->client_addr
;
5537 interface_reference(&enc_packet
->interface
, packet
->interface
, MDL
);
5538 enc_packet
->dhcpv6_container_packet
= packet
;
5540 msg_type
= enc_opt_data
.data
[0];
5541 if ((msg_type
== DHCPV6_RELAY_FORW
) ||
5542 (msg_type
== DHCPV6_RELAY_REPL
)) {
5543 int relaylen
= (int)(offsetof(struct dhcpv6_relay_packet
, options
));
5544 relay
= (struct dhcpv6_relay_packet
*)enc_opt_data
.data
;
5545 enc_packet
->dhcpv6_msg_type
= relay
->msg_type
;
5547 /* relay-specific data */
5548 enc_packet
->dhcpv6_hop_count
= relay
->hop_count
;
5549 memcpy(&enc_packet
->dhcpv6_link_address
,
5550 relay
->link_address
, sizeof(relay
->link_address
));
5551 memcpy(&enc_packet
->dhcpv6_peer_address
,
5552 relay
->peer_address
, sizeof(relay
->peer_address
));
5554 if (!parse_option_buffer(enc_packet
->options
,
5556 enc_opt_data
.len
- relaylen
,
5557 &dhcpv6_universe
)) {
5558 /* no logging here, as parse_option_buffer() logs all
5559 cases where it fails */
5563 int msglen
= (int)(offsetof(struct dhcpv6_packet
, options
));
5564 msg
= (struct dhcpv6_packet
*)enc_opt_data
.data
;
5565 enc_packet
->dhcpv6_msg_type
= msg
->msg_type
;
5567 /* message-specific data */
5568 memcpy(enc_packet
->dhcpv6_transaction_id
,
5569 msg
->transaction_id
,
5570 sizeof(enc_packet
->dhcpv6_transaction_id
));
5572 if (!parse_option_buffer(enc_packet
->options
,
5574 enc_opt_data
.len
- msglen
,
5575 &dhcpv6_universe
)) {
5576 /* no logging here, as parse_option_buffer() logs all
5577 cases where it fails */
5583 * This is recursive. It is possible to exceed maximum packet size.
5584 * XXX: This will cause the packet send to fail.
5586 build_dhcpv6_reply(&enc_reply
, enc_packet
);
5589 * If we got no encapsulated data, then it is discarded, and
5590 * our reply-forw is also discarded.
5592 if (enc_reply
.data
== NULL
) {
5597 * Now we can use the reply_data buffer.
5598 * Packet header stuff all comes from the forward message.
5600 reply
= (struct dhcpv6_relay_packet
*)reply_data
;
5601 reply
->msg_type
= DHCPV6_RELAY_REPL
;
5602 reply
->hop_count
= packet
->dhcpv6_hop_count
;
5603 memcpy(reply
->link_address
, &packet
->dhcpv6_link_address
,
5604 sizeof(reply
->link_address
));
5605 memcpy(reply
->peer_address
, &packet
->dhcpv6_peer_address
,
5606 sizeof(reply
->peer_address
));
5607 reply_ofs
= (int)(offsetof(struct dhcpv6_relay_packet
, options
));
5610 * Get the reply option state.
5613 if (!option_state_allocate(&opt_state
, MDL
)) {
5614 log_error("dhcpv6_relay_forw: no memory for option state.");
5619 * Append the interface-id if present.
5621 oc
= lookup_option(&dhcpv6_universe
, packet
->options
,
5624 if (!evaluate_option_cache(&a_opt
, packet
,
5626 packet
->options
, NULL
,
5627 &global_scope
, oc
, MDL
)) {
5628 log_error("dhcpv6_relay_forw: error evaluating "
5632 if (!save_option_buffer(&dhcpv6_universe
, opt_state
, NULL
,
5633 (unsigned char *)a_opt
.data
,
5635 D6O_INTERFACE_ID
, 0)) {
5636 log_error("dhcpv6_relay_forw: error saving "
5640 data_string_forget(&a_opt
, MDL
);
5644 * Append our encapsulated stuff for caller.
5646 if (!save_option_buffer(&dhcpv6_universe
, opt_state
, NULL
,
5647 (unsigned char *)enc_reply
.data
,
5649 D6O_RELAY_MSG
, 0)) {
5650 log_error("dhcpv6_relay_forw: error saving Relay MSG.");
5655 * Get the ERO if any.
5657 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_ERO
);
5662 if (!evaluate_option_cache(&packet_ero
, packet
,
5664 packet
->options
, NULL
,
5665 &global_scope
, oc
, MDL
) ||
5666 (packet_ero
.len
& 1)) {
5667 log_error("dhcpv6_relay_forw: error evaluating ERO.");
5671 /* Decode and apply the ERO. */
5672 for (i
= 0; i
< packet_ero
.len
; i
+= 2) {
5673 req
= getUShort(packet_ero
.data
+ i
);
5674 /* Already in the reply? */
5675 oc
= lookup_option(&dhcpv6_universe
, opt_state
, req
);
5678 /* Get it from the packet if present. */
5679 oc
= lookup_option(&dhcpv6_universe
,
5684 if (!evaluate_option_cache(&a_opt
, packet
,
5686 packet
->options
, NULL
,
5687 &global_scope
, oc
, MDL
)) {
5688 log_error("dhcpv6_relay_forw: error "
5689 "evaluating option %u.", req
);
5692 if (!save_option_buffer(&dhcpv6_universe
,
5695 (unsigned char *)a_opt
.data
,
5699 log_error("dhcpv6_relay_forw: error saving "
5703 data_string_forget(&a_opt
, MDL
);
5707 reply_ofs
+= store_options6(reply_data
+ reply_ofs
,
5708 sizeof(reply_data
) - reply_ofs
,
5710 required_opts_agent
, &packet_ero
);
5713 * Return our reply to the caller.
5715 reply_ret
->len
= reply_ofs
;
5716 reply_ret
->buffer
= NULL
;
5717 if (!buffer_allocate(&reply_ret
->buffer
, reply_ret
->len
, MDL
)) {
5718 log_fatal("No memory to store reply.");
5720 reply_ret
->data
= reply_ret
->buffer
->data
;
5721 memcpy(reply_ret
->buffer
->data
, reply_data
, reply_ofs
);
5724 if (opt_state
!= NULL
)
5725 option_state_dereference(&opt_state
, MDL
);
5726 if (a_opt
.data
!= NULL
) {
5727 data_string_forget(&a_opt
, MDL
);
5729 if (packet_ero
.data
!= NULL
) {
5730 data_string_forget(&packet_ero
, MDL
);
5732 if (enc_reply
.data
!= NULL
) {
5733 data_string_forget(&enc_reply
, MDL
);
5735 if (enc_opt_data
.data
!= NULL
) {
5736 data_string_forget(&enc_opt_data
, MDL
);
5738 if (enc_packet
!= NULL
) {
5739 packet_dereference(&enc_packet
, MDL
);
5744 dhcpv6_discard(struct packet
*packet
) {
5745 /* INSIST(packet->msg_type > 0); */
5746 /* INSIST(packet->msg_type < dhcpv6_type_name_max); */
5748 log_debug("Discarding %s from %s; message type not handled by server",
5749 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
5750 piaddr(packet
->client_addr
));
5754 build_dhcpv6_reply(struct data_string
*reply
, struct packet
*packet
) {
5755 memset(reply
, 0, sizeof(*reply
));
5756 switch (packet
->dhcpv6_msg_type
) {
5757 case DHCPV6_SOLICIT
:
5758 dhcpv6_solicit(reply
, packet
);
5760 case DHCPV6_ADVERTISE
:
5761 dhcpv6_discard(packet
);
5763 case DHCPV6_REQUEST
:
5764 dhcpv6_request(reply
, packet
);
5766 case DHCPV6_CONFIRM
:
5767 dhcpv6_confirm(reply
, packet
);
5770 dhcpv6_renew(reply
, packet
);
5773 dhcpv6_rebind(reply
, packet
);
5776 dhcpv6_discard(packet
);
5778 case DHCPV6_RELEASE
:
5779 dhcpv6_release(reply
, packet
);
5781 case DHCPV6_DECLINE
:
5782 dhcpv6_decline(reply
, packet
);
5784 case DHCPV6_RECONFIGURE
:
5785 dhcpv6_discard(packet
);
5787 case DHCPV6_INFORMATION_REQUEST
:
5788 dhcpv6_information_request(reply
, packet
);
5790 case DHCPV6_RELAY_FORW
:
5791 dhcpv6_relay_forw(reply
, packet
);
5793 case DHCPV6_RELAY_REPL
:
5794 dhcpv6_discard(packet
);
5796 case DHCPV6_LEASEQUERY
:
5797 dhcpv6_leasequery(reply
, packet
);
5799 case DHCPV6_LEASEQUERY_REPLY
:
5800 dhcpv6_discard(packet
);
5803 /* XXX: would be nice if we had "notice" level,
5804 as syslog, for this */
5805 log_info("Discarding unknown DHCPv6 message type %d "
5806 "from %s", packet
->dhcpv6_msg_type
,
5807 piaddr(packet
->client_addr
));
5812 log_packet_in(const struct packet
*packet
) {
5813 struct data_string s
;
5815 char tmp_addr
[INET6_ADDRSTRLEN
];
5818 memset(&s
, 0, sizeof(s
));
5820 if (packet
->dhcpv6_msg_type
< dhcpv6_type_name_max
) {
5821 data_string_sprintfa(&s
, "%s message from %s port %d",
5822 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
5823 piaddr(packet
->client_addr
),
5824 ntohs(packet
->client_port
));
5826 data_string_sprintfa(&s
,
5827 "Unknown message type %d from %s port %d",
5828 packet
->dhcpv6_msg_type
,
5829 piaddr(packet
->client_addr
),
5830 ntohs(packet
->client_port
));
5832 if ((packet
->dhcpv6_msg_type
== DHCPV6_RELAY_FORW
) ||
5833 (packet
->dhcpv6_msg_type
== DHCPV6_RELAY_REPL
)) {
5834 addr
= &packet
->dhcpv6_link_address
;
5835 data_string_sprintfa(&s
, ", link address %s",
5836 inet_ntop(AF_INET6
, addr
,
5837 tmp_addr
, sizeof(tmp_addr
)));
5838 addr
= &packet
->dhcpv6_peer_address
;
5839 data_string_sprintfa(&s
, ", peer address %s",
5840 inet_ntop(AF_INET6
, addr
,
5841 tmp_addr
, sizeof(tmp_addr
)));
5844 memcpy(((char *)&tid
)+1, packet
->dhcpv6_transaction_id
, 3);
5845 data_string_sprintfa(&s
, ", transaction ID 0x%06X", tid
);
5848 oc = lookup_option(&dhcpv6_universe, packet->options,
5851 memset(&tmp_ds, 0, sizeof(tmp_ds_));
5852 if (!evaluate_option_cache(&tmp_ds, packet, NULL, NULL,
5853 packet->options, NULL,
5854 &global_scope, oc, MDL)) {
5855 log_error("Error evaluating Client Identifier");
5857 data_strint_sprintf(&s, ", client ID %s",
5859 data_string_forget(&tmp_ds, MDL);
5865 log_info("%s", s
.data
);
5867 data_string_forget(&s
, MDL
);
5871 dhcpv6(struct packet
*packet
) {
5872 struct data_string reply
;
5873 struct sockaddr_in6 to_addr
;
5877 * Log a message that we received this packet.
5879 log_packet_in(packet
);
5882 * Build our reply packet.
5884 build_dhcpv6_reply(&reply
, packet
);
5886 if (reply
.data
!= NULL
) {
5888 * Send our reply, if we have one.
5890 memset(&to_addr
, 0, sizeof(to_addr
));
5891 to_addr
.sin6_family
= AF_INET6
;
5892 if ((packet
->dhcpv6_msg_type
== DHCPV6_RELAY_FORW
) ||
5893 (packet
->dhcpv6_msg_type
== DHCPV6_RELAY_REPL
)) {
5894 to_addr
.sin6_port
= local_port
;
5896 to_addr
.sin6_port
= remote_port
;
5899 #if defined (REPLY_TO_SOURCE_PORT)
5901 * This appears to have been included for testing so we would
5902 * not need a root client, but was accidently left in the
5903 * final code. We continue to include it in case
5904 * some users have come to rely upon it, but leave
5905 * it off by default as it's a bad idea.
5907 to_addr
.sin6_port
= packet
->client_port
;
5910 memcpy(&to_addr
.sin6_addr
, packet
->client_addr
.iabuf
,
5911 sizeof(to_addr
.sin6_addr
));
5913 log_info("Sending %s to %s port %d",
5914 dhcpv6_type_names
[reply
.data
[0]],
5915 piaddr(packet
->client_addr
),
5916 ntohs(to_addr
.sin6_port
));
5918 send_ret
= send_packet6(packet
->interface
,
5919 reply
.data
, reply
.len
, &to_addr
);
5920 if (send_ret
!= reply
.len
) {
5921 log_error("dhcpv6: send_packet6() sent %d of %d bytes",
5922 send_ret
, reply
.len
);
5924 data_string_forget(&reply
, MDL
);
5929 seek_shared_host(struct host_decl
**hp
, struct shared_network
*shared
) {
5930 struct host_decl
*nofixed
= NULL
;
5931 struct host_decl
*seek
, *hold
= NULL
;
5934 * Seek forward through fixed addresses for the right link.
5936 * Note: how to do this for fixed prefixes???
5938 host_reference(&hold
, *hp
, MDL
);
5939 host_dereference(hp
, MDL
);
5941 while (seek
!= NULL
) {
5942 if (seek
->fixed_addr
== NULL
)
5944 else if (fixed_matches_shared(seek
, shared
))
5947 seek
= seek
->n_ipaddr
;
5950 if ((seek
== NULL
) && (nofixed
!= NULL
))
5954 host_reference(hp
, seek
, MDL
);
5957 static isc_boolean_t
5958 fixed_matches_shared(struct host_decl
*host
, struct shared_network
*shared
) {
5959 struct subnet
*subnet
;
5960 struct data_string addr
;
5961 isc_boolean_t matched
;
5964 if (host
->fixed_addr
== NULL
)
5967 memset(&addr
, 0, sizeof(addr
));
5968 if (!evaluate_option_cache(&addr
, NULL
, NULL
, NULL
, NULL
, NULL
,
5969 &global_scope
, host
->fixed_addr
, MDL
))
5972 if (addr
.len
< 16) {
5973 data_string_forget(&addr
, MDL
);
5978 memcpy(fixed
.iabuf
, addr
.data
, 16);
5980 matched
= ISC_FALSE
;
5981 for (subnet
= shared
->subnets
; subnet
!= NULL
;
5982 subnet
= subnet
->next_sibling
) {
5983 if (addr_eq(subnet_number(fixed
, subnet
->netmask
),
5990 data_string_forget(&addr
, MDL
);
5995 * find_host_by_duid_chaddr() synthesizes a DHCPv4-like 'hardware'
5996 * parameter from a DHCPv6 supplied DUID (client-identifier option),
5997 * and may seek to use client or relay supplied hardware addresses.
6000 find_hosts_by_duid_chaddr(struct host_decl
**host
,
6001 const struct data_string
*client_id
) {
6002 static int once_htype
;
6004 const unsigned char *chaddr
;
6007 * The DUID-LL and DUID-LLT must have a 2-byte DUID type and 2-byte
6010 if (client_id
->len
< 4)
6014 * The third and fourth octets of the DUID-LL and DUID-LLT
6015 * is the hardware type, but in 16 bits.
6017 htype
= getUShort(client_id
->data
+ 2);
6021 /* The first two octets of the DUID identify the type. */
6022 switch(getUShort(client_id
->data
)) {
6024 if (client_id
->len
> 8) {
6025 hlen
= client_id
->len
- 8;
6026 chaddr
= client_id
->data
+ 8;
6032 * Note that client_id->len must be greater than or equal
6033 * to four to get to this point in the function.
6035 hlen
= client_id
->len
- 4;
6036 chaddr
= client_id
->data
+ 4;
6043 if ((hlen
== 0) || (hlen
> HARDWARE_ADDR_LEN
))
6047 * XXX: DHCPv6 gives a 16-bit field for the htype. DHCPv4 gives an
6048 * 8-bit field. To change the semantics of the generic 'hardware'
6049 * structure, we would have to adjust many DHCPv4 sources (from
6050 * interface to DHCPv4 lease code), and we would have to update the
6051 * 'hardware' config directive (probably being reverse compatible and
6052 * providing a new upgrade/replacement primitive). This is a little
6053 * too much to change for now. Hopefully we will revisit this before
6054 * hardware types exceeding 8 bits are assigned.
6056 if ((htype
& 0xFF00) && !once_htype
) {
6058 log_error("Attention: At least one client advertises a "
6059 "hardware type of %d, which exceeds the software "
6060 "limitation of 255.", htype
);
6063 return find_hosts_by_haddr(host
, htype
, chaddr
, hlen
, MDL
);