2 * Copyright (C) 2006-2008 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 option_state
*opt_state
;
47 struct packet
*packet
;
48 struct data_string client_id
;
50 /* IA level persistent state */
52 unsigned client_resources
;
53 isc_boolean_t ia_addrs_included
;
54 isc_boolean_t static_lease
;
56 struct ia_na
*old_ia_na
;
57 struct option_state
*reply_ia
;
58 struct data_string fixed
;
60 /* IAADDR level persistent state */
64 * "t1", "t2", preferred, and valid lifetimes records for calculating
65 * t1 and t2 (min/max).
67 u_int32_t renew
, rebind
, prefer
, valid
;
69 /* Client-requested valid and preferred lifetimes. */
70 u_int32_t client_valid
, client_prefer
;
72 /* Chosen values to transmit for valid and preferred lifetimes. */
73 u_int32_t send_valid
, send_prefer
;
75 /* Index into the data field that has been consumed. */
79 unsigned char data
[65536];
80 struct dhcpv6_packet reply
;
85 * Prototypes local to this file.
87 static int get_encapsulated_IA_state(struct option_state
**enc_opt_state
,
88 struct data_string
*enc_opt_data
,
89 struct packet
*packet
,
90 struct option_cache
*oc
,
92 static void build_dhcpv6_reply(struct data_string
*, struct packet
*);
93 static isc_result_t
shared_network_from_packet6(struct shared_network
**shared
,
94 struct packet
*packet
);
95 static void seek_shared_host(struct host_decl
**hp
,
96 struct shared_network
*shared
);
97 static isc_boolean_t
fixed_matches_shared(struct host_decl
*host
,
98 struct shared_network
*shared
);
99 static isc_result_t
reply_process_ia_na(struct reply_state
*reply
,
100 struct option_cache
*ia
);
101 static isc_result_t
reply_process_addr(struct reply_state
*reply
,
102 struct option_cache
*addr
);
103 static isc_boolean_t
address_is_owned(struct reply_state
*reply
,
105 static isc_result_t
reply_process_try_addr(struct reply_state
*reply
,
107 static isc_result_t
find_client_address(struct reply_state
*reply
);
108 static isc_result_t
reply_process_is_addressed(struct reply_state
*reply
,
109 struct binding_scope
**scope
,
110 struct group
*group
);
111 static isc_result_t
reply_process_send_addr(struct reply_state
*reply
,
113 static struct iaaddr
*lease_compare(struct iaaddr
*alpha
, struct iaaddr
*beta
);
116 * This function returns the time since DUID time start for the
117 * given time_t value.
120 duid_time(time_t when
) {
122 * This time is modulo 2^32.
124 while ((when
- DUID_TIME_EPOCH
) > 4294967295u) {
125 /* use 2^31 to avoid spurious compiler warnings */
130 return when
- DUID_TIME_EPOCH
;
137 * This must remain the same for the lifetime of this server, because
138 * clients return the server DUID that we sent them in Request packets.
140 * We pick the server DUID like this:
142 * 1. Check dhcpd.conf - any value the administrator has configured
143 * overrides any possible values.
144 * 2. Check the leases.txt - we want to use the previous value if
146 * 3. Check if dhcpd.conf specifies a type of server DUID to use,
147 * and generate that type.
148 * 4. Generate a type 1 (time + hardware address) DUID.
150 static struct data_string server_duid
;
153 * Check if the server_duid has been set.
156 server_duid_isset(void) {
157 return (server_duid
.data
!= NULL
);
161 * Return the server_duid.
164 copy_server_duid(struct data_string
*ds
, const char *file
, int line
) {
165 data_string_copy(ds
, &server_duid
, file
, line
);
169 * Set the server DUID to a specified value. This is used when
170 * the server DUID is stored in persistent memory (basically the
174 set_server_duid(struct data_string
*new_duid
) {
175 /* INSIST(new_duid != NULL); */
176 /* INSIST(new_duid->data != NULL); */
178 if (server_duid_isset()) {
179 data_string_forget(&server_duid
, MDL
);
181 data_string_copy(&server_duid
, new_duid
, MDL
);
186 * Set the server DUID based on the D6O_SERVERID option. This handles
187 * the case where the administrator explicitly put it in the dhcpd.conf
191 set_server_duid_from_option(void) {
192 struct option_state
*opt_state
;
193 struct option_cache
*oc
;
194 struct data_string option_duid
;
195 isc_result_t ret_val
;
198 if (!option_state_allocate(&opt_state
, MDL
)) {
199 log_fatal("No memory for server DUID.");
202 execute_statements_in_scope(NULL
, NULL
, NULL
, NULL
, NULL
,
203 opt_state
, &global_scope
, root_group
, NULL
);
205 oc
= lookup_option(&dhcpv6_universe
, opt_state
, D6O_SERVERID
);
207 ret_val
= ISC_R_NOTFOUND
;
209 memset(&option_duid
, 0, sizeof(option_duid
));
210 if (!evaluate_option_cache(&option_duid
, NULL
, NULL
, NULL
,
211 opt_state
, NULL
, &global_scope
,
213 ret_val
= ISC_R_UNEXPECTED
;
215 set_server_duid(&option_duid
);
216 data_string_forget(&option_duid
, MDL
);
217 ret_val
= ISC_R_SUCCESS
;
221 option_state_dereference(&opt_state
, MDL
);
227 * DUID layout, as defined in RFC 3315, section 9.
229 * We support type 1 (hardware address plus time) and type 3 (hardware
232 * We can support type 2 for specific vendors in the future, if they
233 * publish the specification. And of course there may be additional
236 static int server_duid_type
= DUID_LLT
;
242 set_server_duid_type(int type
) {
243 server_duid_type
= type
;
247 * Generate a new server DUID. This is done if there was no DUID in
248 * the leases.txt or in the dhcpd.conf file.
251 generate_new_server_duid(void) {
252 struct interface_info
*p
;
254 struct data_string generated_duid
;
257 * Verify we have a type that we support.
259 if ((server_duid_type
!= DUID_LL
) && (server_duid_type
!= DUID_LLT
)) {
260 log_error("Invalid DUID type %d specified, "
261 "only LL and LLT types supported", server_duid_type
);
262 return ISC_R_INVALIDARG
;
266 * Find an interface with a hardware address.
269 for (p
= interfaces
; p
!= NULL
; p
= p
->next
) {
270 if (p
->hw_address
.hlen
> 0) {
275 return ISC_R_UNEXPECTED
;
281 memset(&generated_duid
, 0, sizeof(generated_duid
));
282 if (server_duid_type
== DUID_LLT
) {
283 time_val
= duid_time(time(NULL
));
284 generated_duid
.len
= 8 + p
->hw_address
.hlen
- 1;
285 if (!buffer_allocate(&generated_duid
.buffer
,
286 generated_duid
.len
, MDL
)) {
287 log_fatal("No memory for server DUID.");
289 generated_duid
.data
= generated_duid
.buffer
->data
;
290 putUShort(generated_duid
.buffer
->data
, DUID_LLT
);
291 putUShort(generated_duid
.buffer
->data
+ 2,
292 p
->hw_address
.hbuf
[0]);
293 putULong(generated_duid
.buffer
->data
+ 4, time_val
);
294 memcpy(generated_duid
.buffer
->data
+ 8,
295 p
->hw_address
.hbuf
+1, p
->hw_address
.hlen
-1);
296 } else if (server_duid_type
== DUID_LL
) {
297 generated_duid
.len
= 4 + p
->hw_address
.hlen
- 1;
298 if (!buffer_allocate(&generated_duid
.buffer
,
299 generated_duid
.len
, MDL
)) {
300 log_fatal("No memory for server DUID.");
302 generated_duid
.data
= generated_duid
.buffer
->data
;
303 putUShort(generated_duid
.buffer
->data
, DUID_LL
);
304 putUShort(generated_duid
.buffer
->data
+ 2,
305 p
->hw_address
.hbuf
[0]);
306 memcpy(generated_duid
.buffer
->data
+4,
307 p
->hw_address
.hbuf
+1, p
->hw_address
.hlen
-1);
309 log_fatal("Unsupported server DUID type %d.", server_duid_type
);
312 set_server_duid(&generated_duid
);
313 data_string_forget(&generated_duid
, MDL
);
315 return ISC_R_SUCCESS
;
319 * Get the client identifier from the packet.
322 get_client_id(struct packet
*packet
, struct data_string
*client_id
) {
323 struct option_cache
*oc
;
326 * Verify our client_id structure is empty.
328 if ((client_id
->data
!= NULL
) || (client_id
->len
!= 0)) {
329 return ISC_R_INVALIDARG
;
332 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_CLIENTID
);
334 return ISC_R_NOTFOUND
;
337 if (!evaluate_option_cache(client_id
, packet
, NULL
, NULL
,
338 packet
->options
, NULL
,
339 &global_scope
, oc
, MDL
)) {
340 return ISC_R_FAILURE
;
343 return ISC_R_SUCCESS
;
347 * Message validation, defined in RFC 3315, sections 15.2, 15.5, 15.7:
349 * Servers MUST discard any Solicit messages that do not include a
350 * Client Identifier option or that do include a Server Identifier
354 valid_client_msg(struct packet
*packet
, struct data_string
*client_id
) {
356 struct option_cache
*oc
;
357 struct data_string data
;
360 memset(client_id
, 0, sizeof(*client_id
));
361 memset(&data
, 0, sizeof(data
));
363 switch (get_client_id(packet
, client_id
)) {
367 log_debug("Discarding %s from %s; "
368 "client identifier missing",
369 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
370 piaddr(packet
->client_addr
));
373 log_error("Error processing %s from %s; "
374 "unable to evaluate Client Identifier",
375 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
376 piaddr(packet
->client_addr
));
381 * Required by RFC 3315, section 15.
383 if (packet
->unicast
) {
384 log_debug("Discarding %s from %s; packet sent unicast "
386 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
387 piaddr(packet
->client_addr
),
388 print_hex_1(client_id
->len
, client_id
->data
, 60));
393 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
395 if (evaluate_option_cache(&data
, packet
, NULL
, NULL
,
396 packet
->options
, NULL
,
397 &global_scope
, oc
, MDL
)) {
398 log_debug("Discarding %s from %s; "
399 "server identifier found "
400 "(CLIENTID %s, SERVERID %s)",
401 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
402 piaddr(packet
->client_addr
),
403 print_hex_1(client_id
->len
,
404 client_id
->data
, 60),
405 print_hex_2(data
.len
,
408 log_debug("Discarding %s from %s; "
409 "server identifier found "
411 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
412 print_hex_1(client_id
->len
,
413 client_id
->data
, 60),
414 piaddr(packet
->client_addr
));
424 data_string_forget(&data
, MDL
);
427 if (client_id
->len
> 0) {
428 data_string_forget(client_id
, MDL
);
435 * Response validation, defined in RFC 3315, sections 15.4, 15.6, 15.8,
436 * 15.9 (slightly different wording, but same meaning):
438 * Servers MUST discard any received Request message that meet any of
439 * the following conditions:
441 * - the message does not include a Server Identifier option.
442 * - the contents of the Server Identifier option do not match the
444 * - the message does not include a Client Identifier option.
447 valid_client_resp(struct packet
*packet
,
448 struct data_string
*client_id
,
449 struct data_string
*server_id
)
452 struct option_cache
*oc
;
454 /* INSIST((duid.data != NULL) && (duid.len > 0)); */
457 memset(client_id
, 0, sizeof(*client_id
));
458 memset(server_id
, 0, sizeof(*server_id
));
460 switch (get_client_id(packet
, client_id
)) {
464 log_debug("Discarding %s from %s; "
465 "client identifier missing",
466 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
467 piaddr(packet
->client_addr
));
470 log_error("Error processing %s from %s; "
471 "unable to evaluate Client Identifier",
472 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
473 piaddr(packet
->client_addr
));
477 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
479 log_debug("Discarding %s from %s: "
480 "server identifier missing (CLIENTID %s)",
481 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
482 piaddr(packet
->client_addr
),
483 print_hex_1(client_id
->len
, client_id
->data
, 60));
486 if (!evaluate_option_cache(server_id
, packet
, NULL
, NULL
,
487 packet
->options
, NULL
,
488 &global_scope
, oc
, MDL
)) {
489 log_error("Error processing %s from %s; "
490 "unable to evaluate Server Identifier (CLIENTID %s)",
491 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
492 piaddr(packet
->client_addr
),
493 print_hex_1(client_id
->len
, client_id
->data
, 60));
496 if ((server_duid
.len
!= server_id
->len
) ||
497 (memcmp(server_duid
.data
, server_id
->data
, server_duid
.len
) != 0)) {
498 log_debug("Discarding %s from %s; "
499 "not our server identifier "
500 "(CLIENTID %s, SERVERID %s, server DUID %s)",
501 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
502 piaddr(packet
->client_addr
),
503 print_hex_1(client_id
->len
, client_id
->data
, 60),
504 print_hex_2(server_id
->len
, server_id
->data
, 60),
505 print_hex_3(server_duid
.len
, server_duid
.data
, 60));
514 if (server_id
->len
> 0) {
515 data_string_forget(server_id
, MDL
);
517 if (client_id
->len
> 0) {
518 data_string_forget(client_id
, MDL
);
525 * Information request validation, defined in RFC 3315, section 15.12:
527 * Servers MUST discard any received Information-request message that
528 * meets any of the following conditions:
530 * - The message includes a Server Identifier option and the DUID in
531 * the option does not match the server's DUID.
533 * - The message includes an IA option.
536 valid_client_info_req(struct packet
*packet
, struct data_string
*server_id
) {
538 struct option_cache
*oc
;
539 struct data_string client_id
;
540 char client_id_str
[80]; /* print_hex_1() uses maximum 60 characters,
541 plus a few more for extra information */
544 memset(server_id
, 0, sizeof(*server_id
));
547 * Make a string that we can print out to give more
548 * information about the client if we need to.
550 * By RFC 3315, Section 18.1.5 clients SHOULD have a
551 * client-id on an Information-request packet, but it
552 * is not strictly necessary.
554 if (get_client_id(packet
, &client_id
) == ISC_R_SUCCESS
) {
555 snprintf(client_id_str
, sizeof(client_id_str
), " (CLIENTID %s)",
556 print_hex_1(client_id
.len
, client_id
.data
, 60));
557 data_string_forget(&client_id
, MDL
);
559 client_id_str
[0] = '\0';
563 * Required by RFC 3315, section 15.
565 if (packet
->unicast
) {
566 log_debug("Discarding %s from %s; packet sent unicast%s",
567 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
568 piaddr(packet
->client_addr
), client_id_str
);
572 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
574 log_debug("Discarding %s from %s; "
575 "IA_NA option present%s",
576 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
577 piaddr(packet
->client_addr
), client_id_str
);
580 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_TA
);
582 log_debug("Discarding %s from %s; "
583 "IA_TA option present%s",
584 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
585 piaddr(packet
->client_addr
), client_id_str
);
588 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_PD
);
590 log_debug("Discarding %s from %s; "
591 "IA_PD option present%s",
592 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
593 piaddr(packet
->client_addr
), client_id_str
);
597 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
599 if (!evaluate_option_cache(server_id
, packet
, NULL
, NULL
,
600 packet
->options
, NULL
,
601 &global_scope
, oc
, MDL
)) {
602 log_error("Error processing %s from %s; "
603 "unable to evaluate Server Identifier%s",
604 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
605 piaddr(packet
->client_addr
), client_id_str
);
608 if ((server_duid
.len
!= server_id
->len
) ||
609 (memcmp(server_duid
.data
, server_id
->data
,
610 server_duid
.len
) != 0)) {
611 log_debug("Discarding %s from %s; "
612 "not our server identifier "
613 "(SERVERID %s, server DUID %s)%s",
614 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
615 piaddr(packet
->client_addr
),
616 print_hex_1(server_id
->len
,
617 server_id
->data
, 60),
618 print_hex_2(server_duid
.len
,
619 server_duid
.data
, 60),
630 if (server_id
->len
> 0) {
631 data_string_forget(server_id
, MDL
);
638 * Options that we want to send, in addition to what was requested
641 static const int required_opts
[] = {
648 static const int required_opts_NAA
[] = {
654 static const int required_opts_solicit
[] = {
667 static const int required_opts_IA_NA
[] = {
674 static const int required_opts_IA_TA[] = {
680 static const int required_opts_IA_PD[] = {
687 static const int required_opts_STATUS_CODE
[] = {
693 * Extracts from packet contents an IA_* option, storing the IA structure
694 * in its entirety in enc_opt_data, and storing any decoded DHCPv6 options
695 * in enc_opt_state for later lookup and evaluation. The 'offset' indicates
696 * where in the IA_* the DHCPv6 options commence.
699 get_encapsulated_IA_state(struct option_state
**enc_opt_state
,
700 struct data_string
*enc_opt_data
,
701 struct packet
*packet
,
702 struct option_cache
*oc
,
706 * Get the raw data for the encapsulated options.
708 memset(enc_opt_data
, 0, sizeof(*enc_opt_data
));
709 if (!evaluate_option_cache(enc_opt_data
, packet
,
710 NULL
, NULL
, packet
->options
, NULL
,
711 &global_scope
, oc
, MDL
)) {
712 log_error("get_encapsulated_IA_state: "
713 "error evaluating raw option.");
716 if (enc_opt_data
->len
< offset
) {
717 log_error("get_encapsulated_IA_state: raw option too small.");
718 data_string_forget(enc_opt_data
, MDL
);
723 * Now create the option state structure, and pass it to the
724 * function that parses options.
726 *enc_opt_state
= NULL
;
727 if (!option_state_allocate(enc_opt_state
, MDL
)) {
728 log_error("get_encapsulated_IA_state: no memory for options.");
729 data_string_forget(enc_opt_data
, MDL
);
732 if (!parse_option_buffer(*enc_opt_state
,
733 enc_opt_data
->data
+ offset
,
734 enc_opt_data
->len
- offset
,
736 log_error("get_encapsulated_IA_state: error parsing options.");
737 option_state_dereference(enc_opt_state
, MDL
);
738 data_string_forget(enc_opt_data
, MDL
);
746 set_status_code(u_int16_t status_code
, const char *status_message
,
747 struct option_state
*opt_state
)
749 struct data_string d
;
752 memset(&d
, 0, sizeof(d
));
753 d
.len
= sizeof(status_code
) + strlen(status_message
);
754 if (!buffer_allocate(&d
.buffer
, d
.len
, MDL
)) {
755 log_fatal("set_status_code: no memory for status code.");
757 d
.data
= d
.buffer
->data
;
758 putUShort(d
.buffer
->data
, status_code
);
759 memcpy(d
.buffer
->data
+ sizeof(status_code
),
760 status_message
, d
.len
- sizeof(status_code
));
761 if (!save_option_buffer(&dhcpv6_universe
, opt_state
,
762 d
.buffer
, (unsigned char *)d
.data
, d
.len
,
763 D6O_STATUS_CODE
, 0)) {
764 log_error("set_status_code: error saving status code.");
769 data_string_forget(&d
, MDL
);
774 * We have a set of operations we do to set up the reply packet, which
775 * is the same for many message types.
778 start_reply(struct packet
*packet
,
779 const struct data_string
*client_id
,
780 const struct data_string
*server_id
,
781 struct option_state
**opt_state
,
782 struct dhcpv6_packet
*reply
)
784 struct option_cache
*oc
;
785 const unsigned char *server_id_data
;
789 * Build our option state for reply.
792 if (!option_state_allocate(opt_state
, MDL
)) {
793 log_error("start_reply: no memory for option_state.");
796 execute_statements_in_scope(NULL
, packet
, NULL
, NULL
,
797 packet
->options
, *opt_state
,
798 &global_scope
, root_group
, NULL
);
801 * A small bit of special handling for Solicit messages.
803 * We could move the logic into a flag, but for now just check
806 if (packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
) {
807 reply
->msg_type
= DHCPV6_ADVERTISE
;
811 * - this message type supports rapid commit (Solicit), and
812 * - the server is configured to supply a rapid commit, and
813 * - the client requests a rapid commit,
814 * Then we add a rapid commit option, and send Reply (instead
817 oc
= lookup_option(&dhcpv6_universe
,
818 *opt_state
, D6O_RAPID_COMMIT
);
820 oc
= lookup_option(&dhcpv6_universe
,
821 packet
->options
, D6O_RAPID_COMMIT
);
823 /* Rapid-commit in action. */
824 reply
->msg_type
= DHCPV6_REPLY
;
826 /* Don't want a rapid-commit in advertise. */
827 delete_option(&dhcpv6_universe
,
828 *opt_state
, D6O_RAPID_COMMIT
);
832 reply
->msg_type
= DHCPV6_REPLY
;
833 /* Delete the rapid-commit from the sent options. */
834 oc
= lookup_option(&dhcpv6_universe
,
835 *opt_state
, D6O_RAPID_COMMIT
);
837 delete_option(&dhcpv6_universe
,
838 *opt_state
, D6O_RAPID_COMMIT
);
843 * Use the client's transaction identifier for the reply.
845 memcpy(reply
->transaction_id
, packet
->dhcpv6_transaction_id
,
846 sizeof(reply
->transaction_id
));
849 * RFC 3315, section 18.2 says we need server identifier and
852 * If the server ID is defined via the configuration file, then
853 * it will already be present in the option state at this point,
854 * so we don't need to set it.
856 * If we have a server ID passed in from the caller,
857 * use that, otherwise use the global DUID.
859 oc
= lookup_option(&dhcpv6_universe
, *opt_state
, D6O_SERVERID
);
861 if (server_id
== NULL
) {
862 server_id_data
= server_duid
.data
;
863 server_id_len
= server_duid
.len
;
865 server_id_data
= server_id
->data
;
866 server_id_len
= server_id
->len
;
868 if (!save_option_buffer(&dhcpv6_universe
, *opt_state
,
869 NULL
, (unsigned char *)server_id_data
,
870 server_id_len
, D6O_SERVERID
, 0)) {
871 log_error("start_reply: "
872 "error saving server identifier.");
877 if (client_id
->buffer
!= NULL
) {
878 if (!save_option_buffer(&dhcpv6_universe
, *opt_state
,
880 (unsigned char *)client_id
->data
,
883 log_error("start_reply: error saving "
884 "client identifier.");
890 * If the client accepts reconfiguration, let it know that we
893 * Note: we don't actually do this yet, but DOCSIS requires we
896 oc
= lookup_option(&dhcpv6_universe
, packet
->options
,
899 if (!save_option_buffer(&dhcpv6_universe
, *opt_state
,
900 NULL
, (unsigned char *)"", 0,
901 D6O_RECONF_ACCEPT
, 0)) {
902 log_error("start_reply: "
903 "error saving RECONF_ACCEPT option.");
904 option_state_dereference(opt_state
, MDL
);
913 * Try to get the IPv6 address the client asked for from the
916 * addr is the result (should be a pointer to NULL on entry)
917 * pool is the pool to search in
918 * requested_addr is the address the client wants
921 try_client_v6_address(struct iaaddr
**addr
,
922 struct ipv6_pool
*pool
,
923 const struct data_string
*requested_addr
)
925 struct in6_addr tmp_addr
;
928 if (requested_addr
->len
< sizeof(tmp_addr
)) {
929 return ISC_R_INVALIDARG
;
931 memcpy(&tmp_addr
, requested_addr
->data
, sizeof(tmp_addr
));
932 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr
)) {
933 return ISC_R_FAILURE
;
936 if (!ipv6_addr_in_pool(&tmp_addr
, pool
)) {
937 return ISC_R_FAILURE
;
940 if (lease6_exists(pool
, &tmp_addr
)) {
941 return ISC_R_ADDRINUSE
;
944 result
= iaaddr_allocate(addr
, MDL
);
945 if (result
!= ISC_R_SUCCESS
) {
948 (*addr
)->addr
= tmp_addr
;
950 result
= add_lease6(pool
, *addr
, 0);
951 if (result
!= ISC_R_SUCCESS
) {
952 iaaddr_dereference(addr
, MDL
);
958 * Get an IPv6 address for the client.
960 * addr is the result (should be a pointer to NULL on entry)
961 * packet is the information about the packet from the client
962 * requested_iaaddr is a hint from the client
963 * client_id is the DUID for the client
966 pick_v6_address(struct iaaddr
**addr
, struct shared_network
*shared_network
,
967 const struct data_string
*client_id
)
972 unsigned int attempts
;
973 char tmp_buf
[INET6_ADDRSTRLEN
];
976 * No pools, we're done.
978 if (shared_network
->ipv6_pools
== NULL
) {
979 log_debug("Unable to pick client address: "
980 "no IPv6 pools on this shared network");
981 return ISC_R_NORESOURCES
;
985 * Otherwise try to get a lease from the first subnet possible.
987 * We start looking at the last pool we allocated from, unless
988 * it had a collision trying to allocate an address. This will
989 * tend to move us into less-filled pools.
991 start_pool
= shared_network
->last_ipv6_pool
;
995 p
= shared_network
->ipv6_pools
[i
];
996 if (activate_lease6(p
, addr
, &attempts
,
997 client_id
, 0) == ISC_R_SUCCESS
) {
999 * Record the pool used (or next one if there
1004 if (shared_network
->ipv6_pools
[i
] == NULL
) {
1008 shared_network
->last_ipv6_pool
= i
;
1010 log_debug("Picking pool address %s",
1011 inet_ntop(AF_INET6
, &((*addr
)->addr
),
1012 tmp_buf
, sizeof(tmp_buf
)));
1013 return ISC_R_SUCCESS
;
1017 if (shared_network
->ipv6_pools
[i
] == NULL
) {
1020 } while (i
!= start_pool
);
1023 * If we failed to pick an IPv6 address from any of the subnets.
1024 * Presumably that means we have no addresses for the client.
1026 log_debug("Unable to pick client address: no addresses available");
1027 return ISC_R_NORESOURCES
;
1031 * lease_to_client() is called from several messages to construct a
1032 * reply that contains all that we know about the client's correct lease
1033 * (or projected lease).
1035 * Solicit - "Soft" binding, ignore unknown addresses or bindings, just
1036 * send what we "may" give them on a request.
1038 * Request - "Hard" binding, but ignore supplied addresses (just provide what
1039 * the client should really use).
1041 * Renew - "Hard" binding, but client-supplied addresses are 'real'. Error
1042 * Rebind out any "wrong" addresses the client sends. This means we send
1043 * an empty IA_NA with a status code of NoBinding or NotOnLink or
1044 * possibly send the address with zeroed lifetimes.
1046 * Information-Request - No binding.
1048 * The basic structure is to traverse the client-supplied data first, and
1049 * validate and echo back any contents that can be. If the client-supplied
1050 * data does not error out (on renew/rebind as above), but we did not send
1051 * any addresses, attempt to allocate one.
1053 /* TODO: look at client hints for lease times */
1055 lease_to_client(struct data_string
*reply_ret
,
1056 struct packet
*packet
,
1057 const struct data_string
*client_id
,
1058 const struct data_string
*server_id
)
1060 static struct reply_state reply
;
1061 struct option_cache
*oc
;
1062 struct data_string packet_oro
;
1063 isc_boolean_t no_addrs_avail
;
1065 /* Locate the client. */
1066 if (shared_network_from_packet6(&reply
.shared
,
1067 packet
) != ISC_R_SUCCESS
)
1071 * Initialize the reply.
1073 packet_reference(&reply
.packet
, packet
, MDL
);
1074 data_string_copy(&reply
.client_id
, client_id
, MDL
);
1076 if (!start_reply(packet
, client_id
, server_id
, &reply
.opt_state
,
1080 /* Set the write cursor to just past the reply header. */
1081 reply
.cursor
= REPLY_OPTIONS_INDEX
;
1084 * Get the ORO from the packet, if any.
1086 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_ORO
);
1087 memset(&packet_oro
, 0, sizeof(packet_oro
));
1089 if (!evaluate_option_cache(&packet_oro
, packet
,
1091 packet
->options
, NULL
,
1092 &global_scope
, oc
, MDL
)) {
1093 log_error("lease_to_client: error evaluating ORO.");
1099 * Find a host record that matches from the packet, if any, and is
1100 * valid for the shared network the client is on.
1102 if (find_hosts_by_option(&reply
.host
, packet
, packet
->options
, MDL
)) {
1103 seek_shared_host(&reply
.host
, reply
.shared
);
1106 if ((reply
.host
== NULL
) &&
1107 find_hosts_by_uid(&reply
.host
, client_id
->data
, client_id
->len
,
1109 seek_shared_host(&reply
.host
, reply
.shared
);
1112 /* Process the client supplied IA_NA's onto the reply buffer. */
1114 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
1115 no_addrs_avail
= ISC_FALSE
;
1116 for (; oc
!= NULL
; oc
= oc
->next
) {
1117 isc_result_t status
;
1119 /* Start counting resources (addresses) offered. */
1120 reply
.client_resources
= 0;
1121 reply
.ia_addrs_included
= ISC_FALSE
;
1123 status
= reply_process_ia_na(&reply
, oc
);
1126 * We continue to try other IA's whether we can address
1127 * this one or not. Any other result is an immediate fail.
1129 if ((status
!= ISC_R_SUCCESS
) &&
1130 (status
!= ISC_R_NORESOURCES
))
1134 * If any address can be given to any IA, then do not set the
1135 * NoAddrsAvail status code.
1137 if (reply
.client_resources
== 0)
1138 no_addrs_avail
= ISC_TRUE
;
1141 /* Do IA_TA and IA_PD */
1144 * Make no reply if we gave no resources and is not
1145 * for Information-Request.
1147 if ((reply
.ia_count
== 0) &&
1148 (packet
->dhcpv6_msg_type
!= DHCPV6_INFORMATION_REQUEST
))
1152 * RFC3315 section 17.2.2 (Solicit):
1154 * If the server will not assign any addresses to any IAs in a
1155 * subsequent Request from the client, the server MUST send an
1156 * Advertise message to the client that includes only a Status
1157 * Code option with code NoAddrsAvail and a status message for
1158 * the user, a Server Identifier option with the server's DUID,
1159 * and a Client Identifier option with the client's DUID.
1161 * Section 18.2.1 (Request):
1163 * If the server cannot assign any addresses to an IA in the
1164 * message from the client, the server MUST include the IA in
1165 * the Reply message with no addresses in the IA and a Status
1166 * Code option in the IA containing status code NoAddrsAvail.
1168 * Section 18.1.8 (Client Behavior):
1170 * Leave unchanged any information about addresses the client has
1171 * recorded in the IA but that were not included in the IA from
1173 * Sends a Renew/Rebind if the IA is not in the Reply message.
1175 if (no_addrs_avail
&&
1176 (reply
.packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
))
1178 /* Set the NoAddrsAvail status code. */
1179 if (!set_status_code(STATUS_NoAddrsAvail
,
1180 "No addresses available for this "
1181 "interface.", reply
.opt_state
)) {
1182 log_error("lease_to_client: Unable to set "
1183 "NoAddrsAvail status code.");
1187 /* Rewind the cursor to the start. */
1188 reply
.cursor
= REPLY_OPTIONS_INDEX
;
1191 * Produce an advertise that includes only:
1197 reply
.buf
.reply
.msg_type
= DHCPV6_ADVERTISE
;
1198 reply
.cursor
+= store_options6((char *)reply
.buf
.data
+
1202 reply
.opt_state
, reply
.packet
,
1207 * Having stored the client's IA_NA's, store any options that
1208 * will fit in the remaining space.
1210 reply
.cursor
+= store_options6((char *)reply
.buf
.data
+
1214 reply
.opt_state
, reply
.packet
,
1215 required_opts_solicit
,
1219 /* Return our reply to the caller. */
1220 reply_ret
->len
= reply
.cursor
;
1221 reply_ret
->buffer
= NULL
;
1222 if (!buffer_allocate(&reply_ret
->buffer
, reply
.cursor
, MDL
)) {
1223 log_fatal("No memory to store Reply.");
1225 memcpy(reply_ret
->buffer
->data
, reply
.buf
.data
, reply
.cursor
);
1226 reply_ret
->data
= reply_ret
->buffer
->data
;
1230 if (reply
.shared
!= NULL
)
1231 shared_network_dereference(&reply
.shared
, MDL
);
1232 if (reply
.host
!= NULL
)
1233 host_dereference(&reply
.host
, MDL
);
1234 if (reply
.opt_state
!= NULL
)
1235 option_state_dereference(&reply
.opt_state
, MDL
);
1236 if (reply
.packet
!= NULL
)
1237 packet_dereference(&reply
.packet
, MDL
);
1238 if (reply
.client_id
.data
!= NULL
)
1239 data_string_forget(&reply
.client_id
, MDL
);
1240 reply
.renew
= reply
.rebind
= reply
.prefer
= reply
.valid
= 0;
1244 /* Process a client-supplied IA_NA. This may append options to the tail of
1245 * the reply packet being built in the reply_state structure.
1248 reply_process_ia_na(struct reply_state
*reply
, struct option_cache
*ia
) {
1249 isc_result_t status
= ISC_R_SUCCESS
;
1252 struct option_state
*packet_ia
;
1253 struct option_cache
*oc
;
1254 struct data_string ia_data
, data
;
1255 isc_boolean_t lease_in_database
;
1257 /* Initialize values that will get cleaned up on return. */
1259 memset(&ia_data
, 0, sizeof(ia_data
));
1260 memset(&data
, 0, sizeof(data
));
1261 lease_in_database
= ISC_FALSE
;
1263 * Note that find_client_address() may set reply->lease.
1266 /* Make sure there is at least room for the header. */
1267 if ((reply
->cursor
+ IA_NA_OFFSET
+ 4) > sizeof(reply
->buf
)) {
1268 log_error("reply_process_ia_na: Reply too long for IA.");
1269 return ISC_R_NOSPACE
;
1273 /* Fetch the IA_NA contents. */
1274 if (!get_encapsulated_IA_state(&packet_ia
, &ia_data
, reply
->packet
,
1275 ia
, IA_NA_OFFSET
)) {
1276 log_error("reply_process_ia_na: error evaluating ia_na");
1277 status
= ISC_R_FAILURE
;
1281 /* Extract IA_NA header contents. */
1282 iaid
= getULong(ia_data
.data
);
1283 reply
->renew
= getULong(ia_data
.data
+ 4);
1284 reply
->rebind
= getULong(ia_data
.data
+ 8);
1286 /* Create an IA_NA structure. */
1287 if (ia_na_allocate(&reply
->ia_na
, iaid
, (char *)reply
->client_id
.data
,
1288 reply
->client_id
.len
, MDL
) != ISC_R_SUCCESS
) {
1289 log_error("lease_to_client: no memory for ia_na.");
1290 status
= ISC_R_NOMEMORY
;
1293 reply
->ia_na
->ia_type
= D6O_IA_NA
;
1295 /* Cache pre-existing IA, if any. */
1296 ia_na_hash_lookup(&reply
->old_ia_na
, ia_na_active
,
1297 (unsigned char *)reply
->ia_na
->iaid_duid
.data
,
1298 reply
->ia_na
->iaid_duid
.len
, MDL
);
1301 * Create an option cache to carry the IA_NA option contents, and
1302 * execute any user-supplied values into it.
1304 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
1305 status
= ISC_R_NOMEMORY
;
1309 /* Check & cache the fixed host record. */
1310 if ((reply
->host
!= NULL
) && (reply
->host
->fixed_addr
!= NULL
)) {
1311 if (!evaluate_option_cache(&reply
->fixed
, NULL
, NULL
, NULL
,
1312 NULL
, NULL
, &global_scope
,
1313 reply
->host
->fixed_addr
, MDL
)) {
1314 log_error("reply_process_ia_na: unable to evaluate "
1316 status
= ISC_R_FAILURE
;
1320 if (reply
->fixed
.len
< 16) {
1321 log_error("reply_process_ia_na: invalid fixed address.");
1322 status
= ISC_R_INVALIDARG
;
1326 reply
->static_lease
= ISC_TRUE
;
1328 reply
->static_lease
= ISC_FALSE
;
1331 * Save the cursor position at the start of the IA, so we can
1332 * set length and adjust t1/t2 values later. We write a temporary
1333 * header out now just in case we decide to adjust the packet
1334 * within sub-process functions.
1336 ia_cursor
= reply
->cursor
;
1338 /* Initialize the IA_NA header. First the code. */
1339 putUShort(reply
->buf
.data
+ reply
->cursor
, (unsigned)D6O_IA_NA
);
1342 /* Then option length. */
1343 putUShort(reply
->buf
.data
+ reply
->cursor
, 0x0Cu
);
1346 /* Then IA_NA header contents; IAID. */
1347 putULong(reply
->buf
.data
+ reply
->cursor
, iaid
);
1350 /* We store the client's t1 for now, and may over-ride it later. */
1351 putULong(reply
->buf
.data
+ reply
->cursor
, reply
->renew
);
1354 /* We store the client's t2 for now, and may over-ride it later. */
1355 putULong(reply
->buf
.data
+ reply
->cursor
, reply
->rebind
);
1359 * For each address in this IA_NA, decide what to do about it.
1363 * The client leaves unchanged any infomation about addresses
1364 * it has recorded but are not included ("cancel/break" below).
1365 * A not included IA ("cleanup" below) could give a Renew/Rebind.
1367 oc
= lookup_option(&dhcpv6_universe
, packet_ia
, D6O_IAADDR
);
1368 reply
->valid
= reply
->prefer
= 0xffffffff;
1369 reply
->client_valid
= reply
->client_prefer
= 0;
1370 for (; oc
!= NULL
; oc
= oc
->next
) {
1371 status
= reply_process_addr(reply
, oc
);
1374 * Canceled means we did not allocate addresses to the
1375 * client, but we're "done" with this IA - we set a status
1376 * code. So transmit this reply, e.g., move on to the next
1379 if (status
== ISC_R_CANCELED
)
1382 if ((status
!= ISC_R_SUCCESS
) && (status
!= ISC_R_ADDRINUSE
))
1389 * If we fell through the above and never gave the client
1390 * an address, give it one now.
1392 if ((status
!= ISC_R_CANCELED
) && (reply
->client_resources
== 0)) {
1393 status
= find_client_address(reply
);
1395 if (status
== ISC_R_NORESOURCES
) {
1396 switch (reply
->packet
->dhcpv6_msg_type
) {
1397 case DHCPV6_SOLICIT
:
1399 * No address for all the IA's is handled
1403 case DHCPV6_REQUEST
:
1404 /* Section 18.2.1 (Request):
1406 * If the server cannot assign any addresses to
1407 * an IA in the message from the client, the
1408 * server MUST include the IA in the Reply
1409 * message with no addresses in the IA and a
1410 * Status Code option in the IA containing
1411 * status code NoAddrsAvail.
1413 option_state_dereference(&reply
->reply_ia
, MDL
);
1414 if (!option_state_allocate(&reply
->reply_ia
,
1417 log_error("reply_process_ia_na: No "
1418 "memory for option state "
1420 status
= ISC_R_NOMEMORY
;
1424 if (!set_status_code(STATUS_NoAddrsAvail
,
1425 "No addresses available "
1426 "for this interface.",
1428 log_error("reply_process_ia_na: Unable "
1429 "to set NoAddrsAvail status "
1431 status
= ISC_R_FAILURE
;
1435 status
= ISC_R_SUCCESS
;
1440 * RFC 3315 does not tell us to emit a status
1441 * code in this condition, or anything else.
1443 * If we included non-allocated addresses
1444 * (zeroed lifetimes) in an IA, then the client
1445 * will deconfigure them.
1447 * So we want to include the IA even if we
1448 * can't give it a new address if it includes
1449 * zeroed lifetime addresses.
1451 * We don't want to include the IA if we
1452 * provide zero addresses including zeroed
1455 if (reply
->ia_addrs_included
)
1456 status
= ISC_R_SUCCESS
;
1463 if (status
!= ISC_R_SUCCESS
)
1467 reply
->cursor
+= store_options6((char *)reply
->buf
.data
+ reply
->cursor
,
1468 sizeof(reply
->buf
) - reply
->cursor
,
1469 reply
->reply_ia
, reply
->packet
,
1470 required_opts_IA_NA
, NULL
);
1472 /* Reset the length of this IA to match what was just written. */
1473 putUShort(reply
->buf
.data
+ ia_cursor
+ 2,
1474 reply
->cursor
- (ia_cursor
+ 4));
1477 * T1/T2 time selection is kind of weird. We actually use DHCP
1478 * (v4) scoped options as handy existing places where these might
1479 * be configured by an administrator. A value of zero tells the
1480 * client it may choose its own renewal time.
1483 oc
= lookup_option(&dhcp_universe
, reply
->opt_state
,
1484 DHO_DHCP_RENEWAL_TIME
);
1486 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
1487 reply
->packet
->options
,
1488 reply
->opt_state
, &global_scope
,
1491 log_error("Invalid renewal time.");
1493 reply
->renew
= getULong(data
.data
);
1496 if (data
.data
!= NULL
)
1497 data_string_forget(&data
, MDL
);
1499 putULong(reply
->buf
.data
+ ia_cursor
+ 8, reply
->renew
);
1503 oc
= lookup_option(&dhcp_universe
, reply
->opt_state
,
1504 DHO_DHCP_REBINDING_TIME
);
1506 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
1507 reply
->packet
->options
,
1508 reply
->opt_state
, &global_scope
,
1511 log_error("Invalid rebinding time.");
1513 reply
->rebind
= getULong(data
.data
);
1516 if (data
.data
!= NULL
)
1517 data_string_forget(&data
, MDL
);
1519 putULong(reply
->buf
.data
+ ia_cursor
+ 12, reply
->rebind
);
1522 * If this is not a 'soft' binding, consume the new changes into
1523 * the database (if any have been attached to the ia_na).
1525 * Loop through the assigned dynamic addresses, referencing the
1526 * leases onto this IA_NA rather than any old ones, and updating
1527 * pool timers for each (if any).
1529 if ((status
!= ISC_R_CANCELED
) && !reply
->static_lease
&&
1530 (reply
->buf
.reply
.msg_type
== DHCPV6_REPLY
) &&
1531 (reply
->ia_na
->num_iaaddr
!= 0)) {
1533 struct data_string
*ia_id
;
1536 for (i
= 0 ; i
< reply
->ia_na
->num_iaaddr
; i
++) {
1537 tmp
= reply
->ia_na
->iaaddr
[i
];
1539 if (tmp
->ia_na
!= NULL
)
1540 ia_na_dereference(&tmp
->ia_na
, MDL
);
1541 ia_na_reference(&tmp
->ia_na
, reply
->ia_na
, MDL
);
1543 schedule_lease_timeout(tmp
->ipv6_pool
);
1546 * If this constitutes a 'hard' binding, perform ddns
1549 oc
= lookup_option(&server_universe
, reply
->opt_state
,
1552 evaluate_boolean_option_cache(NULL
, reply
->packet
,
1554 reply
->packet
->options
,
1558 ddns_updates(reply
->packet
, NULL
, NULL
,
1559 tmp
, NULL
, reply
->opt_state
);
1563 /* Remove any old ia_na from the hash. */
1564 if (reply
->old_ia_na
!= NULL
) {
1565 ia_id
= &reply
->old_ia_na
->iaid_duid
;
1566 ia_na_hash_delete(ia_na_active
,
1567 (unsigned char *)ia_id
->data
,
1569 ia_na_dereference(&reply
->old_ia_na
, MDL
);
1572 /* Put new ia_na into the hash. */
1573 ia_id
= &reply
->ia_na
->iaid_duid
;
1574 ia_na_hash_add(ia_na_active
, (unsigned char *)ia_id
->data
,
1575 ia_id
->len
, reply
->ia_na
, MDL
);
1577 write_ia(reply
->ia_na
);
1580 * Note that we wrote the lease into the database,
1581 * so that we know not to release it when we're done
1582 * with this function.
1584 lease_in_database
= ISC_TRUE
;
1587 * If this is a soft binding, we will check to see if we are
1588 * suggesting the existing database entry to the client.
1590 } else if ((status
!= ISC_R_CANCELED
) && !reply
->static_lease
&&
1591 (reply
->old_ia_na
!= NULL
)) {
1592 if (ia_na_equal(reply
->old_ia_na
, reply
->ia_na
)) {
1593 lease_in_database
= ISC_TRUE
;
1598 if (packet_ia
!= NULL
)
1599 option_state_dereference(&packet_ia
, MDL
);
1600 if (reply
->reply_ia
!= NULL
)
1601 option_state_dereference(&reply
->reply_ia
, MDL
);
1602 if (ia_data
.data
!= NULL
)
1603 data_string_forget(&ia_data
, MDL
);
1604 if (data
.data
!= NULL
)
1605 data_string_forget(&data
, MDL
);
1606 if (reply
->ia_na
!= NULL
)
1607 ia_na_dereference(&reply
->ia_na
, MDL
);
1608 if (reply
->old_ia_na
!= NULL
)
1609 ia_na_dereference(&reply
->old_ia_na
, MDL
);
1610 if (reply
->lease
!= NULL
) {
1611 if (!lease_in_database
) {
1612 release_lease6(reply
->lease
->ipv6_pool
, reply
->lease
);
1614 iaaddr_dereference(&reply
->lease
, MDL
);
1616 if (reply
->fixed
.data
!= NULL
)
1617 data_string_forget(&reply
->fixed
, MDL
);
1620 * ISC_R_CANCELED is a status code used by the addr processing to
1621 * indicate we're replying with a status code. This is still a
1622 * success at higher layers.
1624 return((status
== ISC_R_CANCELED
) ? ISC_R_SUCCESS
: status
);
1628 * Process an IAADDR within a given IA_NA, storing any IAADDR reply contents
1629 * into the reply's current ia-scoped option cache. Returns ISC_R_CANCELED
1630 * in the event we are replying with a status code and do not wish to process
1631 * more IAADDRs within this IA.
1634 reply_process_addr(struct reply_state
*reply
, struct option_cache
*addr
) {
1635 u_int32_t pref_life
, valid_life
;
1636 struct binding_scope
**scope
;
1637 struct group
*group
;
1638 struct subnet
*subnet
;
1639 struct iaddr tmp_addr
;
1640 struct option_cache
*oc
;
1641 struct data_string iaaddr
, data
;
1642 isc_result_t status
= ISC_R_SUCCESS
;
1644 /* Initializes values that will be cleaned up. */
1645 memset(&iaaddr
, 0, sizeof(iaaddr
));
1646 memset(&data
, 0, sizeof(data
));
1647 /* Note that reply->lease may be set by address_is_owned() */
1650 * There is no point trying to process an incoming address if there
1651 * is no room for an outgoing address.
1653 if ((reply
->cursor
+ 28) > sizeof(reply
->buf
)) {
1654 log_error("reply_process_addr: Out of room for address.");
1655 return ISC_R_NOSPACE
;
1658 /* Extract this IAADDR option. */
1659 if (!evaluate_option_cache(&iaaddr
, reply
->packet
, NULL
, NULL
,
1660 reply
->packet
->options
, NULL
, &global_scope
,
1662 (iaaddr
.len
< IAADDR_OFFSET
)) {
1663 log_error("reply_process_addr: error evaluating IAADDR.");
1664 status
= ISC_R_FAILURE
;
1668 /* The first 16 bytes are the IPv6 address. */
1669 pref_life
= getULong(iaaddr
.data
+ 16);
1670 valid_life
= getULong(iaaddr
.data
+ 20);
1672 if ((reply
->client_valid
== 0) ||
1673 (reply
->client_valid
> valid_life
))
1674 reply
->client_valid
= valid_life
;
1676 if ((reply
->client_prefer
== 0) ||
1677 (reply
->client_prefer
> pref_life
))
1678 reply
->client_prefer
= pref_life
;
1681 * Clients may choose to send :: as an address, with the idea to give
1682 * hints about preferred-lifetime or valid-lifetime.
1685 memset(tmp_addr
.iabuf
, 0, 16);
1686 if (!memcmp(iaaddr
.data
, tmp_addr
.iabuf
, 16)) {
1687 /* Status remains success; we just ignore this one. */
1691 /* tmp_addr len remains 16 */
1692 memcpy(tmp_addr
.iabuf
, iaaddr
.data
, 16);
1695 * Verify that this address is on the client's network.
1697 for (subnet
= reply
->shared
->subnets
; subnet
!= NULL
;
1698 subnet
= subnet
->next_sibling
) {
1699 if (addr_eq(subnet_number(tmp_addr
, subnet
->netmask
),
1704 /* Address not found on shared network. */
1705 if (subnet
== NULL
) {
1706 /* Ignore this address on 'soft' bindings. */
1707 if (reply
->packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
)
1708 /* status remains success */
1712 * RFC3315 section 18.2.1:
1714 * If the server finds that the prefix on one or more IP
1715 * addresses in any IA in the message from the client is not
1716 * appropriate for the link to which the client is connected,
1717 * the server MUST return the IA to the client with a Status
1718 * Code option with the value NotOnLink.
1720 if (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REQUEST
) {
1721 /* Rewind the IA_NA to empty. */
1722 option_state_dereference(&reply
->reply_ia
, MDL
);
1723 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
1724 log_error("reply_process_addr: No memory for "
1725 "option state wipe.");
1726 status
= ISC_R_NOMEMORY
;
1730 /* Append a NotOnLink status code. */
1731 if (!set_status_code(STATUS_NotOnLink
,
1732 "Address not for use on this "
1733 "link.", reply
->reply_ia
)) {
1734 log_error("reply_process_addr: Failure "
1735 "setting status code.");
1736 status
= ISC_R_FAILURE
;
1740 /* Fin (no more IAADDRs). */
1741 status
= ISC_R_CANCELED
;
1746 * RFC3315 sections 18.2.3 and 18.2.4 have identical language:
1748 * If the server finds that any of the addresses are not
1749 * appropriate for the link to which the client is attached,
1750 * the server returns the address to the client with lifetimes
1753 if ((reply
->packet
->dhcpv6_msg_type
!= DHCPV6_RENEW
) &&
1754 (reply
->packet
->dhcpv6_msg_type
!= DHCPV6_REBIND
)) {
1755 log_error("It is impossible to lease a client that is "
1756 "not sending a solicit, request, renew, or "
1758 status
= ISC_R_FAILURE
;
1762 reply
->send_prefer
= reply
->send_valid
= 0;
1766 /* Verify the address belongs to the client. */
1767 if (!address_is_owned(reply
, &tmp_addr
)) {
1769 * For solicit and request, any addresses included are
1770 * 'requested' addresses. For rebind, we actually have
1771 * no direction on what to do from 3315 section 18.2.4!
1772 * So I think the best bet is to try and give it out, and if
1773 * we can't, zero lifetimes.
1775 if ((reply
->packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
) ||
1776 (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REQUEST
) ||
1777 (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REBIND
)) {
1778 status
= reply_process_try_addr(reply
, &tmp_addr
);
1780 /* Either error out or skip this address. */
1781 if ((status
!= ISC_R_SUCCESS
) &&
1782 (status
!= ISC_R_ADDRINUSE
))
1785 if (reply
->lease
== NULL
) {
1786 if (reply
->packet
->dhcpv6_msg_type
==
1788 reply
->send_prefer
= 0;
1789 reply
->send_valid
= 0;
1793 /* status remains success - ignore */
1797 * RFC3315 section 18.2.3:
1799 * If the server cannot find a client entry for the IA the
1800 * server returns the IA containing no addresses with a Status
1801 * Code option set to NoBinding in the Reply message.
1803 * On mismatch we (ab)use this pretending we have not the IA
1804 * as soon as we have not an address.
1806 } else if (reply
->packet
->dhcpv6_msg_type
== DHCPV6_RENEW
) {
1807 /* Rewind the IA_NA to empty. */
1808 option_state_dereference(&reply
->reply_ia
, MDL
);
1809 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
1810 log_error("reply_process_addr: No memory for "
1811 "option state wipe.");
1812 status
= ISC_R_NOMEMORY
;
1816 /* Append a NoBinding status code. */
1817 if (!set_status_code(STATUS_NoBinding
,
1818 "Address not bound to this "
1819 "interface.", reply
->reply_ia
)) {
1820 log_error("reply_process_addr: Unable to "
1821 "attach status code.");
1822 status
= ISC_R_FAILURE
;
1826 /* Fin (no more IAADDRs). */
1827 status
= ISC_R_CANCELED
;
1830 log_error("It is impossible to lease a client that is "
1831 "not sending a solicit, request, renew, or "
1833 status
= ISC_R_FAILURE
;
1838 if (reply
->static_lease
) {
1839 if (reply
->host
== NULL
)
1840 log_fatal("Impossible condition at %s:%d.", MDL
);
1842 scope
= &global_scope
;
1843 group
= reply
->host
->group
;
1845 if (reply
->lease
== NULL
)
1846 log_fatal("Impossible condition at %s:%d.", MDL
);
1848 scope
= &reply
->lease
->scope
;
1849 group
= reply
->shared
->group
;
1853 * If client_resources is nonzero, then the reply_process_is_addressed
1854 * function has executed configuration state into the reply option
1855 * cache. We will use that valid cache to derive configuration for
1856 * whether or not to engage in additional addresses, and similar.
1858 if (reply
->client_resources
!= 0) {
1862 * Does this client have "enough" addresses already? Default
1863 * to one. Everybody gets one, and one should be enough for
1866 oc
= lookup_option(&server_universe
, reply
->opt_state
,
1867 SV_LIMIT_ADDRS_PER_IA
);
1869 if (!evaluate_option_cache(&data
, reply
->packet
,
1871 reply
->packet
->options
,
1875 log_error("reply_process_addr: unable to "
1876 "evaluate addrs-per-ia value.");
1877 status
= ISC_R_FAILURE
;
1881 limit
= getULong(data
.data
);
1882 data_string_forget(&data
, MDL
);
1886 * If we wish to limit the client to a certain number of
1887 * addresses, then omit the address from the reply.
1889 if (reply
->client_resources
>= limit
)
1893 status
= reply_process_is_addressed(reply
, scope
, group
);
1894 if (status
!= ISC_R_SUCCESS
)
1898 status
= reply_process_send_addr(reply
, &tmp_addr
);
1901 if (iaaddr
.data
!= NULL
)
1902 data_string_forget(&iaaddr
, MDL
);
1903 if (data
.data
!= NULL
)
1904 data_string_forget(&data
, MDL
);
1905 if (reply
->lease
!= NULL
)
1906 iaaddr_dereference(&reply
->lease
, MDL
);
1912 * Verify the address belongs to the client. If we've got a host
1913 * record with a fixed address, it has to be the assigned address
1914 * (fault out all else). Otherwise it's a dynamic address, so lookup
1915 * that address and make sure it belongs to this DUID:IAID pair.
1917 static isc_boolean_t
1918 address_is_owned(struct reply_state
*reply
, struct iaddr
*addr
) {
1922 * This faults out addresses that don't match fixed addresses.
1924 if (reply
->static_lease
) {
1925 if (reply
->fixed
.data
== NULL
)
1926 log_fatal("Impossible condition at %s:%d.", MDL
);
1928 if (memcmp(addr
->iabuf
, reply
->fixed
.data
, 16) == 0)
1934 if ((reply
->old_ia_na
== NULL
) || (reply
->old_ia_na
->num_iaaddr
== 0))
1937 for (i
= 0 ; i
< reply
->old_ia_na
->num_iaaddr
; i
++) {
1940 tmp
= reply
->old_ia_na
->iaaddr
[i
];
1942 if (memcmp(addr
->iabuf
, &tmp
->addr
, 16) == 0) {
1943 iaaddr_reference(&reply
->lease
, tmp
, MDL
);
1952 * This function only returns failure on 'hard' failures. If it succeeds,
1953 * it will leave a lease structure behind.
1956 reply_process_try_addr(struct reply_state
*reply
, struct iaddr
*addr
) {
1957 isc_result_t status
= ISC_R_FAILURE
;
1958 struct ipv6_pool
*pool
;
1960 struct data_string data_addr
;
1962 if ((reply
== NULL
) || (reply
->shared
== NULL
) ||
1963 (reply
->shared
->ipv6_pools
== NULL
) || (addr
== NULL
) ||
1964 (reply
->lease
!= NULL
))
1965 return ISC_R_INVALIDARG
;
1967 memset(&data_addr
, 0, sizeof(data_addr
));
1968 data_addr
.len
= addr
->len
;
1969 data_addr
.data
= addr
->iabuf
;
1971 for (i
= 0 ; (pool
= reply
->shared
->ipv6_pools
[i
]) != NULL
; i
++) {
1972 status
= try_client_v6_address(&reply
->lease
, pool
,
1974 if (status
== ISC_R_SUCCESS
)
1978 /* Note that this is just pedantry. There is no allocation to free. */
1979 data_string_forget(&data_addr
, MDL
);
1980 /* Return just the most recent status... */
1984 /* Look around for an address to give the client. First, look through the
1985 * old IA for addresses we can extend. Second, try to allocate a new address.
1986 * Finally, actually add that address into the current reply IA.
1989 find_client_address(struct reply_state
*reply
) {
1990 struct iaddr send_addr
;
1991 isc_result_t status
= ISC_R_NORESOURCES
;
1992 struct iaaddr
*lease
, *best_lease
= NULL
;
1993 struct binding_scope
**scope
;
1994 struct group
*group
;
1997 if (reply
->host
!= NULL
)
1998 group
= reply
->host
->group
;
2000 group
= reply
->shared
->group
;
2002 if (reply
->static_lease
) {
2003 if (reply
->host
== NULL
)
2004 return ISC_R_INVALIDARG
;
2007 memcpy(send_addr
.iabuf
, reply
->fixed
.data
, 16);
2009 status
= ISC_R_SUCCESS
;
2010 scope
= &global_scope
;
2014 if (reply
->old_ia_na
!= NULL
) {
2015 for (i
= 0 ; i
< reply
->old_ia_na
->num_iaaddr
; i
++) {
2016 lease
= reply
->old_ia_na
->iaaddr
[i
];
2018 best_lease
= lease_compare(lease
, best_lease
);
2022 /* Try to pick a new address if we didn't find one, or if we found an
2025 if ((best_lease
== NULL
) || (best_lease
->state
== FTS_ABANDONED
)) {
2026 status
= pick_v6_address(&reply
->lease
, reply
->shared
,
2028 } else if (best_lease
!= NULL
) {
2029 iaaddr_reference(&reply
->lease
, best_lease
, MDL
);
2030 status
= ISC_R_SUCCESS
;
2033 /* Pick the abandoned lease as a last resort. */
2034 if ((status
== ISC_R_NORESOURCES
) && (best_lease
!= NULL
)) {
2035 /* I don't see how this is supposed to be done right now. */
2036 log_error("Reclaiming abandoned addresses is not yet "
2037 "supported. Treating this as an out of space "
2039 /* lease_reference(&reply->lease, best_lease, MDL); */
2042 /* Give up now if we didn't find a lease. */
2043 if (status
!= ISC_R_SUCCESS
)
2046 if (reply
->lease
== NULL
)
2047 log_fatal("Impossible condition at %s:%d.", MDL
);
2049 scope
= &reply
->lease
->scope
;
2050 group
= reply
->shared
->group
;
2053 memcpy(send_addr
.iabuf
, &reply
->lease
->addr
, 16);
2056 status
= reply_process_is_addressed(reply
, scope
, group
);
2057 if (status
!= ISC_R_SUCCESS
)
2060 status
= reply_process_send_addr(reply
, &send_addr
);
2064 /* Once an address is found for a client, perform several common functions;
2065 * Calculate and store valid and preferred lease times, draw client options
2066 * into the option state.
2069 reply_process_is_addressed(struct reply_state
*reply
,
2070 struct binding_scope
**scope
, struct group
*group
)
2072 isc_result_t status
= ISC_R_SUCCESS
;
2073 struct data_string data
;
2074 struct option_cache
*oc
;
2076 /* Initialize values we will cleanup. */
2077 memset(&data
, 0, sizeof(data
));
2079 /* Execute relevant options into root scope. */
2080 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
2081 reply
->packet
->options
, reply
->opt_state
,
2082 scope
, group
, root_group
);
2084 /* Determine valid lifetime. */
2085 if (reply
->client_valid
== 0)
2086 reply
->send_valid
= DEFAULT_DEFAULT_LEASE_TIME
;
2088 reply
->send_valid
= reply
->client_valid
;
2090 oc
= lookup_option(&server_universe
, reply
->opt_state
,
2091 SV_DEFAULT_LEASE_TIME
);
2093 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
2094 reply
->packet
->options
,
2098 log_error("reply_process_is_addressed: unable to "
2099 "evaluate default lease time");
2100 status
= ISC_R_FAILURE
;
2104 reply
->send_valid
= getULong(data
.data
);
2105 data_string_forget(&data
, MDL
);
2108 if (reply
->client_prefer
== 0)
2109 reply
->send_prefer
= reply
->send_valid
;
2111 reply
->send_prefer
= reply
->client_prefer
;
2113 if (reply
->send_prefer
>= reply
->send_valid
)
2114 reply
->send_prefer
= (reply
->send_valid
/ 2) +
2115 (reply
->send_valid
/ 8);
2117 oc
= lookup_option(&server_universe
, reply
->opt_state
,
2118 SV_PREFER_LIFETIME
);
2120 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
2121 reply
->packet
->options
,
2125 log_error("reply_process_is_addressed: unable to "
2126 "evaluate preferred lease time");
2127 status
= ISC_R_FAILURE
;
2131 reply
->send_prefer
= getULong(data
.data
);
2132 data_string_forget(&data
, MDL
);
2135 /* Note lowest values for later calculation of renew/rebind times. */
2136 if (reply
->prefer
> reply
->send_prefer
)
2137 reply
->prefer
= reply
->send_prefer
;
2139 if (reply
->valid
> reply
->send_valid
)
2140 reply
->valid
= reply
->send_valid
;
2144 * XXX: Old 4.0.0 alpha code would change the host {} record
2145 * XXX: uid upon lease assignment. This was intended to cover the
2146 * XXX: case where a client first identifies itself using vendor
2147 * XXX: options in a solicit, or request, but later neglects to include
2148 * XXX: these options in a Renew or Rebind. It is not clear that this
2149 * XXX: is required, and has some startling ramifications (such as
2150 * XXX: how to recover this dynamic host {} state across restarts).
2152 if (reply
->host
!= NULL
)
2153 change_host_uid(host
, reply
->client_id
->data
,
2154 reply
->client_id
->len
);
2157 /* Perform dynamic lease related update work. */
2158 if (reply
->lease
!= NULL
) {
2159 /* Advance (or rewind) the valid lifetime. */
2160 reply
->lease
->valid_lifetime_end_time
= cur_time
+
2162 renew_lease6(reply
->lease
->ipv6_pool
, reply
->lease
);
2164 status
= ia_na_add_iaaddr(reply
->ia_na
, reply
->lease
, MDL
);
2165 if (status
!= ISC_R_SUCCESS
) {
2166 log_fatal("reply_process_addr: Unable to attach lease "
2167 "to new IA: %s", isc_result_totext(status
));
2171 * If this is a new lease, make sure it is attached somewhere.
2173 if (reply
->lease
->ia_na
== NULL
) {
2174 ia_na_reference(&reply
->lease
->ia_na
, reply
->ia_na
,
2179 /* Bring a copy of the relevant options into the IA scope. */
2180 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
2181 reply
->packet
->options
, reply
->reply_ia
,
2182 scope
, group
, root_group
);
2185 if (data
.data
!= NULL
)
2186 data_string_forget(&data
, MDL
);
2188 if (status
== ISC_R_SUCCESS
)
2189 reply
->client_resources
++;
2194 /* Simply send an IAADDR within the IA_NA scope as described. */
2196 reply_process_send_addr(struct reply_state
*reply
, struct iaddr
*addr
) {
2197 isc_result_t status
= ISC_R_SUCCESS
;
2198 struct data_string data
;
2200 memset(&data
, 0, sizeof(data
));
2202 /* Now append the lease. */
2203 data
.len
= IAADDR_OFFSET
;
2204 if (!buffer_allocate(&data
.buffer
, data
.len
, MDL
)) {
2205 log_error("reply_process_send_addr: out of memory allocating "
2206 "new IAADDR buffer.");
2207 status
= ISC_R_NOMEMORY
;
2210 data
.data
= data
.buffer
->data
;
2212 memcpy(data
.buffer
->data
, addr
->iabuf
, 16);
2213 putULong(data
.buffer
->data
+ 16, reply
->send_prefer
);
2214 putULong(data
.buffer
->data
+ 20, reply
->send_valid
);
2216 if (!append_option_buffer(&dhcpv6_universe
, reply
->reply_ia
,
2217 data
.buffer
, data
.buffer
->data
,
2218 data
.len
, D6O_IAADDR
, 0)) {
2219 log_error("reply_process_send_addr: unable to save IAADDR "
2221 status
= ISC_R_FAILURE
;
2225 reply
->ia_addrs_included
= ISC_TRUE
;
2228 if (data
.data
!= NULL
)
2229 data_string_forget(&data
, MDL
);
2234 /* Choose the better of two leases. */
2235 static struct iaaddr
*
2236 lease_compare(struct iaaddr
*alpha
, struct iaaddr
*beta
) {
2242 switch(alpha
->state
) {
2244 switch(beta
->state
) {
2246 /* Choose the lease with the longest lifetime (most
2247 * likely the most recently allocated).
2249 if (alpha
->valid_lifetime_end_time
<
2250 beta
->valid_lifetime_end_time
)
2260 log_fatal("Impossible condition at %s:%d.", MDL
);
2265 switch (beta
->state
) {
2270 /* Choose the most recently expired lease. */
2271 if (alpha
->valid_lifetime_end_time
<
2272 beta
->valid_lifetime_end_time
)
2281 log_fatal("Impossible condition at %s:%d.", MDL
);
2286 switch (beta
->state
) {
2292 /* Choose the lease that was abandoned longest ago. */
2293 if (alpha
->valid_lifetime_end_time
<
2294 beta
->valid_lifetime_end_time
)
2298 log_fatal("Impossible condition at %s:%d.", MDL
);
2303 log_fatal("Impossible condition at %s:%d.", MDL
);
2306 log_fatal("Triple impossible condition at %s:%d.", MDL
);
2311 * Solicit is how a client starts requesting addresses.
2313 * If the client asks for rapid commit, and we support it, we will
2314 * allocate the addresses and reply.
2316 * Otherwise we will send an advertise message.
2320 dhcpv6_solicit(struct data_string
*reply_ret
, struct packet
*packet
) {
2321 struct data_string client_id
;
2324 * Validate our input.
2326 if (!valid_client_msg(packet
, &client_id
)) {
2330 lease_to_client(reply_ret
, packet
, &client_id
, NULL
);
2335 data_string_forget(&client_id
, MDL
);
2339 * Request is how a client actually requests addresses.
2341 * Very similar to Solicit handling, except the server DUID is required.
2344 /* TODO: reject unicast messages, unless we set unicast option */
2346 dhcpv6_request(struct data_string
*reply_ret
, struct packet
*packet
) {
2347 struct data_string client_id
;
2348 struct data_string server_id
;
2351 * Validate our input.
2353 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
2360 lease_to_client(reply_ret
, packet
, &client_id
, &server_id
);
2365 data_string_forget(&client_id
, MDL
);
2366 data_string_forget(&server_id
, MDL
);
2369 /* Find a DHCPv6 packet's shared network from hints in the packet.
2372 shared_network_from_packet6(struct shared_network
**shared
,
2373 struct packet
*packet
)
2375 const struct packet
*chk_packet
;
2376 const struct in6_addr
*link_addr
, *first_link_addr
;
2377 struct iaddr tmp_addr
;
2378 struct subnet
*subnet
;
2379 isc_result_t status
;
2381 if ((shared
== NULL
) || (*shared
!= NULL
) || (packet
== NULL
))
2382 return ISC_R_INVALIDARG
;
2385 * First, find the link address where the packet from the client
2386 * first appeared (if this packet was relayed).
2388 first_link_addr
= NULL
;
2389 chk_packet
= packet
->dhcpv6_container_packet
;
2390 while (chk_packet
!= NULL
) {
2391 link_addr
= &chk_packet
->dhcpv6_link_address
;
2392 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr
) &&
2393 !IN6_IS_ADDR_LINKLOCAL(link_addr
)) {
2394 first_link_addr
= link_addr
;
2396 chk_packet
= chk_packet
->dhcpv6_container_packet
;
2400 * If there is a relayed link address, find the subnet associated
2401 * with that, and use that to get the appropriate
2404 if (first_link_addr
!= NULL
) {
2405 tmp_addr
.len
= sizeof(*first_link_addr
);
2406 memcpy(tmp_addr
.iabuf
,
2407 first_link_addr
, sizeof(*first_link_addr
));
2409 if (!find_subnet(&subnet
, tmp_addr
, MDL
)) {
2410 log_debug("No subnet found for link-address %s.",
2412 return ISC_R_NOTFOUND
;
2414 status
= shared_network_reference(shared
,
2415 subnet
->shared_network
, MDL
);
2416 subnet_dereference(&subnet
, MDL
);
2419 * If there is no link address, we will use the interface
2420 * that this packet came in on to pick the shared_network.
2423 status
= shared_network_reference(shared
,
2424 packet
->interface
->shared_network
,
2432 * When a client thinks it might be on a new link, it sends a
2435 * From RFC3315 section 18.2.2:
2437 * When the server receives a Confirm message, the server determines
2438 * whether the addresses in the Confirm message are appropriate for the
2439 * link to which the client is attached. If all of the addresses in the
2440 * Confirm message pass this test, the server returns a status of
2441 * Success. If any of the addresses do not pass this test, the server
2442 * returns a status of NotOnLink. If the server is unable to perform
2443 * this test (for example, the server does not have information about
2444 * prefixes on the link to which the client is connected), or there were
2445 * no addresses in any of the IAs sent by the client, the server MUST
2446 * NOT send a reply to the client.
2450 dhcpv6_confirm(struct data_string
*reply_ret
, struct packet
*packet
) {
2451 struct shared_network
*shared
;
2452 struct subnet
*subnet
;
2453 struct option_cache
*ia
, *ta
, *oc
;
2454 struct data_string cli_enc_opt_data
, iaaddr
, client_id
, packet_oro
;
2455 struct option_state
*cli_enc_opt_state
, *opt_state
;
2456 struct iaddr cli_addr
;
2458 isc_boolean_t inappropriate
, has_addrs
;
2459 char reply_data
[65536];
2460 struct dhcpv6_packet
*reply
= (struct dhcpv6_packet
*)reply_data
;
2461 int reply_ofs
= (int)((char *)reply
->options
- (char *)reply
);
2464 * Basic client message validation.
2466 memset(&client_id
, 0, sizeof(client_id
));
2467 if (!valid_client_msg(packet
, &client_id
)) {
2471 /* Do not process Confirms that do not have IA's we do not recognize.
2473 ia
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
2474 ta
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_TA
);
2475 if ((ia
== NULL
) && (ta
== NULL
))
2479 * Bit of variable initialization.
2481 opt_state
= cli_enc_opt_state
= NULL
;
2482 memset(&cli_enc_opt_data
, 0, sizeof(cli_enc_opt_data
));
2483 memset(&iaaddr
, 0, sizeof(iaaddr
));
2484 memset(&packet_oro
, 0, sizeof(packet_oro
));
2486 /* Determine what shared network the client is connected to. We
2487 * must not respond if we don't have any information about the
2488 * network the client is on.
2491 if ((shared_network_from_packet6(&shared
, packet
) != ISC_R_SUCCESS
) ||
2495 /* If there are no recorded subnets, then we have no
2496 * information about this subnet - ignore Confirms.
2498 subnet
= shared
->subnets
;
2502 /* Are the addresses in all the IA's appropriate for that link? */
2503 has_addrs
= inappropriate
= ISC_FALSE
;
2505 while(!inappropriate
) {
2506 /* If we've reached the end of the IA_NA pass, move to the
2509 if ((pass
== D6O_IA_NA
) && (ia
== NULL
)) {
2514 /* If we've reached the end of all passes, we're done. */
2518 if (((pass
== D6O_IA_NA
) &&
2519 !get_encapsulated_IA_state(&cli_enc_opt_state
,
2521 packet
, ia
, IA_NA_OFFSET
)) ||
2522 ((pass
== D6O_IA_TA
) &&
2523 !get_encapsulated_IA_state(&cli_enc_opt_state
,
2525 packet
, ia
, IA_TA_OFFSET
))) {
2529 oc
= lookup_option(&dhcpv6_universe
, cli_enc_opt_state
,
2532 for ( ; oc
!= NULL
; oc
= oc
->next
) {
2533 if (!evaluate_option_cache(&iaaddr
, packet
, NULL
, NULL
,
2534 packet
->options
, NULL
,
2535 &global_scope
, oc
, MDL
) ||
2536 (iaaddr
.len
< IAADDR_OFFSET
)) {
2537 log_error("dhcpv6_confirm: "
2538 "error evaluating IAADDR.");
2542 /* Copy out the IPv6 address for processing. */
2544 memcpy(cli_addr
.iabuf
, iaaddr
.data
, 16);
2546 data_string_forget(&iaaddr
, MDL
);
2548 /* Record that we've processed at least one address. */
2549 has_addrs
= ISC_TRUE
;
2551 /* Find out if any subnets cover this address. */
2552 for (subnet
= shared
->subnets
; subnet
!= NULL
;
2553 subnet
= subnet
->next_sibling
) {
2554 if (addr_eq(subnet_number(cli_addr
,
2560 /* If we reach the end of the subnet list, and no
2561 * subnet matches the client address, then it must
2562 * be inappropriate to the link (so far as our
2563 * configuration says). Once we've found one
2564 * inappropriate address, there is no reason to
2565 * continue searching.
2567 if (subnet
== NULL
) {
2568 inappropriate
= ISC_TRUE
;
2573 option_state_dereference(&cli_enc_opt_state
, MDL
);
2574 data_string_forget(&cli_enc_opt_data
, MDL
);
2576 /* Advance to the next IA_*. */
2580 /* If the client supplied no addresses, do not reply. */
2587 if (!start_reply(packet
, &client_id
, NULL
, &opt_state
, reply
)) {
2594 if (inappropriate
) {
2595 if (!set_status_code(STATUS_NotOnLink
,
2596 "Some of the addresses are not on link.",
2601 if (!set_status_code(STATUS_Success
,
2602 "All addresses still on link.",
2609 * Only one option: add it.
2611 reply_ofs
+= store_options6(reply_data
+reply_ofs
,
2612 sizeof(reply_data
)-reply_ofs
,
2614 required_opts
, &packet_oro
);
2617 * Return our reply to the caller.
2619 reply_ret
->len
= reply_ofs
;
2620 reply_ret
->buffer
= NULL
;
2621 if (!buffer_allocate(&reply_ret
->buffer
, reply_ofs
, MDL
)) {
2622 log_fatal("No memory to store reply.");
2624 reply_ret
->data
= reply_ret
->buffer
->data
;
2625 memcpy(reply_ret
->buffer
->data
, reply
, reply_ofs
);
2628 /* Cleanup any stale data strings. */
2629 if (cli_enc_opt_data
.buffer
!= NULL
)
2630 data_string_forget(&cli_enc_opt_data
, MDL
);
2631 if (iaaddr
.buffer
!= NULL
)
2632 data_string_forget(&iaaddr
, MDL
);
2633 if (client_id
.buffer
!= NULL
)
2634 data_string_forget(&client_id
, MDL
);
2635 if (packet_oro
.buffer
!= NULL
)
2636 data_string_forget(&packet_oro
, MDL
);
2638 /* Release any stale option states. */
2639 if (cli_enc_opt_state
!= NULL
)
2640 option_state_dereference(&cli_enc_opt_state
, MDL
);
2641 if (opt_state
!= NULL
)
2642 option_state_dereference(&opt_state
, MDL
);
2646 * Renew is when a client wants to extend its lease, at time T1.
2648 * We handle this the same as if the client wants a new lease, except
2649 * for the error code of when addresses don't match.
2652 /* TODO: reject unicast messages, unless we set unicast option */
2654 dhcpv6_renew(struct data_string
*reply
, struct packet
*packet
) {
2655 struct data_string client_id
;
2656 struct data_string server_id
;
2659 * Validate the request.
2661 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
2668 lease_to_client(reply
, packet
, &client_id
, &server_id
);
2673 data_string_forget(&server_id
, MDL
);
2674 data_string_forget(&client_id
, MDL
);
2678 * Rebind is when a client wants to extend its lease, at time T2.
2680 * We handle this the same as if the client wants a new lease, except
2681 * for the error code of when addresses don't match.
2685 dhcpv6_rebind(struct data_string
*reply
, struct packet
*packet
) {
2686 struct data_string client_id
;
2688 if (!valid_client_msg(packet
, &client_id
)) {
2692 lease_to_client(reply
, packet
, &client_id
, NULL
);
2694 data_string_forget(&client_id
, MDL
);
2698 ia_na_match_decline(const struct data_string
*client_id
,
2699 const struct data_string
*iaaddr
,
2700 struct iaaddr
*lease
)
2702 char tmp_addr
[INET6_ADDRSTRLEN
];
2704 log_error("Client %s reports address %s is "
2705 "already in use by another host!",
2706 print_hex_1(client_id
->len
, client_id
->data
, 60),
2707 inet_ntop(AF_INET6
, iaaddr
->data
,
2708 tmp_addr
, sizeof(tmp_addr
)));
2709 if (lease
!= NULL
) {
2710 decline_lease6(lease
->ipv6_pool
, lease
);
2711 write_ia(lease
->ia_na
);
2716 ia_na_nomatch_decline(const struct data_string
*client_id
,
2717 const struct data_string
*iaaddr
,
2718 u_int32_t
*ia_na_id
,
2719 struct packet
*packet
,
2724 char tmp_addr
[INET6_ADDRSTRLEN
];
2725 struct option_state
*host_opt_state
;
2728 log_info("Client %s declines address %s, which is not offered to it.",
2729 print_hex_1(client_id
->len
, client_id
->data
, 60),
2730 inet_ntop(AF_INET6
, iaaddr
->data
, tmp_addr
, sizeof(tmp_addr
)));
2733 * Create state for this IA_NA.
2735 host_opt_state
= NULL
;
2736 if (!option_state_allocate(&host_opt_state
, MDL
)) {
2737 log_error("ia_na_nomatch_decline: out of memory "
2738 "allocating option_state.");
2742 if (!set_status_code(STATUS_NoBinding
, "Decline for unknown address.",
2748 * Insure we have enough space
2750 if (reply_len
< (*reply_ofs
+ 16)) {
2751 log_error("ia_na_nomatch_decline: "
2752 "out of space for reply packet.");
2757 * Put our status code into the reply packet.
2759 len
= store_options6(reply_data
+(*reply_ofs
)+16,
2760 reply_len
-(*reply_ofs
)-16,
2761 host_opt_state
, packet
,
2762 required_opts_STATUS_CODE
, NULL
);
2765 * Store the non-encapsulated option data for this
2766 * IA_NA into our reply packet. Defined in RFC 3315,
2770 putUShort((unsigned char *)reply_data
+(*reply_ofs
), D6O_IA_NA
);
2772 putUShort((unsigned char *)reply_data
+(*reply_ofs
)+2, len
+ 12);
2773 /* IA_NA, copied from the client */
2774 memcpy(reply_data
+(*reply_ofs
)+4, ia_na_id
, 4);
2775 /* t1 and t2, odd that we need them, but here it is */
2776 putULong((unsigned char *)reply_data
+(*reply_ofs
)+8, 0);
2777 putULong((unsigned char *)reply_data
+(*reply_ofs
)+12, 0);
2780 * Get ready for next IA_NA.
2782 *reply_ofs
+= (len
+ 16);
2785 option_state_dereference(&host_opt_state
, MDL
);
2789 iterate_over_ia_na(struct data_string
*reply_ret
,
2790 struct packet
*packet
,
2791 const struct data_string
*client_id
,
2792 const struct data_string
*server_id
,
2793 const char *packet_type
,
2794 void (*ia_na_match
)(),
2795 void (*ia_na_nomatch
)())
2797 struct option_state
*opt_state
;
2798 struct host_decl
*packet_host
;
2799 struct option_cache
*ia
;
2800 struct option_cache
*oc
;
2801 /* cli_enc_... variables come from the IA_NA/IA_TA options */
2802 struct data_string cli_enc_opt_data
;
2803 struct option_state
*cli_enc_opt_state
;
2804 struct host_decl
*host
;
2805 struct option_state
*host_opt_state
;
2806 struct data_string iaaddr
;
2807 struct data_string fixed_addr
;
2808 int iaaddr_is_found
;
2809 char reply_data
[65536];
2810 struct dhcpv6_packet
*reply
= (struct dhcpv6_packet
*)reply_data
;
2811 int reply_ofs
= (int)((char *)reply
->options
- (char *)reply
);
2812 char status_msg
[32];
2813 struct iaaddr
*lease
;
2814 struct ia_na
*existing_ia_na
;
2816 struct data_string key
;
2820 * Initialize to empty values, in case we have to exit early.
2823 memset(&cli_enc_opt_data
, 0, sizeof(cli_enc_opt_data
));
2824 cli_enc_opt_state
= NULL
;
2825 memset(&iaaddr
, 0, sizeof(iaaddr
));
2826 memset(&fixed_addr
, 0, sizeof(fixed_addr
));
2827 host_opt_state
= NULL
;
2831 * Find the host record that matches from the packet, if any.
2834 if (!find_hosts_by_uid(&packet_host
,
2835 client_id
->data
, client_id
->len
, MDL
)) {
2838 * Note: In general, we don't expect a client to provide
2839 * enough information to match by option for these
2840 * types of messages, but if we don't have a UID
2841 * match we can check anyway.
2843 if (!find_hosts_by_option(&packet_host
,
2844 packet
, packet
->options
, MDL
)) {
2850 * Set our reply information.
2852 reply
->msg_type
= DHCPV6_REPLY
;
2853 memcpy(reply
->transaction_id
, packet
->dhcpv6_transaction_id
,
2854 sizeof(reply
->transaction_id
));
2857 * Build our option state for reply.
2860 if (!option_state_allocate(&opt_state
, MDL
)) {
2861 log_error("iterate_over_ia_na: no memory for option_state.");
2864 execute_statements_in_scope(NULL
, packet
, NULL
, NULL
,
2865 packet
->options
, opt_state
,
2866 &global_scope
, root_group
, NULL
);
2869 * RFC 3315, section 18.2.7 tells us which options to include.
2871 oc
= lookup_option(&dhcpv6_universe
, opt_state
, D6O_SERVERID
);
2873 if (!save_option_buffer(&dhcpv6_universe
, opt_state
, NULL
,
2874 (unsigned char *)server_duid
.data
,
2875 server_duid
.len
, D6O_SERVERID
, 0)) {
2876 log_error("iterate_over_ia_na: "
2877 "error saving server identifier.");
2882 if (!save_option_buffer(&dhcpv6_universe
, opt_state
,
2884 (unsigned char *)client_id
->data
,
2887 log_error("iterate_over_ia_na: "
2888 "error saving client identifier.");
2892 snprintf(status_msg
, sizeof(status_msg
), "%s received.", packet_type
);
2893 if (!set_status_code(STATUS_Success
, status_msg
, opt_state
)) {
2898 * Add our options that are not associated with any IA_NA or IA_TA.
2900 reply_ofs
+= store_options6(reply_data
+reply_ofs
,
2901 sizeof(reply_data
)-reply_ofs
,
2903 required_opts
, NULL
);
2906 * Loop through the IA_NA reported by the client, and deal with
2907 * addresses reported as already in use.
2909 for (ia
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
2910 ia
!= NULL
; ia
= ia
->next
) {
2911 iaaddr_is_found
= 0;
2913 if (!get_encapsulated_IA_state(&cli_enc_opt_state
,
2915 packet
, ia
, IA_NA_OFFSET
)) {
2919 iaid
= getULong(cli_enc_opt_data
.data
);
2922 * XXX: It is possible that we can get multiple addresses
2923 * sent by the client. We don't send multiple
2924 * addresses, so this indicates a client error.
2925 * We should check for multiple IAADDR options, log
2926 * if found, and set as an error.
2928 oc
= lookup_option(&dhcpv6_universe
, cli_enc_opt_state
,
2931 /* no address given for this IA, ignore */
2932 option_state_dereference(&cli_enc_opt_state
, MDL
);
2933 data_string_forget(&cli_enc_opt_data
, MDL
);
2937 memset(&iaaddr
, 0, sizeof(iaaddr
));
2938 if (!evaluate_option_cache(&iaaddr
, packet
, NULL
, NULL
,
2939 packet
->options
, NULL
,
2940 &global_scope
, oc
, MDL
)) {
2941 log_error("iterate_over_ia_na: "
2942 "error evaluating IAADDR.");
2947 * Now we need to figure out which host record matches
2948 * this IA_NA and IAADDR.
2950 * XXX: We don't currently track IA_NA separately, but
2951 * we will need to do this!
2954 if (!find_hosts_by_option(&host
, packet
,
2955 cli_enc_opt_state
, MDL
)) {
2956 if (packet_host
!= NULL
) {
2962 while (host
!= NULL
) {
2963 if (host
->fixed_addr
!= NULL
) {
2964 if (!evaluate_option_cache(&fixed_addr
, NULL
,
2966 NULL
, &global_scope
,
2969 log_error("iterate_over_ia_na: error "
2970 "evaluating host address.");
2973 if ((iaaddr
.len
>= 16) &&
2974 !memcmp(fixed_addr
.data
, iaaddr
.data
, 16)) {
2975 data_string_forget(&fixed_addr
, MDL
);
2978 data_string_forget(&fixed_addr
, MDL
);
2980 host
= host
->n_ipaddr
;
2983 if ((host
== NULL
) && (iaaddr
.len
>= IAADDR_OFFSET
)) {
2985 * Find existing IA_NA.
2987 if (ia_make_key(&key
, iaid
,
2988 (char *)client_id
->data
,
2990 MDL
) != ISC_R_SUCCESS
) {
2991 log_fatal("iterate_over_ia_na: no memory for "
2995 existing_ia_na
= NULL
;
2996 if (ia_na_hash_lookup(&existing_ia_na
, ia_na_active
,
2997 (unsigned char *)key
.data
,
3000 * Make sure this address is in the IA_NA.
3002 for (i
=0; i
<existing_ia_na
->num_iaaddr
; i
++) {
3004 struct in6_addr
*in6_addr
;
3006 tmp
= existing_ia_na
->iaaddr
[i
];
3007 in6_addr
= &tmp
->addr
;
3008 if (memcmp(in6_addr
,
3009 iaaddr
.data
, 16) == 0) {
3010 iaaddr_reference(&lease
,
3017 data_string_forget(&key
, MDL
);
3020 if ((host
!= NULL
) || (lease
!= NULL
)) {
3021 ia_na_match(client_id
, &iaaddr
, lease
);
3023 ia_na_nomatch(client_id
, &iaaddr
,
3024 (u_int32_t
*)cli_enc_opt_data
.data
,
3025 packet
, reply_data
, &reply_ofs
,
3026 sizeof(reply_data
));
3029 if (lease
!= NULL
) {
3030 iaaddr_dereference(&lease
, MDL
);
3033 data_string_forget(&iaaddr
, MDL
);
3034 option_state_dereference(&cli_enc_opt_state
, MDL
);
3035 data_string_forget(&cli_enc_opt_data
, MDL
);
3039 * Return our reply to the caller.
3041 reply_ret
->len
= reply_ofs
;
3042 reply_ret
->buffer
= NULL
;
3043 if (!buffer_allocate(&reply_ret
->buffer
, reply_ofs
, MDL
)) {
3044 log_fatal("No memory to store reply.");
3046 reply_ret
->data
= reply_ret
->buffer
->data
;
3047 memcpy(reply_ret
->buffer
->data
, reply
, reply_ofs
);
3050 if (lease
!= NULL
) {
3051 iaaddr_dereference(&lease
, MDL
);
3053 if (host_opt_state
!= NULL
) {
3054 option_state_dereference(&host_opt_state
, MDL
);
3056 if (fixed_addr
.buffer
!= NULL
) {
3057 data_string_forget(&fixed_addr
, MDL
);
3059 if (iaaddr
.buffer
!= NULL
) {
3060 data_string_forget(&iaaddr
, MDL
);
3062 if (cli_enc_opt_state
!= NULL
) {
3063 option_state_dereference(&cli_enc_opt_state
, MDL
);
3065 if (cli_enc_opt_data
.buffer
!= NULL
) {
3066 data_string_forget(&cli_enc_opt_data
, MDL
);
3068 if (opt_state
!= NULL
) {
3069 option_state_dereference(&opt_state
, MDL
);
3074 * Decline means a client has detected that something else is using an
3075 * address we gave it.
3077 * Since we're only dealing with fixed leases for now, there's not
3078 * much we can do, other that log the occurrence.
3080 * When we start issuing addresses from pools, then we will have to
3081 * record our declined addresses and issue another. In general with
3082 * IPv6 there is no worry about DoS by clients exhausting space, but
3083 * we still need to be aware of this possibility.
3086 /* TODO: reject unicast messages, unless we set unicast option */
3089 dhcpv6_decline(struct data_string
*reply
, struct packet
*packet
) {
3090 struct data_string client_id
;
3091 struct data_string server_id
;
3094 * Validate our input.
3096 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
3101 * And operate on each IA_NA in this packet.
3103 iterate_over_ia_na(reply
, packet
, &client_id
, &server_id
, "Decline",
3104 ia_na_match_decline
, ia_na_nomatch_decline
);
3108 ia_na_match_release(const struct data_string
*client_id
,
3109 const struct data_string
*iaaddr
,
3110 struct iaaddr
*lease
)
3112 char tmp_addr
[INET6_ADDRSTRLEN
];
3114 log_info("Client %s releases address %s",
3115 print_hex_1(client_id
->len
, client_id
->data
, 60),
3116 inet_ntop(AF_INET6
, iaaddr
->data
, tmp_addr
, sizeof(tmp_addr
)));
3117 if (lease
!= NULL
) {
3118 release_lease6(lease
->ipv6_pool
, lease
);
3119 write_ia(lease
->ia_na
);
3124 ia_na_nomatch_release(const struct data_string
*client_id
,
3125 const struct data_string
*iaaddr
,
3126 u_int32_t
*ia_na_id
,
3127 struct packet
*packet
,
3132 char tmp_addr
[INET6_ADDRSTRLEN
];
3133 struct option_state
*host_opt_state
;
3136 log_info("Client %s releases address %s, which is not leased to it.",
3137 print_hex_1(client_id
->len
, client_id
->data
, 60),
3138 inet_ntop(AF_INET6
, iaaddr
->data
, tmp_addr
, sizeof(tmp_addr
)));
3141 * Create state for this IA_NA.
3143 host_opt_state
= NULL
;
3144 if (!option_state_allocate(&host_opt_state
, MDL
)) {
3145 log_error("ia_na_nomatch_release: out of memory "
3146 "allocating option_state.");
3150 if (!set_status_code(STATUS_NoBinding
,
3151 "Release for non-leased address.",
3157 * Insure we have enough space
3159 if (reply_len
< (*reply_ofs
+ 16)) {
3160 log_error("ia_na_nomatch_release: "
3161 "out of space for reply packet.");
3166 * Put our status code into the reply packet.
3168 len
= store_options6(reply_data
+(*reply_ofs
)+16,
3169 reply_len
-(*reply_ofs
)-16,
3170 host_opt_state
, packet
,
3171 required_opts_STATUS_CODE
, NULL
);
3174 * Store the non-encapsulated option data for this
3175 * IA_NA into our reply packet. Defined in RFC 3315,
3179 putUShort((unsigned char *)reply_data
+(*reply_ofs
), D6O_IA_NA
);
3181 putUShort((unsigned char *)reply_data
+(*reply_ofs
)+2, len
+ 12);
3182 /* IA_NA, copied from the client */
3183 memcpy(reply_data
+(*reply_ofs
)+4, ia_na_id
, 4);
3184 /* t1 and t2, odd that we need them, but here it is */
3185 putULong((unsigned char *)reply_data
+(*reply_ofs
)+8, 0);
3186 putULong((unsigned char *)reply_data
+(*reply_ofs
)+12, 0);
3189 * Get ready for next IA_NA.
3191 *reply_ofs
+= (len
+ 16);
3194 option_state_dereference(&host_opt_state
, MDL
);
3198 * Release means a client is done with the addresses.
3201 /* TODO: reject unicast messages, unless we set unicast option */
3203 dhcpv6_release(struct data_string
*reply
, struct packet
*packet
) {
3204 struct data_string client_id
;
3205 struct data_string server_id
;
3208 * Validate our input.
3210 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
3215 * And operate on each IA_NA in this packet.
3217 iterate_over_ia_na(reply
, packet
, &client_id
, &server_id
, "Release",
3218 ia_na_match_release
, ia_na_nomatch_release
);
3220 data_string_forget(&server_id
, MDL
);
3221 data_string_forget(&client_id
, MDL
);
3225 * Information-Request is used by clients who have obtained an address
3226 * from other means, but want configuration information from the server.
3230 dhcpv6_information_request(struct data_string
*reply
, struct packet
*packet
) {
3231 struct data_string client_id
;
3232 struct data_string server_id
;
3235 * Validate our input.
3237 if (!valid_client_info_req(packet
, &server_id
)) {
3242 * Get our client ID, if there is one.
3244 memset(&client_id
, 0, sizeof(client_id
));
3245 if (get_client_id(packet
, &client_id
) != ISC_R_SUCCESS
) {
3246 data_string_forget(&client_id
, MDL
);
3250 * Use the lease_to_client() function. This will work fine,
3251 * because the valid_client_info_req() insures that we
3252 * don't have any IA_NA or IA_TA that would cause us to
3253 * allocate addresses to the client.
3255 lease_to_client(reply
, packet
, &client_id
,
3256 server_id
.data
!= NULL
? &server_id
: NULL
);
3261 if (client_id
.data
!= NULL
) {
3262 data_string_forget(&client_id
, MDL
);
3264 data_string_forget(&server_id
, MDL
);
3268 * The Relay-forw message is sent by relays. It typically contains a
3269 * single option, which encapsulates an entire packet.
3271 * We need to build an encapsulated reply.
3274 /* XXX: this is very, very similar to do_packet6(), and should probably
3275 be combined in a clever way */
3277 dhcpv6_relay_forw(struct data_string
*reply_ret
, struct packet
*packet
) {
3278 struct dhcpv6_relay_packet reply
;
3279 struct option_cache
*oc
;
3280 struct data_string enc_opt_data
;
3281 struct packet
*enc_packet
;
3282 unsigned char msg_type
;
3283 const struct dhcpv6_packet
*msg
;
3284 const struct dhcpv6_relay_packet
*relay
;
3285 struct data_string enc_reply
;
3286 char link_addr
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
3287 char peer_addr
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
3288 struct data_string interface_id
;
3291 * Initialize variables for early exit.
3293 memset(&enc_opt_data
, 0, sizeof(enc_opt_data
));
3295 memset(&enc_reply
, 0, sizeof(enc_reply
));
3296 memset(&interface_id
, 0, sizeof(interface_id
));
3299 * Get our encapsulated relay message.
3301 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_RELAY_MSG
);
3303 inet_ntop(AF_INET6
, &packet
->dhcpv6_link_address
,
3304 link_addr
, sizeof(link_addr
));
3305 inet_ntop(AF_INET6
, &packet
->dhcpv6_peer_address
,
3306 peer_addr
, sizeof(peer_addr
));
3307 log_info("Relay-forward from %s with link address=%s and "
3308 "peer address=%s missing Relay Message option.",
3309 piaddr(packet
->client_addr
), link_addr
, peer_addr
);
3313 memset(&enc_opt_data
, 0, sizeof(enc_opt_data
));
3314 if (!evaluate_option_cache(&enc_opt_data
, NULL
, NULL
, NULL
,
3315 NULL
, NULL
, &global_scope
, oc
, MDL
)) {
3316 log_error("dhcpv6_forw_relay: error evaluating "
3317 "relayed message.");
3321 if (!packet6_len_okay((char *)enc_opt_data
.data
, enc_opt_data
.len
)) {
3322 log_error("dhcpv6_forw_relay: encapsulated packet too short.");
3327 * Build a packet structure from this encapsulated packet.
3330 if (!packet_allocate(&enc_packet
, MDL
)) {
3331 log_error("dhcpv6_forw_relay: "
3332 "no memory for encapsulated packet.");
3336 if (!option_state_allocate(&enc_packet
->options
, MDL
)) {
3337 log_error("dhcpv6_forw_relay: "
3338 "no memory for encapsulated packet's options.");
3342 enc_packet
->client_port
= packet
->client_port
;
3343 enc_packet
->client_addr
= packet
->client_addr
;
3344 enc_packet
->dhcpv6_container_packet
= packet
;
3346 msg_type
= enc_opt_data
.data
[0];
3347 if ((msg_type
== DHCPV6_RELAY_FORW
) ||
3348 (msg_type
== DHCPV6_RELAY_REPL
)) {
3349 relay
= (struct dhcpv6_relay_packet
*)enc_opt_data
.data
;
3350 enc_packet
->dhcpv6_msg_type
= relay
->msg_type
;
3352 /* relay-specific data */
3353 enc_packet
->dhcpv6_hop_count
= relay
->hop_count
;
3354 memcpy(&enc_packet
->dhcpv6_link_address
,
3355 relay
->link_address
, sizeof(relay
->link_address
));
3356 memcpy(&enc_packet
->dhcpv6_peer_address
,
3357 relay
->peer_address
, sizeof(relay
->peer_address
));
3359 if (!parse_option_buffer(enc_packet
->options
,
3361 enc_opt_data
.len
-sizeof(*relay
),
3362 &dhcpv6_universe
)) {
3363 /* no logging here, as parse_option_buffer() logs all
3364 cases where it fails */
3368 msg
= (struct dhcpv6_packet
*)enc_opt_data
.data
;
3369 enc_packet
->dhcpv6_msg_type
= msg
->msg_type
;
3371 /* message-specific data */
3372 memcpy(enc_packet
->dhcpv6_transaction_id
,
3373 msg
->transaction_id
,
3374 sizeof(enc_packet
->dhcpv6_transaction_id
));
3376 if (!parse_option_buffer(enc_packet
->options
,
3378 enc_opt_data
.len
-sizeof(*msg
),
3379 &dhcpv6_universe
)) {
3380 /* no logging here, as parse_option_buffer() logs all
3381 cases where it fails */
3387 * This is recursive. It is possible to exceed maximum packet size.
3388 * XXX: This will cause the packet send to fail.
3390 build_dhcpv6_reply(&enc_reply
, enc_packet
);
3393 * If we got no encapsulated data, then it is discarded, and
3394 * our reply-forw is also discarded.
3396 if (enc_reply
.data
== NULL
) {
3401 * Append the interface-id if present
3403 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_INTERFACE_ID
);
3405 memset(&interface_id
, 0, sizeof(interface_id
));
3406 if (!evaluate_option_cache(&interface_id
, NULL
, NULL
, NULL
,
3407 NULL
, NULL
, &global_scope
,
3409 log_error("dhcpv6_forw_relay: error evaluating "
3416 * Packet header stuff all comes from the forward message.
3418 reply
.msg_type
= DHCPV6_RELAY_REPL
;
3419 reply
.hop_count
= packet
->dhcpv6_hop_count
;
3420 memcpy(reply
.link_address
, &packet
->dhcpv6_link_address
,
3421 sizeof(reply
.link_address
));
3422 memcpy(reply
.peer_address
, &packet
->dhcpv6_peer_address
,
3423 sizeof(reply
.peer_address
));
3426 * Copy our encapsulated stuff for caller.
3428 reply_ret
->len
= sizeof(reply
) + 4 + enc_reply
.len
;
3429 if (interface_id
.data
!= NULL
) {
3430 reply_ret
->len
+= 4 + interface_id
.len
;
3433 * XXX: We should not allow this to happen, perhaps by letting
3434 * build_dhcp_reply() know our space remaining.
3436 if (reply_ret
->len
>= 65536) {
3437 log_error("dhcpv6_forw_relay: RELAY-REPL too big (%d bytes)",
3441 reply_ret
->buffer
= NULL
;
3442 if (!buffer_allocate(&reply_ret
->buffer
, reply_ret
->len
, MDL
)) {
3443 log_fatal("No memory to store reply.");
3445 reply_ret
->data
= reply_ret
->buffer
->data
;
3446 memcpy(reply_ret
->buffer
->data
, &reply
, sizeof(reply
));
3447 putShort(reply_ret
->buffer
->data
+sizeof(reply
), D6O_RELAY_MSG
);
3448 putShort(reply_ret
->buffer
->data
+sizeof(reply
)+2, enc_reply
.len
);
3449 memcpy(reply_ret
->buffer
->data
+sizeof(reply
)+4,
3450 enc_reply
.data
, enc_reply
.len
);
3451 if (interface_id
.data
!= NULL
) {
3452 putShort(reply_ret
->buffer
->data
+sizeof(reply
)+4+enc_reply
.len
,
3454 putShort(reply_ret
->buffer
->data
+sizeof(reply
)+6+enc_reply
.len
,
3456 memcpy(reply_ret
->buffer
->data
+sizeof(reply
)+8+enc_reply
.len
,
3457 interface_id
.data
, interface_id
.len
);
3461 if (interface_id
.data
!= NULL
) {
3462 data_string_forget(&interface_id
, MDL
);
3464 if (enc_reply
.data
!= NULL
) {
3465 data_string_forget(&enc_reply
, MDL
);
3467 if (enc_opt_data
.data
!= NULL
) {
3468 data_string_forget(&enc_opt_data
, MDL
);
3470 if (enc_packet
!= NULL
) {
3471 packet_dereference(&enc_packet
, MDL
);
3476 dhcpv6_discard(struct packet
*packet
) {
3477 /* INSIST(packet->msg_type > 0); */
3478 /* INSIST(packet->msg_type < dhcpv6_type_name_max); */
3480 log_debug("Discarding %s from %s; message type not handled by server",
3481 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
3482 piaddr(packet
->client_addr
));
3486 build_dhcpv6_reply(struct data_string
*reply
, struct packet
*packet
) {
3487 memset(reply
, 0, sizeof(*reply
));
3488 switch (packet
->dhcpv6_msg_type
) {
3489 case DHCPV6_SOLICIT
:
3490 dhcpv6_solicit(reply
, packet
);
3492 case DHCPV6_ADVERTISE
:
3493 dhcpv6_discard(packet
);
3495 case DHCPV6_REQUEST
:
3496 dhcpv6_request(reply
, packet
);
3498 case DHCPV6_CONFIRM
:
3499 dhcpv6_confirm(reply
, packet
);
3502 dhcpv6_renew(reply
, packet
);
3505 dhcpv6_rebind(reply
, packet
);
3508 dhcpv6_discard(packet
);
3510 case DHCPV6_RELEASE
:
3511 dhcpv6_release(reply
, packet
);
3513 case DHCPV6_DECLINE
:
3514 dhcpv6_decline(reply
, packet
);
3516 case DHCPV6_RECONFIGURE
:
3517 dhcpv6_discard(packet
);
3519 case DHCPV6_INFORMATION_REQUEST
:
3520 dhcpv6_information_request(reply
, packet
);
3522 case DHCPV6_RELAY_FORW
:
3523 dhcpv6_relay_forw(reply
, packet
);
3525 case DHCPV6_RELAY_REPL
:
3526 dhcpv6_discard(packet
);
3529 /* XXX: would be nice if we had "notice" level,
3530 as syslog, for this */
3531 log_info("Discarding unknown DHCPv6 message type %d "
3532 "from %s", packet
->dhcpv6_msg_type
,
3533 piaddr(packet
->client_addr
));
3538 log_packet_in(const struct packet
*packet
) {
3539 struct data_string s
;
3541 char tmp_addr
[INET6_ADDRSTRLEN
];
3544 memset(&s
, 0, sizeof(s
));
3546 if (packet
->dhcpv6_msg_type
< dhcpv6_type_name_max
) {
3547 data_string_sprintfa(&s
, "%s message from %s port %d",
3548 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
3549 piaddr(packet
->client_addr
),
3550 ntohs(packet
->client_port
));
3552 data_string_sprintfa(&s
,
3553 "Unknown message type %d from %s port %d",
3554 packet
->dhcpv6_msg_type
,
3555 piaddr(packet
->client_addr
),
3556 ntohs(packet
->client_port
));
3558 if ((packet
->dhcpv6_msg_type
== DHCPV6_RELAY_FORW
) ||
3559 (packet
->dhcpv6_msg_type
== DHCPV6_RELAY_REPL
)) {
3560 addr
= &packet
->dhcpv6_link_address
;
3561 data_string_sprintfa(&s
, ", link address %s",
3562 inet_ntop(AF_INET6
, addr
,
3563 tmp_addr
, sizeof(tmp_addr
)));
3564 addr
= &packet
->dhcpv6_peer_address
;
3565 data_string_sprintfa(&s
, ", peer address %s",
3566 inet_ntop(AF_INET6
, addr
,
3567 tmp_addr
, sizeof(tmp_addr
)));
3570 memcpy(((char *)&tid
)+1, packet
->dhcpv6_transaction_id
, 3);
3571 data_string_sprintfa(&s
, ", transaction ID 0x%06X", tid
);
3574 oc = lookup_option(&dhcpv6_universe, packet->options,
3577 memset(&tmp_ds, 0, sizeof(tmp_ds_));
3578 if (!evaluate_option_cache(&tmp_ds, packet, NULL, NULL,
3579 packet->options, NULL,
3580 &global_scope, oc, MDL)) {
3581 log_error("Error evaluating Client Identifier");
3583 data_strint_sprintf(&s, ", client ID %s",
3585 data_string_forget(&tmp_ds, MDL);
3591 log_info("%s", s
.data
);
3593 data_string_forget(&s
, MDL
);
3597 dhcpv6(struct packet
*packet
) {
3598 struct data_string reply
;
3599 struct sockaddr_in6 to_addr
;
3603 * Log a message that we received this packet.
3605 log_packet_in(packet
);
3608 * Build our reply packet.
3610 build_dhcpv6_reply(&reply
, packet
);
3612 if (reply
.data
!= NULL
) {
3614 * Send our reply, if we have one.
3616 memset(&to_addr
, 0, sizeof(to_addr
));
3617 to_addr
.sin6_family
= AF_INET6
;
3618 if ((packet
->dhcpv6_msg_type
== DHCPV6_RELAY_FORW
) ||
3619 (packet
->dhcpv6_msg_type
== DHCPV6_RELAY_REPL
)) {
3620 to_addr
.sin6_port
= local_port
;
3622 to_addr
.sin6_port
= remote_port
;
3624 /* For testing, we reply to the sending port, so we don't need a root client */
3625 to_addr
.sin6_port
= packet
->client_port
;
3626 memcpy(&to_addr
.sin6_addr
, packet
->client_addr
.iabuf
,
3627 sizeof(to_addr
.sin6_addr
));
3629 log_info("Sending %s to %s port %d",
3630 dhcpv6_type_names
[reply
.data
[0]],
3631 piaddr(packet
->client_addr
),
3632 ntohs(to_addr
.sin6_port
));
3634 send_ret
= send_packet6(packet
->interface
,
3635 reply
.data
, reply
.len
, &to_addr
);
3636 if (send_ret
!= reply
.len
) {
3637 log_error("dhcpv6: send_packet6() sent %d of %d bytes",
3638 send_ret
, reply
.len
);
3640 data_string_forget(&reply
, MDL
);
3645 seek_shared_host(struct host_decl
**hp
, struct shared_network
*shared
) {
3646 struct host_decl
*nofixed
= NULL
;
3647 struct host_decl
*seek
, *hold
= NULL
;
3650 * Seek forward through fixed addresses for the right broadcast
3653 host_reference(&hold
, *hp
, MDL
);
3654 host_dereference(hp
, MDL
);
3656 while (seek
!= NULL
) {
3657 if (seek
->fixed_addr
== NULL
)
3659 else if (fixed_matches_shared(seek
, shared
))
3662 seek
= seek
->n_ipaddr
;
3665 if ((seek
== NULL
) && (nofixed
!= NULL
))
3669 host_reference(hp
, seek
, MDL
);
3672 static isc_boolean_t
3673 fixed_matches_shared(struct host_decl
*host
, struct shared_network
*shared
) {
3674 struct subnet
*subnet
;
3675 struct data_string addr
;
3676 isc_boolean_t matched
;
3679 if (host
->fixed_addr
== NULL
)
3682 memset(&addr
, 0, sizeof(addr
));
3683 if (!evaluate_option_cache(&addr
, NULL
, NULL
, NULL
, NULL
, NULL
,
3684 &global_scope
, host
->fixed_addr
, MDL
))
3687 if (addr
.len
< 16) {
3688 data_string_forget(&addr
, MDL
);
3693 memcpy(fixed
.iabuf
, addr
.data
, 16);
3695 matched
= ISC_FALSE
;
3696 for (subnet
= shared
->subnets
; subnet
!= NULL
;
3697 subnet
= subnet
->next_sibling
) {
3698 if (addr_eq(subnet_number(fixed
, subnet
->netmask
),
3705 data_string_forget(&addr
, MDL
);