2 * Copyright (C) 2006-2007 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_addresses
;
53 isc_boolean_t ia_addrs_included
;
54 isc_boolean_t static_lease
;
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(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 * DUID time starts 2000-01-01.
117 * This constant is the number of seconds since 1970-01-01,
118 * when the Unix epoch began.
120 #define DUID_TIME_EPOCH 946684800
123 * This function returns the time since DUID time start for the
124 * given time_t value.
127 duid_time(time_t when
) {
129 * This time is modulo 2^32.
131 while ((when
- DUID_TIME_EPOCH
) > 4294967295u) {
132 /* use 2^31 to avoid spurious compiler warnings */
137 return when
- DUID_TIME_EPOCH
;
144 * This must remain the same for the lifetime of this server, because
145 * clients return the server DUID that we sent them in Request packets.
147 * We pick the server DUID like this:
149 * 1. Check dhcpd.conf - any value the administrator has configured
150 * overrides any possible values.
151 * 2. Check the leases.txt - we want to use the previous value if
153 * 3. Check if dhcpd.conf specifies a type of server DUID to use,
154 * and generate that type.
155 * 4. Generate a type 1 (time + hardware address) DUID.
157 static struct data_string server_duid
;
160 * Check if the server_duid has been set.
163 server_duid_isset(void) {
164 return (server_duid
.data
!= NULL
);
168 * Return the server_duid.
171 copy_server_duid(struct data_string
*ds
, const char *file
, int line
) {
172 data_string_copy(ds
, &server_duid
, file
, line
);
176 * Set the server DUID to a specified value. This is used when
177 * the server DUID is stored in persistent memory (basically the
181 set_server_duid(struct data_string
*new_duid
) {
182 /* INSIST(new_duid != NULL); */
183 /* INSIST(new_duid->data != NULL); */
185 if (server_duid_isset()) {
186 data_string_forget(&server_duid
, MDL
);
188 data_string_copy(&server_duid
, new_duid
, MDL
);
193 * Set the server DUID based on the D6O_SERVERID option. This handles
194 * the case where the administrator explicitly put it in the dhcpd.conf
198 set_server_duid_from_option(void) {
199 struct option_state
*opt_state
;
200 struct option_cache
*oc
;
201 struct data_string option_duid
;
202 isc_result_t ret_val
;
205 if (!option_state_allocate(&opt_state
, MDL
)) {
206 log_fatal("No memory for server DUID.");
209 execute_statements_in_scope(NULL
, NULL
, NULL
, NULL
, NULL
,
210 opt_state
, &global_scope
, root_group
, NULL
);
212 oc
= lookup_option(&dhcpv6_universe
, opt_state
, D6O_SERVERID
);
214 ret_val
= ISC_R_NOTFOUND
;
216 memset(&option_duid
, 0, sizeof(option_duid
));
217 if (!evaluate_option_cache(&option_duid
, NULL
, NULL
, NULL
,
218 opt_state
, NULL
, &global_scope
,
220 ret_val
= ISC_R_UNEXPECTED
;
222 set_server_duid(&option_duid
);
223 data_string_forget(&option_duid
, MDL
);
224 ret_val
= ISC_R_SUCCESS
;
228 option_state_dereference(&opt_state
, MDL
);
234 * DUID layout, as defined in RFC 3315, section 9.
236 * We support type 1 (hardware address plus time) and type 3 (hardware
239 * We can support type 2 for specific vendors in the future, if they
240 * publish the specification. And of course there may be additional
243 static int server_duid_type
= DUID_LLT
;
249 set_server_duid_type(int type
) {
250 server_duid_type
= type
;
254 * Generate a new server DUID. This is done if there was no DUID in
255 * the leases.txt or in the dhcpd.conf file.
258 generate_new_server_duid(void) {
259 struct interface_info
*p
;
261 struct data_string generated_duid
;
264 * Verify we have a type that we support.
266 if ((server_duid_type
!= DUID_LL
) && (server_duid_type
!= DUID_LLT
)) {
267 log_error("Invalid DUID type %d specified, "
268 "only LL and LLT types supported", server_duid_type
);
269 return ISC_R_INVALIDARG
;
273 * Find an interface with a hardware address.
276 for (p
= interfaces
; p
!= NULL
; p
= p
->next
) {
277 if (p
->hw_address
.hlen
> 0) {
282 return ISC_R_UNEXPECTED
;
288 memset(&generated_duid
, 0, sizeof(generated_duid
));
289 if (server_duid_type
== DUID_LLT
) {
290 time_val
= duid_time(time(NULL
));
291 generated_duid
.len
= 8 + p
->hw_address
.hlen
- 1;
292 if (!buffer_allocate(&generated_duid
.buffer
,
293 generated_duid
.len
, MDL
)) {
294 log_fatal("No memory for server DUID.");
296 generated_duid
.data
= generated_duid
.buffer
->data
;
297 putUShort(generated_duid
.buffer
->data
, DUID_LLT
);
298 putUShort(generated_duid
.buffer
->data
+ 2,
299 p
->hw_address
.hbuf
[0]);
300 putULong(generated_duid
.buffer
->data
+ 4, time_val
);
301 memcpy(generated_duid
.buffer
->data
+ 8,
302 p
->hw_address
.hbuf
+1, p
->hw_address
.hlen
-1);
303 } else if (server_duid_type
== DUID_LL
) {
304 generated_duid
.len
= 4 + p
->hw_address
.hlen
- 1;
305 if (!buffer_allocate(&generated_duid
.buffer
,
306 generated_duid
.len
, MDL
)) {
307 log_fatal("No memory for server DUID.");
309 generated_duid
.data
= generated_duid
.buffer
->data
;
310 putUShort(generated_duid
.buffer
->data
, DUID_LL
);
311 putUShort(generated_duid
.buffer
->data
+ 2,
312 p
->hw_address
.hbuf
[0]);
313 memcpy(generated_duid
.buffer
->data
+4,
314 p
->hw_address
.hbuf
+1, p
->hw_address
.hlen
-1);
316 log_fatal("Unsupported server DUID type %d.", server_duid_type
);
319 set_server_duid(&generated_duid
);
320 data_string_forget(&generated_duid
, MDL
);
322 return ISC_R_SUCCESS
;
326 * Get the client identifier from the packet.
329 get_client_id(struct packet
*packet
, struct data_string
*client_id
) {
330 struct option_cache
*oc
;
333 * Verify our client_id structure is empty.
335 if ((client_id
->data
!= NULL
) || (client_id
->len
!= 0)) {
336 return ISC_R_INVALIDARG
;
339 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_CLIENTID
);
341 return ISC_R_NOTFOUND
;
344 if (!evaluate_option_cache(client_id
, packet
, NULL
, NULL
,
345 packet
->options
, NULL
,
346 &global_scope
, oc
, MDL
)) {
347 return ISC_R_FAILURE
;
350 return ISC_R_SUCCESS
;
354 * Message validation, defined in RFC 3315, sections 15.2, 15.5, 15.7:
356 * Servers MUST discard any Solicit messages that do not include a
357 * Client Identifier option or that do include a Server Identifier
361 valid_client_msg(struct packet
*packet
, struct data_string
*client_id
) {
363 struct option_cache
*oc
;
364 struct data_string data
;
367 memset(client_id
, 0, sizeof(*client_id
));
368 memset(&data
, 0, sizeof(data
));
370 switch (get_client_id(packet
, client_id
)) {
374 log_debug("Discarding %s from %s; "
375 "client identifier missing",
376 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
377 piaddr(packet
->client_addr
));
380 log_error("Error processing %s from %s; "
381 "unable to evaluate Client Identifier",
382 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
383 piaddr(packet
->client_addr
));
388 * Required by RFC 3315, section 15.
390 if (packet
->unicast
) {
391 log_debug("Discarding %s from %s; packet sent unicast "
393 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
394 piaddr(packet
->client_addr
),
395 print_hex_1(client_id
->len
, client_id
->data
, 60));
400 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
402 if (evaluate_option_cache(&data
, packet
, NULL
, NULL
,
403 packet
->options
, NULL
,
404 &global_scope
, oc
, MDL
)) {
405 log_debug("Discarding %s from %s; "
406 "server identifier found "
407 "(CLIENTID %s, SERVERID %s)",
408 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
409 piaddr(packet
->client_addr
),
410 print_hex_1(client_id
->len
,
411 client_id
->data
, 60),
412 print_hex_2(data
.len
,
415 log_debug("Discarding %s from %s; "
416 "server identifier found "
418 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
419 print_hex_1(client_id
->len
,
420 client_id
->data
, 60),
421 piaddr(packet
->client_addr
));
431 data_string_forget(&data
, MDL
);
434 if (client_id
->len
> 0) {
435 data_string_forget(client_id
, MDL
);
442 * Response validation, defined in RFC 3315, sections 15.4, 15.6, 15.8,
443 * 15.9 (slightly different wording, but same meaning):
445 * Servers MUST discard any received Request message that meet any of
446 * the following conditions:
448 * - the message does not include a Server Identifier option.
449 * - the contents of the Server Identifier option do not match the
451 * - the message does not include a Client Identifier option.
454 valid_client_resp(struct packet
*packet
,
455 struct data_string
*client_id
,
456 struct data_string
*server_id
)
459 struct option_cache
*oc
;
461 /* INSIST((duid.data != NULL) && (duid.len > 0)); */
464 memset(client_id
, 0, sizeof(*client_id
));
465 memset(server_id
, 0, sizeof(*server_id
));
467 switch (get_client_id(packet
, client_id
)) {
471 log_debug("Discarding %s from %s; "
472 "client identifier missing",
473 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
474 piaddr(packet
->client_addr
));
477 log_error("Error processing %s from %s; "
478 "unable to evaluate Client Identifier",
479 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
480 piaddr(packet
->client_addr
));
484 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
486 log_debug("Discarding %s from %s: "
487 "server identifier missing (CLIENTID %s)",
488 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
489 piaddr(packet
->client_addr
),
490 print_hex_1(client_id
->len
, client_id
->data
, 60));
493 if (!evaluate_option_cache(server_id
, packet
, NULL
, NULL
,
494 packet
->options
, NULL
,
495 &global_scope
, oc
, MDL
)) {
496 log_error("Error processing %s from %s; "
497 "unable to evaluate Server Identifier (CLIENTID %s)",
498 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
499 piaddr(packet
->client_addr
),
500 print_hex_1(client_id
->len
, client_id
->data
, 60));
503 if ((server_duid
.len
!= server_id
->len
) ||
504 (memcmp(server_duid
.data
, server_id
->data
, server_duid
.len
) != 0)) {
505 log_debug("Discarding %s from %s; "
506 "not our server identifier "
507 "(CLIENTID %s, SERVERID %s, server DUID %s)",
508 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
509 piaddr(packet
->client_addr
),
510 print_hex_1(client_id
->len
, client_id
->data
, 60),
511 print_hex_2(server_id
->len
, server_id
->data
, 60),
512 print_hex_3(server_duid
.len
, server_duid
.data
, 60));
521 if (server_id
->len
> 0) {
522 data_string_forget(server_id
, MDL
);
524 if (client_id
->len
> 0) {
525 data_string_forget(client_id
, MDL
);
532 * Information request validation, defined in RFC 3315, section 15.12:
534 * Servers MUST discard any received Information-request message that
535 * meets any of the following conditions:
537 * - The message includes a Server Identifier option and the DUID in
538 * the option does not match the server's DUID.
540 * - The message includes an IA option.
543 valid_client_info_req(struct packet
*packet
, struct data_string
*server_id
) {
545 struct option_cache
*oc
;
546 struct data_string client_id
;
547 char client_id_str
[80]; /* print_hex_1() uses maximum 60 characters,
548 plus a few more for extra information */
551 memset(server_id
, 0, sizeof(*server_id
));
554 * Make a string that we can print out to give more
555 * information about the client if we need to.
557 * By RFC 3315, Section 18.1.5 clients SHOULD have a
558 * client-id on an Information-request packet, but it
559 * is not strictly necessary.
561 if (get_client_id(packet
, &client_id
) == ISC_R_SUCCESS
) {
562 snprintf(client_id_str
, sizeof(client_id_str
), " (CLIENTID %s)",
563 print_hex_1(client_id
.len
, client_id
.data
, 60));
564 data_string_forget(&client_id
, MDL
);
566 client_id_str
[0] = '\0';
570 * Required by RFC 3315, section 15.
572 if (packet
->unicast
) {
573 log_debug("Discarding %s from %s; packet sent unicast%s",
574 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
575 piaddr(packet
->client_addr
), client_id_str
);
579 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
581 log_debug("Discarding %s from %s; "
582 "IA_NA option present%s",
583 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
584 piaddr(packet
->client_addr
), client_id_str
);
587 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_TA
);
589 log_debug("Discarding %s from %s; "
590 "IA_TA option present%s",
591 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
592 piaddr(packet
->client_addr
), client_id_str
);
596 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_SERVERID
);
598 if (!evaluate_option_cache(server_id
, packet
, NULL
, NULL
,
599 packet
->options
, NULL
,
600 &global_scope
, oc
, MDL
)) {
601 log_error("Error processing %s from %s; "
602 "unable to evaluate Server Identifier%s",
603 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
604 piaddr(packet
->client_addr
), client_id_str
);
607 if ((server_duid
.len
!= server_id
->len
) ||
608 (memcmp(server_duid
.data
, server_id
->data
,
609 server_duid
.len
) != 0)) {
610 log_debug("Discarding %s from %s; "
611 "not our server identifier "
612 "(SERVERID %s, server DUID %s)%s",
613 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
614 piaddr(packet
->client_addr
),
615 print_hex_1(server_id
->len
,
616 server_id
->data
, 60),
617 print_hex_2(server_duid
.len
,
618 server_duid
.data
, 60),
629 if (server_id
->len
> 0) {
630 data_string_forget(server_id
, MDL
);
637 * Options that we want to send, in addition to what was requested
640 static const int required_opts
[] = {
647 static const int required_opts_solicit
[] = {
659 static const int required_opts_IA_NA
[] = {
665 static const int required_opts_STATUS_CODE
[] = {
671 * Extracts from packet contents an IA_* option, storing the IA structure
672 * in its entirety in enc_opt_data, and storing any decoded DHCPv6 options
673 * in enc_opt_state for later lookup and evaluation. The 'offset' indicates
674 * where in the IA_* the DHCPv6 options commence.
677 get_encapsulated_IA_state(struct option_state
**enc_opt_state
,
678 struct data_string
*enc_opt_data
,
679 struct packet
*packet
,
680 struct option_cache
*oc
,
684 * Get the raw data for the encapsulated options.
686 memset(enc_opt_data
, 0, sizeof(*enc_opt_data
));
687 if (!evaluate_option_cache(enc_opt_data
, packet
,
688 NULL
, NULL
, packet
->options
, NULL
,
689 &global_scope
, oc
, MDL
)) {
690 log_error("get_encapsulated_IA_state: "
691 "error evaluating raw option.");
694 if (enc_opt_data
->len
< offset
) {
695 log_error("get_encapsulated_IA_state: raw option too small.");
696 data_string_forget(enc_opt_data
, MDL
);
701 * Now create the option state structure, and pass it to the
702 * function that parses options.
704 *enc_opt_state
= NULL
;
705 if (!option_state_allocate(enc_opt_state
, MDL
)) {
706 log_error("get_encapsulated_IA_state: no memory for options.");
707 data_string_forget(enc_opt_data
, MDL
);
710 if (!parse_option_buffer(*enc_opt_state
,
711 enc_opt_data
->data
+ offset
,
712 enc_opt_data
->len
- offset
,
714 log_error("get_encapsulated_IA_state: error parsing options.");
715 option_state_dereference(enc_opt_state
, MDL
);
716 data_string_forget(enc_opt_data
, MDL
);
724 set_status_code(u_int16_t status_code
, const char *status_message
,
725 struct option_state
*opt_state
)
727 struct data_string d
;
730 memset(&d
, 0, sizeof(d
));
731 d
.len
= sizeof(status_code
) + strlen(status_message
);
732 if (!buffer_allocate(&d
.buffer
, d
.len
, MDL
)) {
733 log_fatal("set_status_code: no memory for status code.");
735 d
.data
= d
.buffer
->data
;
736 putUShort(d
.buffer
->data
, status_code
);
737 memcpy(d
.buffer
->data
+ sizeof(status_code
),
738 status_message
, d
.len
- sizeof(status_code
));
739 if (!save_option_buffer(&dhcpv6_universe
, opt_state
,
740 d
.buffer
, (unsigned char *)d
.data
, d
.len
,
741 D6O_STATUS_CODE
, 0)) {
742 log_error("set_status_code: error saving status code.");
747 data_string_forget(&d
, MDL
);
752 * We have a set of operations we do to set up the reply packet, which
753 * is the same for many message types.
756 start_reply(struct packet
*packet
,
757 const struct data_string
*client_id
,
758 const struct data_string
*server_id
,
759 struct option_state
**opt_state
,
760 struct dhcpv6_packet
*reply
)
762 struct option_cache
*oc
;
763 const unsigned char *server_id_data
;
767 * Build our option state for reply.
770 if (!option_state_allocate(opt_state
, MDL
)) {
771 log_error("start_reply: no memory for option_state.");
774 execute_statements_in_scope(NULL
, packet
, NULL
, NULL
,
775 packet
->options
, *opt_state
,
776 &global_scope
, root_group
, NULL
);
779 * A small bit of special handling for Solicit messages.
781 * We could move the logic into a flag, but for now just check
784 if (packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
) {
785 reply
->msg_type
= DHCPV6_ADVERTISE
;
789 * - this message type supports rapid commit (Solicit), and
790 * - the server is configured to supply a rapid commit, and
791 * - the client requests a rapid commit,
792 * Then we add a rapid commit option, and send Reply (instead
795 oc
= lookup_option(&dhcpv6_universe
,
796 *opt_state
, D6O_RAPID_COMMIT
);
798 oc
= lookup_option(&dhcpv6_universe
,
799 packet
->options
, D6O_RAPID_COMMIT
);
801 if (!save_option_buffer(&dhcpv6_universe
,
803 (unsigned char *)"", 0,
804 D6O_RAPID_COMMIT
, 0)) {
805 log_error("start_reply: error saving "
806 "RAPID_COMMIT option.");
810 reply
->msg_type
= DHCPV6_REPLY
;
814 reply
->msg_type
= DHCPV6_REPLY
;
817 * Use the client's transaction identifier for the reply.
819 memcpy(reply
->transaction_id
, packet
->dhcpv6_transaction_id
,
820 sizeof(reply
->transaction_id
));
823 * RFC 3315, section 18.2 says we need server identifier and
826 * If the server ID is defined via the configuration file, then
827 * it will already be present in the option state at this point,
828 * so we don't need to set it.
830 * If we have a server ID passed in from the caller,
831 * use that, otherwise use the global DUID.
833 oc
= lookup_option(&dhcpv6_universe
, *opt_state
, D6O_SERVERID
);
835 if (server_id
== NULL
) {
836 server_id_data
= server_duid
.data
;
837 server_id_len
= server_duid
.len
;
839 server_id_data
= server_id
->data
;
840 server_id_len
= server_id
->len
;
842 if (!save_option_buffer(&dhcpv6_universe
, *opt_state
,
843 NULL
, (unsigned char *)server_id_data
,
844 server_id_len
, D6O_SERVERID
, 0)) {
845 log_error("start_reply: "
846 "error saving server identifier.");
851 if (client_id
->buffer
!= NULL
) {
852 if (!save_option_buffer(&dhcpv6_universe
, *opt_state
,
854 (unsigned char *)client_id
->data
,
857 log_error("start_reply: error saving "
858 "client identifier.");
864 * If the client accepts reconfiguration, let it know that we
867 * Note: we don't actually do this yet, but DOCSIS requires we
870 oc
= lookup_option(&dhcpv6_universe
, packet
->options
,
873 if (!save_option_buffer(&dhcpv6_universe
, *opt_state
,
874 NULL
, (unsigned char *)"", 0,
875 D6O_RECONF_ACCEPT
, 0)) {
876 log_error("start_reply: "
877 "error saving RECONF_ACCEPT option.");
878 option_state_dereference(opt_state
, MDL
);
887 * Try to get the IPv6 address the client asked for from the
890 * addr is the result (should be a pointer to NULL on entry)
891 * pool is the pool to search in
892 * requested_addr is the address the client wants
895 try_client_v6_address(struct iaaddr
**addr
,
896 struct ipv6_pool
*pool
,
897 const struct data_string
*requested_addr
)
899 struct in6_addr tmp_addr
;
902 if (requested_addr
->len
< sizeof(tmp_addr
)) {
903 return ISC_R_INVALIDARG
;
905 memcpy(&tmp_addr
, requested_addr
->data
, sizeof(tmp_addr
));
906 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr
)) {
907 return ISC_R_FAILURE
;
910 if (!ipv6_addr_in_pool(&tmp_addr
, pool
)) {
911 return ISC_R_FAILURE
;
914 if (lease6_exists(pool
, &tmp_addr
)) {
915 return ISC_R_ADDRINUSE
;
918 result
= iaaddr_allocate(addr
, MDL
);
919 if (result
!= ISC_R_SUCCESS
) {
922 (*addr
)->addr
= tmp_addr
;
924 result
= add_lease6(pool
, *addr
, 0);
925 if (result
!= ISC_R_SUCCESS
) {
926 iaaddr_dereference(addr
, MDL
);
932 * Get an IPv6 address for the client.
934 * addr is the result (should be a pointer to NULL on entry)
935 * packet is the information about the packet from the client
936 * requested_iaaddr is a hint from the client
937 * client_id is the DUID for the client
940 pick_v6_address(struct iaaddr
**addr
, struct shared_network
*shared_network
,
941 const struct data_string
*client_id
)
946 unsigned int attempts
;
947 char tmp_buf
[INET6_ADDRSTRLEN
];
950 * No pools, we're done.
952 if (shared_network
->ipv6_pools
== NULL
) {
953 log_debug("Unable to pick client address: "
954 "no IPv6 pools on this shared network");
955 return ISC_R_NORESOURCES
;
959 * Otherwise try to get a lease from the first subnet possible.
961 * We start looking at the last pool we allocated from, unless
962 * it had a collision trying to allocate an address. This will
963 * tend to move us into less-filled pools.
965 start_pool
= shared_network
->last_ipv6_pool
;
969 p
= shared_network
->ipv6_pools
[i
];
970 if (activate_lease6(p
, addr
, &attempts
,
971 client_id
, 0) == ISC_R_SUCCESS
) {
973 * Record the pool used (or next one if there
978 if (shared_network
->ipv6_pools
[i
] == NULL
) {
982 shared_network
->last_ipv6_pool
= i
;
984 log_debug("Picking pool address %s",
985 inet_ntop(AF_INET6
, &((*addr
)->addr
),
986 tmp_buf
, sizeof(tmp_buf
)));
987 return ISC_R_SUCCESS
;
991 if (shared_network
->ipv6_pools
[i
] == NULL
) {
994 } while (i
!= start_pool
);
997 * If we failed to pick an IPv6 address from any of the subnets.
998 * Presumably that means we have no addresses for the client.
1000 log_debug("Unable to pick client address: no addresses available");
1001 return ISC_R_NORESOURCES
;
1005 * lease_to_client() is called from several messages to construct a
1006 * reply that contains all that we know about the client's correct lease
1007 * (or projected lease).
1009 * Solicit - "Soft" binding, ignore unknown addresses or bindings, just
1010 * send what we "may" give them on a request.
1012 * Request - "Hard" binding, but ignore supplied addresses (just provide what
1013 * the client should really use).
1015 * Renew - "Hard" binding, but client-supplied addresses are 'real'. Error
1016 * Rebind out any "wrong" addresses the client sends. This means we send
1017 * an empty IA_NA with a status code of NoBinding or NotOnLink or
1018 * possibly send the address with zeroed lifetimes.
1020 * Information-Request - No binding.
1022 * The basic structure is to traverse the client-supplied data first, and
1023 * validate and echo back any contents that can be. If the client-supplied
1024 * data does not error out (on renew/rebind as above), but we did not send
1025 * any addresses, attempt to allocate one.
1027 /* TODO: look at client hints for lease times */
1029 lease_to_client(struct data_string
*reply_ret
,
1030 struct packet
*packet
,
1031 const struct data_string
*client_id
,
1032 const struct data_string
*server_id
)
1034 static struct reply_state reply
;
1035 struct option_cache
*oc
;
1036 struct data_string packet_oro
;
1037 isc_boolean_t no_addrs_avail
;
1039 /* Locate the client. */
1040 if (shared_network_from_packet6(&reply
.shared
,
1041 packet
) != ISC_R_SUCCESS
)
1045 * Initialize the reply.
1047 packet_reference(&reply
.packet
, packet
, MDL
);
1048 data_string_copy(&reply
.client_id
, client_id
, MDL
);
1050 if (!start_reply(packet
, client_id
, server_id
, &reply
.opt_state
,
1054 /* Set the write cursor to just past the reply header. */
1055 reply
.cursor
= REPLY_OPTIONS_INDEX
;
1058 * Get the ORO from the packet, if any.
1060 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_ORO
);
1061 memset(&packet_oro
, 0, sizeof(packet_oro
));
1063 if (!evaluate_option_cache(&packet_oro
, packet
,
1065 packet
->options
, NULL
,
1066 &global_scope
, oc
, MDL
)) {
1067 log_error("lease_to_client: error evaluating ORO.");
1073 * Find a host record that matches from the packet, if any, and is
1074 * valid for the shared network the client is on.
1076 if (find_hosts_by_option(&reply
.host
, packet
, packet
->options
, MDL
)) {
1077 seek_shared_host(&reply
.host
, reply
.shared
);
1080 if ((reply
.host
== NULL
) &&
1081 find_hosts_by_uid(&reply
.host
, client_id
->data
, client_id
->len
,
1083 seek_shared_host(&reply
.host
, reply
.shared
);
1086 /* Process the client supplied IA_NA's onto the reply buffer. */
1088 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
1089 no_addrs_avail
= ISC_FALSE
;
1090 for (; oc
!= NULL
; oc
= oc
->next
) {
1091 isc_result_t status
;
1093 /* Start counting addresses offered. */
1094 reply
.client_addresses
= 0;
1095 reply
.ia_addrs_included
= ISC_FALSE
;
1097 status
= reply_process_ia(&reply
, oc
);
1100 * We continue to try other IA's whether we can address
1101 * this one or not. Any other result is an immediate fail.
1103 if ((status
!= ISC_R_SUCCESS
) &&
1104 (status
!= ISC_R_NORESOURCES
))
1108 * If any address can be given to any IA, then do not set the
1109 * NoAddrsAvail status code.
1111 if (reply
.client_addresses
== 0)
1112 no_addrs_avail
= ISC_TRUE
;
1116 * Make no reply if we gave no resources and is not
1117 * for Information-Request.
1119 if ((reply
.ia_count
== 0) &&
1120 (packet
->dhcpv6_msg_type
!= DHCPV6_INFORMATION_REQUEST
))
1124 * RFC3315 section 17.2.2 (Solicit):
1126 * If the server will not assign any addresses to any IAs in a
1127 * subsequent Request from the client, the server MUST send an
1128 * Advertise message to the client that includes only a Status
1129 * Code option with code NoAddrsAvail and a status message for
1130 * the user, a Server Identifier option with the server's DUID,
1131 * and a Client Identifier option with the client's DUID.
1133 * Section 18.2.1 (Request):
1135 * If the server cannot assign any addresses to an IA in the
1136 * message from the client, the server MUST include the IA in
1137 * the Reply message with no addresses in the IA and a Status
1138 * Code option in the IA containing status code NoAddrsAvail.
1140 * Section 18.2.3 (Renew):
1142 * The server may choose to change the list of addresses and
1143 * the lifetimes of addresses in IAs that are returned to the
1146 * Section 18.2.4 (Rebind):
1148 * Absolutely nothing.
1152 * Solicit and Request are fairly explicit; we send NoAddrsAvail.
1153 * We handle SOLICIT here and REQUEST in the reply_process_ia()
1154 * function (because SOLICIT only counts if we never get around to
1157 * Renew and Rebind are totally undefined. If we send a reply with
1158 * empty IA's, however, the client will stop renewing or rebinding,
1159 * and this is a problem if they could have gotten addressed from
1160 * another server. So we ignore client packets...they will eventually
1161 * time out in the worst case.
1163 if (no_addrs_avail
&&
1164 (reply
.packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
))
1166 /* Set the NoAddrsAvail status code. */
1167 if (!set_status_code(STATUS_NoAddrsAvail
,
1168 "No addresses available for this "
1169 "interface.", reply
.opt_state
)) {
1170 log_error("lease_to_client: Unable to set "
1171 "NoAddrsAvail status code.");
1175 /* Rewind the cursor to the start. */
1176 reply
.cursor
= REPLY_OPTIONS_INDEX
;
1179 * Produce an advertise that includes;
1185 reply
.buf
.reply
.msg_type
= DHCPV6_ADVERTISE
;
1186 reply
.cursor
+= store_options6((char *)reply
.buf
.data
+
1190 reply
.opt_state
, reply
.packet
,
1193 } else if (no_addrs_avail
&&
1194 (reply
.packet
->dhcpv6_msg_type
!= DHCPV6_REQUEST
))
1199 * Having stored the client's IA_NA's, store any options that
1200 * will fit in the remaining space.
1202 reply
.cursor
+= store_options6((char *)reply
.buf
.data
+
1206 reply
.opt_state
, reply
.packet
,
1207 required_opts_solicit
,
1211 /* Return our reply to the caller. */
1212 reply_ret
->len
= reply
.cursor
;
1213 reply_ret
->buffer
= NULL
;
1214 if (!buffer_allocate(&reply_ret
->buffer
, reply
.cursor
, MDL
)) {
1215 log_fatal("No memory to store Reply.");
1217 memcpy(reply_ret
->buffer
->data
, reply
.buf
.data
, reply
.cursor
);
1218 reply_ret
->data
= reply_ret
->buffer
->data
;
1222 if (reply
.shared
!= NULL
)
1223 shared_network_dereference(&reply
.shared
, MDL
);
1224 if (reply
.host
!= NULL
)
1225 host_dereference(&reply
.host
, MDL
);
1226 if (reply
.opt_state
!= NULL
)
1227 option_state_dereference(&reply
.opt_state
, MDL
);
1228 if (reply
.packet
!= NULL
)
1229 packet_dereference(&reply
.packet
, MDL
);
1230 if (reply
.client_id
.data
!= NULL
)
1231 data_string_forget(&reply
.client_id
, MDL
);
1232 reply
.renew
= reply
.rebind
= reply
.prefer
= reply
.valid
= 0;
1236 /* Process a client-supplied IA_NA. This may append options to the tail of
1237 * the reply packet being built in the reply_state structure.
1240 reply_process_ia(struct reply_state
*reply
, struct option_cache
*ia
) {
1241 isc_result_t status
= ISC_R_SUCCESS
;
1244 struct option_state
*packet_ia
;
1245 struct option_cache
*oc
;
1246 struct data_string ia_data
, data
;
1247 isc_boolean_t lease_in_database
;
1249 /* Initialize values that will get cleaned up on return. */
1251 memset(&ia_data
, 0, sizeof(ia_data
));
1252 memset(&data
, 0, sizeof(data
));
1253 lease_in_database
= ISC_FALSE
;
1255 * Note that find_client_address() may set reply->lease.
1258 /* Make sure there is at least room for the header. */
1259 if ((reply
->cursor
+ IA_NA_OFFSET
+ 4) > sizeof(reply
->buf
)) {
1260 log_error("reply_process_ia: Reply too long for IA.");
1261 return ISC_R_NOSPACE
;
1265 /* Fetch the IA_NA contents. */
1266 if (!get_encapsulated_IA_state(&packet_ia
, &ia_data
, reply
->packet
,
1267 ia
, IA_NA_OFFSET
)) {
1268 log_error("reply_process_ia: error evaluating ia_na");
1269 status
= ISC_R_FAILURE
;
1273 /* Extract IA_NA header contents. */
1274 iaid
= getULong(ia_data
.data
);
1275 reply
->renew
= getULong(ia_data
.data
+ 4);
1276 reply
->rebind
= getULong(ia_data
.data
+ 8);
1278 /* Create an IA_NA structure. */
1279 if (ia_na_allocate(&reply
->ia_na
, iaid
, (char *)reply
->client_id
.data
,
1280 reply
->client_id
.len
, MDL
) != ISC_R_SUCCESS
) {
1281 log_error("lease_to_client: no memory for ia_na.");
1282 status
= ISC_R_NOMEMORY
;
1286 /* Cache pre-existing IA, if any. */
1287 ia_na_hash_lookup(&reply
->old_ia
, ia_active
,
1288 (unsigned char *)reply
->ia_na
->iaid_duid
.data
,
1289 reply
->ia_na
->iaid_duid
.len
, MDL
);
1292 * Create an option cache to carry the IA_NA option contents, and
1293 * execute any user-supplied values into it.
1295 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
1296 status
= ISC_R_NOMEMORY
;
1300 /* Check & cache the fixed host record. */
1301 if ((reply
->host
!= NULL
) && (reply
->host
->fixed_addr
!= NULL
)) {
1302 if (!evaluate_option_cache(&reply
->fixed
, NULL
, NULL
, NULL
,
1303 NULL
, NULL
, &global_scope
,
1304 reply
->host
->fixed_addr
, MDL
)) {
1305 log_error("reply_process_ia: unable to evaluate "
1307 status
= ISC_R_FAILURE
;
1311 if (reply
->fixed
.len
< 16) {
1312 log_error("reply_process_ia: invalid fixed address.");
1313 status
= ISC_R_INVALIDARG
;
1317 reply
->static_lease
= ISC_TRUE
;
1319 reply
->static_lease
= ISC_FALSE
;
1322 * Save the cursor position at the start of the IA, so we can
1323 * set length and adjust t1/t2 values later. We write a temporary
1324 * header out now just in case we decide to adjust the packet
1325 * within sub-process functions.
1327 ia_cursor
= reply
->cursor
;
1329 /* Initialize the IA_NA header. First the code. */
1330 putUShort(reply
->buf
.data
+ reply
->cursor
, (unsigned)D6O_IA_NA
);
1333 /* Then option length. */
1334 putUShort(reply
->buf
.data
+ reply
->cursor
, 0x0Cu
);
1337 /* Then IA_NA header contents; IAID. */
1338 putULong(reply
->buf
.data
+ reply
->cursor
, iaid
);
1341 /* We store the client's t1 for now, and may over-ride it later. */
1342 putULong(reply
->buf
.data
+ reply
->cursor
, reply
->renew
);
1345 /* We store the client's t2 for now, and may over-ride it later. */
1346 putULong(reply
->buf
.data
+ reply
->cursor
, reply
->rebind
);
1350 * For each address in this IA_NA, decide what to do about
1353 oc
= lookup_option(&dhcpv6_universe
, packet_ia
, D6O_IAADDR
);
1354 reply
->valid
= reply
->prefer
= 0xffffffff;
1355 reply
->client_valid
= reply
->client_prefer
= 0;
1356 for (; oc
!= NULL
; oc
= oc
->next
) {
1357 status
= reply_process_addr(reply
, oc
);
1360 * Canceled means we did not allocate addresses to the
1361 * client, but we're "done" with this IA - we set a status
1362 * code. So transmit this reply, e.g., move on to the next
1365 if (status
== ISC_R_CANCELED
)
1368 if ((status
!= ISC_R_SUCCESS
) && (status
!= ISC_R_ADDRINUSE
))
1375 * If we fell through the above and never gave the client
1376 * an address, give it one now.
1378 if ((status
!= ISC_R_CANCELED
) && (reply
->client_addresses
== 0)) {
1379 status
= find_client_address(reply
);
1381 if (status
== ISC_R_NORESOURCES
) {
1382 switch (reply
->packet
->dhcpv6_msg_type
) {
1383 case DHCPV6_SOLICIT
:
1385 * Solicit is handled by the caller, because
1386 * it has to be the sum of all the IA's.
1390 case DHCPV6_REQUEST
:
1391 /* Section 18.2.1 (Request):
1393 * If the server cannot assign any addresses to
1394 * an IA in the message from the client, the
1395 * server MUST include the IA in the Reply
1396 * message with no addresses in the IA and a
1397 * Status Code option in the IA containing
1398 * status code NoAddrsAvail.
1400 option_state_dereference(&reply
->reply_ia
, MDL
);
1401 if (!option_state_allocate(&reply
->reply_ia
,
1404 log_error("reply_process_ia: No "
1405 "memory for option state "
1407 status
= ISC_R_NOMEMORY
;
1411 if (!set_status_code(STATUS_NoAddrsAvail
,
1412 "No addresses available "
1413 "for this interface.",
1415 log_error("reply_process_ia: Unable "
1416 "to set NoAddrsAvail status "
1418 status
= ISC_R_FAILURE
;
1422 status
= ISC_R_SUCCESS
;
1427 * RFC 3315 does not tell us to emit a status
1428 * code in this condition, or anything else.
1430 * If we included non-allocated addresses
1431 * (zeroed lifetimes) in an IA, then the client
1432 * will deconfigure them.
1434 * So we want to include the IA even if we
1435 * can't give it a new address if it includes
1436 * zeroed lifetime addresses.
1438 * We don't want to include the IA if we
1439 * provide zero addresses including zeroed
1440 * lifetimes...if we did, the client would
1441 * reset its renew/rebind behaviour. If we do
1442 * not, the client may get a success off
1445 if (reply
->ia_addrs_included
)
1446 status
= ISC_R_SUCCESS
;
1453 if (status
!= ISC_R_SUCCESS
)
1457 reply
->cursor
+= store_options6((char *)reply
->buf
.data
+ reply
->cursor
,
1458 sizeof(reply
->buf
) - reply
->cursor
,
1459 reply
->reply_ia
, reply
->packet
,
1460 required_opts_IA_NA
, NULL
);
1462 /* Reset the length of this IA to match what was just written. */
1463 putUShort(reply
->buf
.data
+ ia_cursor
+ 2,
1464 reply
->cursor
- (ia_cursor
+ 4));
1467 * T1/T2 time selection is kind of weird. We actually use DHCP
1468 * (v4) scoped options as handy existing places where these might
1469 * be configured by an administrator. A value of zero tells the
1470 * client it may choose its own renewal time.
1473 oc
= lookup_option(&dhcp_universe
, reply
->opt_state
,
1474 DHO_DHCP_RENEWAL_TIME
);
1476 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
1477 reply
->packet
->options
,
1478 reply
->opt_state
, &global_scope
,
1481 log_error("Invalid renewal time.");
1483 reply
->renew
= getULong(data
.data
);
1486 if (data
.data
!= NULL
)
1487 data_string_forget(&data
, MDL
);
1489 putULong(reply
->buf
.data
+ ia_cursor
+ 8, reply
->renew
);
1493 oc
= lookup_option(&dhcp_universe
, reply
->opt_state
,
1494 DHO_DHCP_REBINDING_TIME
);
1496 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
1497 reply
->packet
->options
,
1498 reply
->opt_state
, &global_scope
,
1501 log_error("Invalid rebinding time.");
1503 reply
->rebind
= getULong(data
.data
);
1506 if (data
.data
!= NULL
)
1507 data_string_forget(&data
, MDL
);
1509 putULong(reply
->buf
.data
+ ia_cursor
+ 12, reply
->rebind
);
1512 * If this is not a 'soft' binding, consume the new changes into
1513 * the database (if any have been attached to the ia_na).
1515 * Loop through the assigned dynamic addresses, referencing the
1516 * leases onto this IA_NA rather than any old ones, and updating
1517 * pool timers for each (if any).
1519 if ((status
!= ISC_R_CANCELED
) && !reply
->static_lease
&&
1520 (reply
->buf
.reply
.msg_type
== DHCPV6_REPLY
) &&
1521 (reply
->ia_na
->num_iaaddr
!= 0)) {
1523 struct data_string
*ia_id
;
1526 for (i
= 0 ; i
< reply
->ia_na
->num_iaaddr
; i
++) {
1527 tmp
= reply
->ia_na
->iaaddr
[i
];
1529 if (tmp
->ia_na
!= NULL
)
1530 ia_na_dereference(&tmp
->ia_na
, MDL
);
1531 ia_na_reference(&tmp
->ia_na
, reply
->ia_na
, MDL
);
1533 schedule_lease_timeout(tmp
->ipv6_pool
);
1536 * If this constitutes a 'hard' binding, perform ddns
1539 oc
= lookup_option(&server_universe
, reply
->opt_state
,
1542 evaluate_boolean_option_cache(NULL
, reply
->packet
,
1544 reply
->packet
->options
,
1548 ddns_updates(reply
->packet
, NULL
, NULL
,
1549 tmp
, NULL
, reply
->opt_state
);
1553 /* Remove any old ia_na from the hash. */
1554 if (reply
->old_ia
!= NULL
) {
1555 ia_id
= &reply
->old_ia
->iaid_duid
;
1556 ia_na_hash_delete(ia_active
,
1557 (unsigned char *)ia_id
->data
,
1559 ia_na_dereference(&reply
->old_ia
, MDL
);
1562 /* Put new ia_na into the hash. */
1563 ia_id
= &reply
->ia_na
->iaid_duid
;
1564 ia_na_hash_add(ia_active
, (unsigned char *)ia_id
->data
,
1565 ia_id
->len
, reply
->ia_na
, MDL
);
1567 write_ia_na(reply
->ia_na
);
1570 * Note that we wrote the lease into the database,
1571 * so that we know not to release it when we're done
1572 * with this function.
1574 lease_in_database
= ISC_TRUE
;
1577 * If this is a soft binding, we will check to see if we are
1578 * suggesting the existing database entry to the client.
1580 } else if ((status
!= ISC_R_CANCELED
) && !reply
->static_lease
&&
1581 (reply
->old_ia
!= NULL
)) {
1582 if (ia_na_equal(reply
->old_ia
, reply
->ia_na
)) {
1583 lease_in_database
= ISC_TRUE
;
1588 if (packet_ia
!= NULL
)
1589 option_state_dereference(&packet_ia
, MDL
);
1590 if (reply
->reply_ia
!= NULL
)
1591 option_state_dereference(&reply
->reply_ia
, MDL
);
1592 if (ia_data
.data
!= NULL
)
1593 data_string_forget(&ia_data
, MDL
);
1594 if (data
.data
!= NULL
)
1595 data_string_forget(&data
, MDL
);
1596 if (reply
->ia_na
!= NULL
)
1597 ia_na_dereference(&reply
->ia_na
, MDL
);
1598 if (reply
->old_ia
!= NULL
)
1599 ia_na_dereference(&reply
->old_ia
, MDL
);
1600 if (reply
->lease
!= NULL
) {
1601 if (!lease_in_database
) {
1602 release_lease6(reply
->lease
->ipv6_pool
, reply
->lease
);
1604 iaaddr_dereference(&reply
->lease
, MDL
);
1606 if (reply
->fixed
.data
!= NULL
)
1607 data_string_forget(&reply
->fixed
, MDL
);
1610 * ISC_R_CANCELED is a status code used by the addr processing to
1611 * indicate we're replying with a status code. This is still a
1612 * success at higher layers.
1614 return((status
== ISC_R_CANCELED
) ? ISC_R_SUCCESS
: status
);
1618 * Process an IAADDR within a given IA_NA, storing any IAADDR reply contents
1619 * into the reply's current ia-scoped option cache. Returns ISC_R_CANCELED
1620 * in the event we are replying with a status code and do not wish to process
1621 * more IAADDRs within this IA.
1624 reply_process_addr(struct reply_state
*reply
, struct option_cache
*addr
) {
1625 u_int32_t pref_life
, valid_life
;
1626 struct binding_scope
**scope
;
1627 struct group
*group
;
1628 struct subnet
*subnet
;
1629 struct iaddr tmp_addr
;
1630 struct option_cache
*oc
;
1631 struct data_string iaaddr
, data
;
1632 isc_result_t status
= ISC_R_SUCCESS
;
1634 /* Initializes values that will be cleaned up. */
1635 memset(&iaaddr
, 0, sizeof(iaaddr
));
1636 memset(&data
, 0, sizeof(data
));
1637 /* Note that reply->lease may be set by address_is_owned() */
1640 * There is no point trying to process an incoming address if there
1641 * is no room for an outgoing address.
1643 if ((reply
->cursor
+ 28) > sizeof(reply
->buf
)) {
1644 log_error("reply_process_addr: Out of room for address.");
1645 return ISC_R_NOSPACE
;
1648 /* Extract this IAADDR option. */
1649 if (!evaluate_option_cache(&iaaddr
, reply
->packet
, NULL
, NULL
,
1650 reply
->packet
->options
, NULL
, &global_scope
,
1652 (iaaddr
.len
< IAADDR_OFFSET
)) {
1653 log_error("reply_process_addr: error evaluating IAADDR.");
1654 status
= ISC_R_FAILURE
;
1658 /* The first 16 bytes are the IPv6 address. */
1659 pref_life
= getULong(iaaddr
.data
+ 16);
1660 valid_life
= getULong(iaaddr
.data
+ 20);
1662 if ((reply
->client_valid
== 0) ||
1663 (reply
->client_valid
> valid_life
))
1664 reply
->client_valid
= valid_life
;
1666 if ((reply
->client_prefer
== 0) ||
1667 (reply
->client_prefer
> pref_life
))
1668 reply
->client_prefer
= pref_life
;
1671 * Clients may choose to send :: as an address, with the idea to give
1672 * hints about preferred-lifetime or valid-lifetime.
1675 memset(tmp_addr
.iabuf
, 0, 16);
1676 if (!memcmp(iaaddr
.data
, tmp_addr
.iabuf
, 16)) {
1677 /* Status remains success; we just ignore this one. */
1681 /* tmp_addr len remains 16 */
1682 memcpy(tmp_addr
.iabuf
, iaaddr
.data
, 16);
1685 * Verify that this address is on the client's network.
1687 for (subnet
= reply
->shared
->subnets
; subnet
!= NULL
;
1688 subnet
= subnet
->next_sibling
) {
1689 if (addr_eq(subnet_number(tmp_addr
, subnet
->netmask
),
1694 /* Address not found on shared network. */
1695 if (subnet
== NULL
) {
1696 /* Ignore this address on 'soft' bindings. */
1697 if (reply
->packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
)
1698 /* status remains success */
1702 * RFC3315 section 18.2.1:
1704 * If the server finds that the prefix on one or more IP
1705 * addresses in any IA in the message from the client is not
1706 * appropriate for the link to which the client is connected,
1707 * the server MUST return the IA to the client with a Status
1708 * Code option with the value NotOnLink.
1710 if (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REQUEST
) {
1711 /* Rewind the IA_NA to empty. */
1712 option_state_dereference(&reply
->reply_ia
, MDL
);
1713 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
1714 log_error("reply_process_addr: No memory for "
1715 "option state wipe.");
1716 status
= ISC_R_NOMEMORY
;
1720 /* Append a NotOnLink status code. */
1721 if (!set_status_code(STATUS_NotOnLink
,
1722 "Address not for use on this "
1723 "link.", reply
->reply_ia
)) {
1724 log_error("reply_process_addr: Failure "
1725 "setting status code.");
1726 status
= ISC_R_FAILURE
;
1730 /* Fin (no more IAADDRs). */
1731 status
= ISC_R_CANCELED
;
1736 * RFC3315 sections 18.2.3 and 18.2.4 have identical language:
1738 * If the server finds that any of the addresses are not
1739 * appropriate for the link to which the client is attached,
1740 * the server returns the address to the client with lifetimes
1743 if ((reply
->packet
->dhcpv6_msg_type
!= DHCPV6_RENEW
) &&
1744 (reply
->packet
->dhcpv6_msg_type
!= DHCPV6_REBIND
)) {
1745 log_error("It is impossible to lease a client that is "
1746 "not sending a solict, request, renew, or "
1748 status
= ISC_R_FAILURE
;
1752 reply
->send_prefer
= reply
->send_valid
= 0;
1756 /* Verify the address belongs to the client. */
1757 if (!address_is_owned(reply
, &tmp_addr
)) {
1759 * For solicit and request, any addresses included are
1760 * 'requested' addresses. For rebind, we actually have
1761 * no direction on what to do from 3315 section 18.2.4!
1762 * So I think the best bet is to try and give it out, and if
1763 * we can't, zero lifetimes.
1765 if ((reply
->packet
->dhcpv6_msg_type
== DHCPV6_SOLICIT
) ||
1766 (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REQUEST
) ||
1767 (reply
->packet
->dhcpv6_msg_type
== DHCPV6_REBIND
)) {
1768 status
= reply_process_try_addr(reply
, &tmp_addr
);
1770 /* Either error out or skip this address. */
1771 if ((status
!= ISC_R_SUCCESS
) &&
1772 (status
!= ISC_R_ADDRINUSE
))
1775 if (reply
->lease
== NULL
) {
1776 if (reply
->packet
->dhcpv6_msg_type
==
1778 reply
->send_prefer
= 0;
1779 reply
->send_valid
= 0;
1783 /* status remains success - ignore */
1787 * RFC3315 section 18.2.3:
1789 * If the server cannot find a client entry for the IA the
1790 * server returns the IA containing no addresses with a Status
1791 * Code option set to NoBinding in the Reply message.
1793 } else if (reply
->packet
->dhcpv6_msg_type
== DHCPV6_RENEW
) {
1794 /* Rewind the IA_NA to empty. */
1795 option_state_dereference(&reply
->reply_ia
, MDL
);
1796 if (!option_state_allocate(&reply
->reply_ia
, MDL
)) {
1797 log_error("reply_process_addr: No memory for "
1798 "option state wipe.");
1799 status
= ISC_R_NOMEMORY
;
1803 /* Append a NoBinding status code. */
1804 if (!set_status_code(STATUS_NoBinding
,
1805 "Address not bound to this "
1806 "interface.", reply
->reply_ia
)) {
1807 log_error("reply_process_addr: Unable to "
1808 "attach status code.");
1809 status
= ISC_R_FAILURE
;
1813 /* Fin (no more IAADDRs). */
1814 status
= ISC_R_CANCELED
;
1817 log_error("It is impossible to lease a client that is "
1818 "not sending a solicit, request, renew, or "
1820 status
= ISC_R_FAILURE
;
1825 if (reply
->static_lease
) {
1826 if (reply
->host
== NULL
)
1827 log_fatal("Impossible condition at %s:%d.", MDL
);
1829 scope
= &global_scope
;
1830 group
= reply
->host
->group
;
1832 if (reply
->lease
== NULL
)
1833 log_fatal("Impossible condition at %s:%d.", MDL
);
1835 scope
= &reply
->lease
->scope
;
1836 group
= reply
->shared
->group
;
1840 * If client_addresses is nonzero, then the reply_process_is_addressed
1841 * function has executed configuration state into the reply option
1842 * cache. We will use that valid cache to derive configuration for
1843 * whether or not to engage in additional addresses, and similar.
1845 if (reply
->client_addresses
!= 0) {
1849 * Does this client have "enough" addresses already? Default
1850 * to one. Everybody gets one, and one should be enough for
1853 oc
= lookup_option(&server_universe
, reply
->opt_state
,
1854 SV_LIMIT_ADDRS_PER_IA
);
1856 if (!evaluate_option_cache(&data
, reply
->packet
,
1858 reply
->packet
->options
,
1862 log_error("reply_process_ia: unable to "
1863 "evaluate addrs-per-ia value.");
1864 status
= ISC_R_FAILURE
;
1868 limit
= getULong(data
.data
);
1869 data_string_forget(&data
, MDL
);
1873 * If we wish to limit the client to a certain number of
1874 * addresses, then omit the address from the reply.
1876 if (reply
->client_addresses
>= limit
)
1880 status
= reply_process_is_addressed(reply
, scope
, group
);
1881 if (status
!= ISC_R_SUCCESS
)
1885 status
= reply_process_send_addr(reply
, &tmp_addr
);
1888 if (iaaddr
.data
!= NULL
)
1889 data_string_forget(&iaaddr
, MDL
);
1890 if (data
.data
!= NULL
)
1891 data_string_forget(&data
, MDL
);
1892 if (reply
->lease
!= NULL
)
1893 iaaddr_dereference(&reply
->lease
, MDL
);
1899 * Verify the address belongs to the client. If we've got a host
1900 * record with a fixed address, it has to be the assigned address
1901 * (fault out all else). Otherwise it's a dynamic address, so lookup
1902 * that address and make sure it belongs to this DUID:IAID pair.
1904 static isc_boolean_t
1905 address_is_owned(struct reply_state
*reply
, struct iaddr
*addr
) {
1909 * This faults out addresses that don't match fixed addresses.
1911 if (reply
->static_lease
) {
1912 if (reply
->fixed
.data
== NULL
)
1913 log_fatal("Impossible condition at %s:%d.", MDL
);
1915 if (memcmp(addr
->iabuf
, reply
->fixed
.data
, 16) == 0)
1921 if ((reply
->old_ia
== NULL
) || (reply
->old_ia
->num_iaaddr
== 0))
1924 for (i
= 0 ; i
< reply
->old_ia
->num_iaaddr
; i
++) {
1927 tmp
= reply
->old_ia
->iaaddr
[i
];
1929 if (memcmp(addr
->iabuf
, &tmp
->addr
, 16) == 0) {
1930 iaaddr_reference(&reply
->lease
, tmp
, MDL
);
1939 * This function only returns failure on 'hard' failures. If it succeeds,
1940 * it will leave a lease structure behind.
1943 reply_process_try_addr(struct reply_state
*reply
, struct iaddr
*addr
) {
1944 isc_result_t status
= ISC_R_FAILURE
;
1945 struct ipv6_pool
*pool
;
1947 struct data_string data_addr
;
1949 if ((reply
== NULL
) || (reply
->shared
== NULL
) ||
1950 (reply
->shared
->ipv6_pools
== NULL
) || (addr
== NULL
) ||
1951 (reply
->lease
!= NULL
))
1952 return ISC_R_INVALIDARG
;
1954 memset(&data_addr
, 0, sizeof(data_addr
));
1955 data_addr
.len
= addr
->len
;
1956 data_addr
.data
= addr
->iabuf
;
1958 for (i
= 0 ; (pool
= reply
->shared
->ipv6_pools
[i
]) != NULL
; i
++) {
1959 status
= try_client_v6_address(&reply
->lease
, pool
,
1961 if (status
== ISC_R_SUCCESS
)
1965 /* Note that this is just pedantry. There is no allocation to free. */
1966 data_string_forget(&data_addr
, MDL
);
1967 /* Return just the most recent status... */
1971 /* Look around for an address to give the client. First, look through the
1972 * old IA for addresses we can extend. Second, try to allocate a new address.
1973 * Finally, actually add that address into the current reply IA.
1976 find_client_address(struct reply_state
*reply
) {
1977 struct iaddr send_addr
;
1978 isc_result_t status
= ISC_R_NORESOURCES
;
1979 struct iaaddr
*lease
, *best_lease
= NULL
;
1980 struct binding_scope
**scope
;
1981 struct group
*group
;
1984 if (reply
->host
!= NULL
)
1985 group
= reply
->host
->group
;
1987 group
= reply
->shared
->group
;
1989 if (reply
->static_lease
) {
1990 if (reply
->host
== NULL
)
1991 return ISC_R_INVALIDARG
;
1994 memcpy(send_addr
.iabuf
, reply
->fixed
.data
, 16);
1996 status
= ISC_R_SUCCESS
;
1997 scope
= &global_scope
;
2001 if (reply
->old_ia
!= NULL
) {
2002 for (i
= 0 ; i
< reply
->old_ia
->num_iaaddr
; i
++) {
2003 lease
= reply
->old_ia
->iaaddr
[i
];
2005 best_lease
= lease_compare(lease
, best_lease
);
2009 /* Try to pick a new address if we didn't find one, or if we found an
2012 if ((best_lease
== NULL
) || (best_lease
->state
== FTS_ABANDONED
)) {
2013 status
= pick_v6_address(&reply
->lease
, reply
->shared
,
2015 } else if (best_lease
!= NULL
) {
2016 iaaddr_reference(&reply
->lease
, best_lease
, MDL
);
2017 status
= ISC_R_SUCCESS
;
2020 /* Pick the abandoned lease as a last resort. */
2021 if ((status
== ISC_R_NORESOURCES
) && (best_lease
!= NULL
)) {
2022 /* I don't see how this is supposed to be done right now. */
2023 log_error("Reclaiming abandoned addresses is not yet "
2024 "supported. Treating this as an out of space "
2026 /* lease_reference(&reply->lease, best_lease, MDL); */
2029 /* Give up now if we didn't find a lease. */
2030 if (status
!= ISC_R_SUCCESS
)
2033 if (reply
->lease
== NULL
)
2034 log_fatal("Impossible condition at %s:%d.", MDL
);
2036 scope
= &reply
->lease
->scope
;
2037 group
= reply
->shared
->group
;
2040 memcpy(send_addr
.iabuf
, &reply
->lease
->addr
, 16);
2043 status
= reply_process_is_addressed(reply
, scope
, group
);
2044 if (status
!= ISC_R_SUCCESS
)
2047 status
= reply_process_send_addr(reply
, &send_addr
);
2051 /* Once an address is found for a client, perform several common functions;
2052 * Calculate and store valid and preferred lease times, draw client options
2053 * into the option state.
2056 reply_process_is_addressed(struct reply_state
*reply
,
2057 struct binding_scope
**scope
, struct group
*group
)
2059 isc_result_t status
= ISC_R_SUCCESS
;
2060 struct data_string data
;
2061 struct option_cache
*oc
;
2063 /* Initialize values we will cleanup. */
2064 memset(&data
, 0, sizeof(data
));
2066 /* Execute relevant options into root scope. */
2067 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
2068 reply
->packet
->options
, reply
->opt_state
,
2069 scope
, group
, root_group
);
2071 /* Determine valid lifetime. */
2072 if (reply
->client_valid
== 0)
2073 reply
->send_valid
= DEFAULT_DEFAULT_LEASE_TIME
;
2075 reply
->send_valid
= reply
->client_valid
;
2077 oc
= lookup_option(&server_universe
, reply
->opt_state
,
2078 SV_DEFAULT_LEASE_TIME
);
2080 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
2081 reply
->packet
->options
,
2085 log_error("reply_process_ia: unable to "
2086 "evaluate default lease time");
2087 status
= ISC_R_FAILURE
;
2091 reply
->send_valid
= getULong(data
.data
);
2092 data_string_forget(&data
, MDL
);
2095 if (reply
->client_prefer
== 0)
2096 reply
->send_prefer
= reply
->send_valid
;
2098 reply
->send_prefer
= reply
->client_prefer
;
2100 if (reply
->send_prefer
>= reply
->send_valid
)
2101 reply
->send_prefer
= (reply
->send_valid
/ 2) +
2102 (reply
->send_valid
/ 8);
2104 oc
= lookup_option(&server_universe
, reply
->opt_state
,
2105 SV_PREFER_LIFETIME
);
2107 if (!evaluate_option_cache(&data
, reply
->packet
, NULL
, NULL
,
2108 reply
->packet
->options
,
2112 log_error("reply_process_ia: unable to "
2113 "evaluate preferred lease time");
2114 status
= ISC_R_FAILURE
;
2118 reply
->send_prefer
= getULong(data
.data
);
2119 data_string_forget(&data
, MDL
);
2122 /* Note lowest values for later calculation of renew/rebind times. */
2123 if (reply
->prefer
> reply
->send_prefer
)
2124 reply
->prefer
= reply
->send_prefer
;
2126 if (reply
->valid
> reply
->send_valid
)
2127 reply
->valid
= reply
->send_valid
;
2131 * XXX: Old 4.0.0 alpha code would change the host {} record
2132 * XXX: uid upon lease assignment. This was intended to cover the
2133 * XXX: case where a client first identifies itself using vendor
2134 * XXX: options in a solicit, or request, but later neglects to include
2135 * XXX: these options in a Renew or Rebind. It is not clear that this
2136 * XXX: is required, and has some startling ramifications (such as
2137 * XXX: how to recover this dynamic host {} state across restarts).
2139 if (reply
->host
!= NULL
)
2140 change_host_uid(host
, reply
->client_id
->data
,
2141 reply
->client_id
->len
);
2144 /* Perform dynamic lease related update work. */
2145 if (reply
->lease
!= NULL
) {
2146 /* Advance (or rewind) the valid lifetime. */
2147 reply
->lease
->valid_lifetime_end_time
= cur_time
+
2149 renew_lease6(reply
->lease
->ipv6_pool
, reply
->lease
);
2151 status
= ia_na_add_iaaddr(reply
->ia_na
, reply
->lease
, MDL
);
2152 if (status
!= ISC_R_SUCCESS
) {
2153 log_fatal("reply_process_addr: Unable to attach lease "
2154 "to new IA: %s", isc_result_totext(status
));
2158 * If this is a new lease, make sure it is attached somewhere.
2160 if (reply
->lease
->ia_na
== NULL
) {
2161 ia_na_reference(&reply
->lease
->ia_na
, reply
->ia_na
,
2166 /* Bring a copy of the relevant options into the IA scope. */
2167 execute_statements_in_scope(NULL
, reply
->packet
, NULL
, NULL
,
2168 reply
->packet
->options
, reply
->reply_ia
,
2169 scope
, group
, root_group
);
2172 if (data
.data
!= NULL
)
2173 data_string_forget(&data
, MDL
);
2175 if (status
== ISC_R_SUCCESS
)
2176 reply
->client_addresses
++;
2181 /* Simply send an IAADDR within the IA_NA scope as described. */
2183 reply_process_send_addr(struct reply_state
*reply
, struct iaddr
*addr
) {
2184 isc_result_t status
= ISC_R_SUCCESS
;
2185 struct data_string data
;
2187 memset(&data
, 0, sizeof(data
));
2189 /* Now append the lease. */
2190 data
.len
= IAADDR_OFFSET
;
2191 if (!buffer_allocate(&data
.buffer
, data
.len
, MDL
)) {
2192 log_error("reply_process_ia: out of memory allocating "
2193 "new IAADDR buffer.");
2194 status
= ISC_R_NOMEMORY
;
2197 data
.data
= data
.buffer
->data
;
2199 memcpy(data
.buffer
->data
, addr
->iabuf
, 16);
2200 putULong(data
.buffer
->data
+ 16, reply
->send_prefer
);
2201 putULong(data
.buffer
->data
+ 20, reply
->send_valid
);
2203 if (!append_option_buffer(&dhcpv6_universe
, reply
->reply_ia
,
2204 data
.buffer
, data
.buffer
->data
,
2205 data
.len
, D6O_IAADDR
, 0)) {
2206 log_error("reply_process_ia: unable to save IAADDR "
2208 status
= ISC_R_FAILURE
;
2212 reply
->ia_addrs_included
= ISC_TRUE
;
2215 if (data
.data
!= NULL
)
2216 data_string_forget(&data
, MDL
);
2221 /* Choose the better of two leases. */
2222 static struct iaaddr
*
2223 lease_compare(struct iaaddr
*alpha
, struct iaaddr
*beta
) {
2229 switch(alpha
->state
) {
2231 switch(beta
->state
) {
2233 /* Choose the lease with the longest lifetime (most
2234 * likely the most recently allocated).
2236 if (alpha
->valid_lifetime_end_time
<
2237 beta
->valid_lifetime_end_time
)
2247 log_fatal("Impossible condition at %s:%d.", MDL
);
2252 switch (beta
->state
) {
2257 /* Choose the most recently expired lease. */
2258 if (alpha
->valid_lifetime_end_time
<
2259 beta
->valid_lifetime_end_time
)
2268 log_fatal("Impossible condition at %s:%d.", MDL
);
2273 switch (beta
->state
) {
2279 /* Choose the lease that was abandoned longest ago. */
2280 if (alpha
->valid_lifetime_end_time
<
2281 beta
->valid_lifetime_end_time
)
2285 log_fatal("Impossible condition at %s:%d.", MDL
);
2290 log_fatal("Impossible condition at %s:%d.", MDL
);
2293 log_fatal("Triple impossible condition at %s:%d.", MDL
);
2298 * Solicit is how a client starts requesting addresses.
2300 * If the client asks for rapid commit, and we support it, we will
2301 * allocate the addresses and reply.
2303 * Otherwise we will send an advertise message.
2307 dhcpv6_solicit(struct data_string
*reply_ret
, struct packet
*packet
) {
2308 struct data_string client_id
;
2311 * Validate our input.
2313 if (!valid_client_msg(packet
, &client_id
)) {
2317 lease_to_client(reply_ret
, packet
, &client_id
, NULL
);
2322 data_string_forget(&client_id
, MDL
);
2326 * Request is how a client actually requests addresses.
2328 * Very similar to Solicit handling, except the server DUID is required.
2331 /* TODO: reject unicast messages, unless we set unicast option */
2333 dhcpv6_request(struct data_string
*reply_ret
, struct packet
*packet
) {
2334 struct data_string client_id
;
2335 struct data_string server_id
;
2338 * Validate our input.
2340 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
2347 lease_to_client(reply_ret
, packet
, &client_id
, &server_id
);
2352 data_string_forget(&client_id
, MDL
);
2353 data_string_forget(&server_id
, MDL
);
2356 /* Find a DHCPv6 packet's shared network from hints in the packet.
2359 shared_network_from_packet6(struct shared_network
**shared
,
2360 struct packet
*packet
)
2362 const struct packet
*chk_packet
;
2363 const struct in6_addr
*link_addr
, *first_link_addr
;
2364 struct iaddr tmp_addr
;
2365 struct subnet
*subnet
;
2366 isc_result_t status
;
2368 if ((shared
== NULL
) || (*shared
!= NULL
) || (packet
== NULL
))
2369 return ISC_R_INVALIDARG
;
2372 * First, find the link address where the packet from the client
2373 * first appeared (if this packet was relayed).
2375 first_link_addr
= NULL
;
2376 chk_packet
= packet
->dhcpv6_container_packet
;
2377 while (chk_packet
!= NULL
) {
2378 link_addr
= &chk_packet
->dhcpv6_link_address
;
2379 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr
) &&
2380 !IN6_IS_ADDR_LINKLOCAL(link_addr
)) {
2381 first_link_addr
= link_addr
;
2383 chk_packet
= chk_packet
->dhcpv6_container_packet
;
2387 * If there is a relayed link address, find the subnet associated
2388 * with that, and use that to get the appropriate
2391 if (first_link_addr
!= NULL
) {
2392 tmp_addr
.len
= sizeof(*first_link_addr
);
2393 memcpy(tmp_addr
.iabuf
,
2394 first_link_addr
, sizeof(*first_link_addr
));
2396 if (!find_subnet(&subnet
, tmp_addr
, MDL
)) {
2397 log_debug("No subnet found for link-address %s.",
2399 return ISC_R_NOTFOUND
;
2401 status
= shared_network_reference(shared
,
2402 subnet
->shared_network
, MDL
);
2403 subnet_dereference(&subnet
, MDL
);
2406 * If there is no link address, we will use the interface
2407 * that this packet came in on to pick the shared_network.
2410 status
= shared_network_reference(shared
,
2411 packet
->interface
->shared_network
,
2419 * When a client thinks it might be on a new link, it sends a
2422 * From RFC3315 section 18.2.2:
2424 * When the server receives a Confirm message, the server determines
2425 * whether the addresses in the Confirm message are appropriate for the
2426 * link to which the client is attached. If all of the addresses in the
2427 * Confirm message pass this test, the server returns a status of
2428 * Success. If any of the addresses do not pass this test, the server
2429 * returns a status of NotOnLink. If the server is unable to perform
2430 * this test (for example, the server does not have information about
2431 * prefixes on the link to which the client is connected), or there were
2432 * no addresses in any of the IAs sent by the client, the server MUST
2433 * NOT send a reply to the client.
2437 dhcpv6_confirm(struct data_string
*reply_ret
, struct packet
*packet
) {
2438 struct shared_network
*shared
;
2439 struct subnet
*subnet
;
2440 struct option_cache
*ia
, *ta
, *oc
;
2441 struct data_string cli_enc_opt_data
, iaaddr
, client_id
, packet_oro
;
2442 struct option_state
*cli_enc_opt_state
, *opt_state
;
2443 struct iaddr cli_addr
;
2445 isc_boolean_t inappropriate
, has_addrs
;
2446 char reply_data
[65536];
2447 struct dhcpv6_packet
*reply
= (struct dhcpv6_packet
*)reply_data
;
2448 int reply_ofs
= (int)((char *)reply
->options
- (char *)reply
);
2451 * Basic client message validation.
2453 memset(&client_id
, 0, sizeof(client_id
));
2454 if (!valid_client_msg(packet
, &client_id
)) {
2458 /* Do not process Confirms that do not have IA's we do not recognize.
2460 ia
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
2461 ta
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_TA
);
2462 if ((ia
== NULL
) && (ta
== NULL
))
2466 * Bit of variable initialization.
2468 opt_state
= cli_enc_opt_state
= NULL
;
2469 memset(&cli_enc_opt_data
, 0, sizeof(cli_enc_opt_data
));
2470 memset(&iaaddr
, 0, sizeof(iaaddr
));
2471 memset(&packet_oro
, 0, sizeof(packet_oro
));
2473 /* Determine what shared network the client is connected to. We
2474 * must not respond if we don't have any information about the
2475 * network the client is on.
2478 if ((shared_network_from_packet6(&shared
, packet
) != ISC_R_SUCCESS
) ||
2482 /* If there are no recorded subnets, then we have no
2483 * information about this subnet - ignore Confirms.
2485 subnet
= shared
->subnets
;
2489 /* Are the addresses in all the IA's appropriate for that link? */
2490 has_addrs
= inappropriate
= ISC_FALSE
;
2492 while(!inappropriate
) {
2493 /* If we've reached the end of the IA_NA pass, move to the
2496 if ((pass
== D6O_IA_NA
) && (ia
== NULL
)) {
2501 /* If we've reached the end of all passes, we're done. */
2505 if (((pass
== D6O_IA_NA
) &&
2506 !get_encapsulated_IA_state(&cli_enc_opt_state
,
2508 packet
, ia
, IA_NA_OFFSET
)) ||
2509 ((pass
== D6O_IA_TA
) &&
2510 !get_encapsulated_IA_state(&cli_enc_opt_state
,
2512 packet
, ia
, IA_TA_OFFSET
))) {
2516 oc
= lookup_option(&dhcpv6_universe
, cli_enc_opt_state
,
2519 for ( ; oc
!= NULL
; oc
= oc
->next
) {
2520 if (!evaluate_option_cache(&iaaddr
, packet
, NULL
, NULL
,
2521 packet
->options
, NULL
,
2522 &global_scope
, oc
, MDL
) ||
2523 (iaaddr
.len
< IAADDR_OFFSET
)) {
2524 log_error("dhcpv6_confirm: "
2525 "error evaluating IAADDR.");
2529 /* Copy out the IPv6 address for processing. */
2531 memcpy(cli_addr
.iabuf
, iaaddr
.data
, 16);
2533 data_string_forget(&iaaddr
, MDL
);
2535 /* Record that we've processed at least one address. */
2536 has_addrs
= ISC_TRUE
;
2538 /* Find out if any subnets cover this address. */
2539 for (subnet
= shared
->subnets
; subnet
!= NULL
;
2540 subnet
= subnet
->next_sibling
) {
2541 if (addr_eq(subnet_number(cli_addr
,
2547 /* If we reach the end of the subnet list, and no
2548 * subnet matches the client address, then it must
2549 * be inappropriate to the link (so far as our
2550 * configuration says). Once we've found one
2551 * inappropriate address, there is no reason to
2552 * continue searching.
2554 if (subnet
== NULL
) {
2555 inappropriate
= ISC_TRUE
;
2560 option_state_dereference(&cli_enc_opt_state
, MDL
);
2561 data_string_forget(&cli_enc_opt_data
, MDL
);
2563 /* Advance to the next IA_*. */
2567 /* If the client supplied no addresses, do not reply. */
2574 if (!start_reply(packet
, &client_id
, NULL
, &opt_state
, reply
)) {
2581 if (inappropriate
) {
2582 if (!set_status_code(STATUS_NotOnLink
,
2583 "Some of the addresses are not on link.",
2588 if (!set_status_code(STATUS_Success
,
2589 "All addresses still on link.",
2596 * Only one option: add it.
2598 reply_ofs
+= store_options6(reply_data
+reply_ofs
,
2599 sizeof(reply_data
)-reply_ofs
,
2601 required_opts
, &packet_oro
);
2604 * Return our reply to the caller.
2606 reply_ret
->len
= reply_ofs
;
2607 reply_ret
->buffer
= NULL
;
2608 if (!buffer_allocate(&reply_ret
->buffer
, reply_ofs
, MDL
)) {
2609 log_fatal("No memory to store reply.");
2611 reply_ret
->data
= reply_ret
->buffer
->data
;
2612 memcpy(reply_ret
->buffer
->data
, reply
, reply_ofs
);
2615 /* Cleanup any stale data strings. */
2616 if (cli_enc_opt_data
.buffer
!= NULL
)
2617 data_string_forget(&cli_enc_opt_data
, MDL
);
2618 if (iaaddr
.buffer
!= NULL
)
2619 data_string_forget(&iaaddr
, MDL
);
2620 if (client_id
.buffer
!= NULL
)
2621 data_string_forget(&client_id
, MDL
);
2622 if (packet_oro
.buffer
!= NULL
)
2623 data_string_forget(&packet_oro
, MDL
);
2625 /* Release any stale option states. */
2626 if (cli_enc_opt_state
!= NULL
)
2627 option_state_dereference(&cli_enc_opt_state
, MDL
);
2628 if (opt_state
!= NULL
)
2629 option_state_dereference(&opt_state
, MDL
);
2633 * Renew is when a client wants to extend its lease, at time T1.
2635 * We handle this the same as if the client wants a new lease, except
2636 * for the error code of when addresses don't match.
2639 /* TODO: reject unicast messages, unless we set unicast option */
2641 dhcpv6_renew(struct data_string
*reply
, struct packet
*packet
) {
2642 struct data_string client_id
;
2643 struct data_string server_id
;
2646 * Validate the request.
2648 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
2655 lease_to_client(reply
, packet
, &client_id
, &server_id
);
2660 data_string_forget(&server_id
, MDL
);
2661 data_string_forget(&client_id
, MDL
);
2665 * Rebind is when a client wants to extend its lease, at time T2.
2667 * We handle this the same as if the client wants a new lease, except
2668 * for the error code of when addresses don't match.
2672 dhcpv6_rebind(struct data_string
*reply
, struct packet
*packet
) {
2673 struct data_string client_id
;
2675 if (!valid_client_msg(packet
, &client_id
)) {
2679 lease_to_client(reply
, packet
, &client_id
, NULL
);
2681 data_string_forget(&client_id
, MDL
);
2685 ia_na_match_decline(const struct data_string
*client_id
,
2686 const struct data_string
*iaaddr
,
2687 struct iaaddr
*lease
)
2689 char tmp_addr
[INET6_ADDRSTRLEN
];
2691 log_error("Client %s reports address %s is "
2692 "already in use by another host!",
2693 print_hex_1(client_id
->len
, client_id
->data
, 60),
2694 inet_ntop(AF_INET6
, iaaddr
->data
,
2695 tmp_addr
, sizeof(tmp_addr
)));
2696 if (lease
!= NULL
) {
2697 decline_lease6(lease
->ipv6_pool
, lease
);
2698 write_ia_na(lease
->ia_na
);
2703 ia_na_nomatch_decline(const struct data_string
*client_id
,
2704 const struct data_string
*iaaddr
,
2705 u_int32_t
*ia_na_id
,
2706 struct packet
*packet
,
2711 char tmp_addr
[INET6_ADDRSTRLEN
];
2712 struct option_state
*host_opt_state
;
2715 log_info("Client %s declines address %s, which is not offered to it.",
2716 print_hex_1(client_id
->len
, client_id
->data
, 60),
2717 inet_ntop(AF_INET6
, iaaddr
->data
, tmp_addr
, sizeof(tmp_addr
)));
2720 * Create state for this IA_NA.
2722 host_opt_state
= NULL
;
2723 if (!option_state_allocate(&host_opt_state
, MDL
)) {
2724 log_error("ia_na_nomatch_decline: out of memory "
2725 "allocating option_state.");
2729 if (!set_status_code(STATUS_NoBinding
, "Decline for unknown address.",
2735 * Insure we have enough space
2737 if (reply_len
< (*reply_ofs
+ 16)) {
2738 log_error("ia_na_nomatch_decline: "
2739 "out of space for reply packet.");
2744 * Put our status code into the reply packet.
2746 len
= store_options6(reply_data
+(*reply_ofs
)+16,
2747 reply_len
-(*reply_ofs
)-16,
2748 host_opt_state
, packet
,
2749 required_opts_STATUS_CODE
, NULL
);
2752 * Store the non-encapsulated option data for this
2753 * IA_NA into our reply packet. Defined in RFC 3315,
2757 putUShort((unsigned char *)reply_data
+(*reply_ofs
), D6O_IA_NA
);
2759 putUShort((unsigned char *)reply_data
+(*reply_ofs
)+2, len
+ 12);
2760 /* IA_NA, copied from the client */
2761 memcpy(reply_data
+(*reply_ofs
)+4, ia_na_id
, 4);
2762 /* t1 and t2, odd that we need them, but here it is */
2763 putULong((unsigned char *)reply_data
+(*reply_ofs
)+8, 0);
2764 putULong((unsigned char *)reply_data
+(*reply_ofs
)+12, 0);
2767 * Get ready for next IA_NA.
2769 *reply_ofs
+= (len
+ 16);
2772 option_state_dereference(&host_opt_state
, MDL
);
2776 iterate_over_ia_na(struct data_string
*reply_ret
,
2777 struct packet
*packet
,
2778 const struct data_string
*client_id
,
2779 const struct data_string
*server_id
,
2780 const char *packet_type
,
2781 void (*ia_na_match
)(),
2782 void (*ia_na_nomatch
)())
2784 struct option_state
*opt_state
;
2785 struct host_decl
*packet_host
;
2786 struct option_cache
*ia
;
2787 struct option_cache
*oc
;
2788 /* cli_enc_... variables come from the IA_NA/IA_TA options */
2789 struct data_string cli_enc_opt_data
;
2790 struct option_state
*cli_enc_opt_state
;
2791 struct host_decl
*host
;
2792 struct option_state
*host_opt_state
;
2793 struct data_string iaaddr
;
2794 struct data_string fixed_addr
;
2795 int iaaddr_is_found
;
2796 char reply_data
[65536];
2797 struct dhcpv6_packet
*reply
= (struct dhcpv6_packet
*)reply_data
;
2798 int reply_ofs
= (int)((char *)reply
->options
- (char *)reply
);
2799 char status_msg
[32];
2800 struct iaaddr
*lease
;
2801 struct ia_na
*existing_ia_na
;
2803 struct data_string key
;
2807 * Initialize to empty values, in case we have to exit early.
2810 memset(&cli_enc_opt_data
, 0, sizeof(cli_enc_opt_data
));
2811 cli_enc_opt_state
= NULL
;
2812 memset(&iaaddr
, 0, sizeof(iaaddr
));
2813 memset(&fixed_addr
, 0, sizeof(fixed_addr
));
2814 host_opt_state
= NULL
;
2818 * Find the host record that matches from the packet, if any.
2821 if (!find_hosts_by_uid(&packet_host
,
2822 client_id
->data
, client_id
->len
, MDL
)) {
2825 * Note: In general, we don't expect a client to provide
2826 * enough information to match by option for these
2827 * types of messages, but if we don't have a UID
2828 * match we can check anyway.
2830 if (!find_hosts_by_option(&packet_host
,
2831 packet
, packet
->options
, MDL
)) {
2837 * Set our reply information.
2839 reply
->msg_type
= DHCPV6_REPLY
;
2840 memcpy(reply
->transaction_id
, packet
->dhcpv6_transaction_id
,
2841 sizeof(reply
->transaction_id
));
2844 * Build our option state for reply.
2847 if (!option_state_allocate(&opt_state
, MDL
)) {
2848 log_error("iterate_over_ia_na: no memory for option_state.");
2851 execute_statements_in_scope(NULL
, packet
, NULL
, NULL
,
2852 packet
->options
, opt_state
,
2853 &global_scope
, root_group
, NULL
);
2856 * RFC 3315, section 18.2.7 tells us which options to include.
2858 oc
= lookup_option(&dhcpv6_universe
, opt_state
, D6O_SERVERID
);
2860 if (!save_option_buffer(&dhcpv6_universe
, opt_state
, NULL
,
2861 (unsigned char *)server_duid
.data
,
2862 server_duid
.len
, D6O_SERVERID
, 0)) {
2863 log_error("iterate_over_ia_na: "
2864 "error saving server identifier.");
2869 if (!save_option_buffer(&dhcpv6_universe
, opt_state
,
2871 (unsigned char *)client_id
->data
,
2874 log_error("iterate_over_ia_na: "
2875 "error saving client identifier.");
2879 snprintf(status_msg
, sizeof(status_msg
), "%s received.", packet_type
);
2880 if (!set_status_code(STATUS_Success
, status_msg
, opt_state
)) {
2885 * Add our options that are not associated with any IA_NA or IA_TA.
2887 reply_ofs
+= store_options6(reply_data
+reply_ofs
,
2888 sizeof(reply_data
)-reply_ofs
,
2890 required_opts
, NULL
);
2893 * Loop through the IA_NA reported by the client, and deal with
2894 * addresses reported as already in use.
2896 for (ia
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_IA_NA
);
2897 ia
!= NULL
; ia
= ia
->next
) {
2898 iaaddr_is_found
= 0;
2900 if (!get_encapsulated_IA_state(&cli_enc_opt_state
,
2902 packet
, ia
, IA_NA_OFFSET
)) {
2906 iaid
= getULong(cli_enc_opt_data
.data
);
2909 * XXX: It is possible that we can get multiple addresses
2910 * sent by the client. We don't send multiple
2911 * addresses, so this indicates a client error.
2912 * We should check for multiple IAADDR options, log
2913 * if found, and set as an error.
2915 oc
= lookup_option(&dhcpv6_universe
, cli_enc_opt_state
,
2918 /* no address given for this IA, ignore */
2919 option_state_dereference(&cli_enc_opt_state
, MDL
);
2920 data_string_forget(&cli_enc_opt_data
, MDL
);
2924 memset(&iaaddr
, 0, sizeof(iaaddr
));
2925 if (!evaluate_option_cache(&iaaddr
, packet
, NULL
, NULL
,
2926 packet
->options
, NULL
,
2927 &global_scope
, oc
, MDL
)) {
2928 log_error("iterate_over_ia_na: "
2929 "error evaluating IAADDR.");
2934 * Now we need to figure out which host record matches
2935 * this IA_NA and IAADDR.
2937 * XXX: We don't currently track IA_NA separately, but
2938 * we will need to do this!
2941 if (!find_hosts_by_option(&host
, packet
,
2942 cli_enc_opt_state
, MDL
)) {
2943 if (packet_host
!= NULL
) {
2949 while (host
!= NULL
) {
2950 if (host
->fixed_addr
!= NULL
) {
2951 if (!evaluate_option_cache(&fixed_addr
, NULL
,
2953 NULL
, &global_scope
,
2956 log_error("iterate_over_ia_na: error "
2957 "evaluating host address.");
2960 if ((iaaddr
.len
>= 16) &&
2961 !memcmp(fixed_addr
.data
, iaaddr
.data
, 16)) {
2962 data_string_forget(&fixed_addr
, MDL
);
2965 data_string_forget(&fixed_addr
, MDL
);
2967 host
= host
->n_ipaddr
;
2970 if ((host
== NULL
) && (iaaddr
.len
>= IAADDR_OFFSET
)) {
2972 * Find existing IA_NA.
2974 if (ia_na_make_key(&key
, iaid
,
2975 (char *)client_id
->data
,
2977 MDL
) != ISC_R_SUCCESS
) {
2978 log_fatal("iterate_over_ia_na: no memory for "
2982 existing_ia_na
= NULL
;
2983 if (ia_na_hash_lookup(&existing_ia_na
, ia_active
,
2984 (unsigned char *)key
.data
,
2987 * Make sure this address is in the IA_NA.
2989 for (i
=0; i
<existing_ia_na
->num_iaaddr
; i
++) {
2991 struct in6_addr
*in6_addr
;
2993 tmp
= existing_ia_na
->iaaddr
[i
];
2994 in6_addr
= &tmp
->addr
;
2995 if (memcmp(in6_addr
,
2996 iaaddr
.data
, 16) == 0) {
2997 iaaddr_reference(&lease
,
3004 data_string_forget(&key
, MDL
);
3007 if ((host
!= NULL
) || (lease
!= NULL
)) {
3008 ia_na_match(client_id
, &iaaddr
, lease
);
3010 ia_na_nomatch(client_id
, &iaaddr
,
3011 (u_int32_t
*)cli_enc_opt_data
.data
,
3012 packet
, reply_data
, &reply_ofs
,
3013 sizeof(reply_data
));
3016 if (lease
!= NULL
) {
3017 iaaddr_dereference(&lease
, MDL
);
3020 data_string_forget(&iaaddr
, MDL
);
3021 option_state_dereference(&cli_enc_opt_state
, MDL
);
3022 data_string_forget(&cli_enc_opt_data
, MDL
);
3026 * Return our reply to the caller.
3028 reply_ret
->len
= reply_ofs
;
3029 reply_ret
->buffer
= NULL
;
3030 if (!buffer_allocate(&reply_ret
->buffer
, reply_ofs
, MDL
)) {
3031 log_fatal("No memory to store reply.");
3033 reply_ret
->data
= reply_ret
->buffer
->data
;
3034 memcpy(reply_ret
->buffer
->data
, reply
, reply_ofs
);
3037 if (lease
!= NULL
) {
3038 iaaddr_dereference(&lease
, MDL
);
3040 if (host_opt_state
!= NULL
) {
3041 option_state_dereference(&host_opt_state
, MDL
);
3043 if (fixed_addr
.buffer
!= NULL
) {
3044 data_string_forget(&fixed_addr
, MDL
);
3046 if (iaaddr
.buffer
!= NULL
) {
3047 data_string_forget(&iaaddr
, MDL
);
3049 if (cli_enc_opt_state
!= NULL
) {
3050 option_state_dereference(&cli_enc_opt_state
, MDL
);
3052 if (cli_enc_opt_data
.buffer
!= NULL
) {
3053 data_string_forget(&cli_enc_opt_data
, MDL
);
3055 if (opt_state
!= NULL
) {
3056 option_state_dereference(&opt_state
, MDL
);
3061 * Decline means a client has detected that something else is using an
3062 * address we gave it.
3064 * Since we're only dealing with fixed leases for now, there's not
3065 * much we can do, other that log the occurrence.
3067 * When we start issuing addresses from pools, then we will have to
3068 * record our declined addresses and issue another. In general with
3069 * IPv6 there is no worry about DoS by clients exhausting space, but
3070 * we still need to be aware of this possibility.
3073 /* TODO: reject unicast messages, unless we set unicast option */
3076 dhcpv6_decline(struct data_string
*reply
, struct packet
*packet
) {
3077 struct data_string client_id
;
3078 struct data_string server_id
;
3081 * Validate our input.
3083 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
3088 * And operate on each IA_NA in this packet.
3090 iterate_over_ia_na(reply
, packet
, &client_id
, &server_id
, "Decline",
3091 ia_na_match_decline
, ia_na_nomatch_decline
);
3095 ia_na_match_release(const struct data_string
*client_id
,
3096 const struct data_string
*iaaddr
,
3097 struct iaaddr
*lease
)
3099 char tmp_addr
[INET6_ADDRSTRLEN
];
3101 log_info("Client %s releases address %s",
3102 print_hex_1(client_id
->len
, client_id
->data
, 60),
3103 inet_ntop(AF_INET6
, iaaddr
->data
, tmp_addr
, sizeof(tmp_addr
)));
3104 if (lease
!= NULL
) {
3105 release_lease6(lease
->ipv6_pool
, lease
);
3106 write_ia_na(lease
->ia_na
);
3111 ia_na_nomatch_release(const struct data_string
*client_id
,
3112 const struct data_string
*iaaddr
,
3113 u_int32_t
*ia_na_id
,
3114 struct packet
*packet
,
3119 char tmp_addr
[INET6_ADDRSTRLEN
];
3120 struct option_state
*host_opt_state
;
3123 log_info("Client %s releases address %s, which is not leased to it.",
3124 print_hex_1(client_id
->len
, client_id
->data
, 60),
3125 inet_ntop(AF_INET6
, iaaddr
->data
, tmp_addr
, sizeof(tmp_addr
)));
3128 * Create state for this IA_NA.
3130 host_opt_state
= NULL
;
3131 if (!option_state_allocate(&host_opt_state
, MDL
)) {
3132 log_error("ia_na_nomatch_release: out of memory "
3133 "allocating option_state.");
3137 if (!set_status_code(STATUS_NoBinding
,
3138 "Release for non-leased address.",
3144 * Insure we have enough space
3146 if (reply_len
< (*reply_ofs
+ 16)) {
3147 log_error("ia_na_nomatch_release: "
3148 "out of space for reply packet.");
3153 * Put our status code into the reply packet.
3155 len
= store_options6(reply_data
+(*reply_ofs
)+16,
3156 reply_len
-(*reply_ofs
)-16,
3157 host_opt_state
, packet
,
3158 required_opts_STATUS_CODE
, NULL
);
3161 * Store the non-encapsulated option data for this
3162 * IA_NA into our reply packet. Defined in RFC 3315,
3166 putUShort((unsigned char *)reply_data
+(*reply_ofs
), D6O_IA_NA
);
3168 putUShort((unsigned char *)reply_data
+(*reply_ofs
)+2, len
+ 12);
3169 /* IA_NA, copied from the client */
3170 memcpy(reply_data
+(*reply_ofs
)+4, ia_na_id
, 4);
3171 /* t1 and t2, odd that we need them, but here it is */
3172 putULong((unsigned char *)reply_data
+(*reply_ofs
)+8, 0);
3173 putULong((unsigned char *)reply_data
+(*reply_ofs
)+12, 0);
3176 * Get ready for next IA_NA.
3178 *reply_ofs
+= (len
+ 16);
3181 option_state_dereference(&host_opt_state
, MDL
);
3185 * Release means a client is done with the addresses.
3188 /* TODO: reject unicast messages, unless we set unicast option */
3190 dhcpv6_release(struct data_string
*reply
, struct packet
*packet
) {
3191 struct data_string client_id
;
3192 struct data_string server_id
;
3195 * Validate our input.
3197 if (!valid_client_resp(packet
, &client_id
, &server_id
)) {
3202 * And operate on each IA_NA in this packet.
3204 iterate_over_ia_na(reply
, packet
, &client_id
, &server_id
, "Release",
3205 ia_na_match_release
, ia_na_nomatch_release
);
3207 data_string_forget(&server_id
, MDL
);
3208 data_string_forget(&client_id
, MDL
);
3212 * Information-Request is used by clients who have obtained an address
3213 * from other means, but want configuration information from the server.
3217 dhcpv6_information_request(struct data_string
*reply
, struct packet
*packet
) {
3218 struct data_string client_id
;
3219 struct data_string server_id
;
3222 * Validate our input.
3224 if (!valid_client_info_req(packet
, &server_id
)) {
3229 * Get our client ID, if there is one.
3231 memset(&client_id
, 0, sizeof(client_id
));
3232 if (get_client_id(packet
, &client_id
) != ISC_R_SUCCESS
) {
3233 data_string_forget(&client_id
, MDL
);
3237 * Use the lease_to_client() function. This will work fine,
3238 * because the valid_client_info_req() insures that we
3239 * don't have any IA_NA or IA_TA that would cause us to
3240 * allocate addresses to the client.
3242 lease_to_client(reply
, packet
, &client_id
,
3243 server_id
.data
!= NULL
? &server_id
: NULL
);
3248 if (client_id
.data
!= NULL
) {
3249 data_string_forget(&client_id
, MDL
);
3251 data_string_forget(&server_id
, MDL
);
3255 * The Relay-forw message is sent by relays. It typically contains a
3256 * single option, which encapsulates an entire packet.
3258 * We need to build an encapsulated reply.
3261 /* XXX: this is very, very similar to do_packet6(), and should probably
3262 be combined in a clever way */
3264 dhcpv6_relay_forw(struct data_string
*reply_ret
, struct packet
*packet
) {
3265 struct dhcpv6_relay_packet reply
;
3266 struct option_cache
*oc
;
3267 struct data_string enc_opt_data
;
3268 struct packet
*enc_packet
;
3269 unsigned char msg_type
;
3270 const struct dhcpv6_packet
*msg
;
3271 const struct dhcpv6_relay_packet
*relay
;
3272 struct data_string enc_reply
;
3273 char link_addr
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
3274 char peer_addr
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
3275 struct data_string interface_id
;
3278 * Initialize variables for early exit.
3280 memset(&enc_opt_data
, 0, sizeof(enc_opt_data
));
3282 memset(&enc_reply
, 0, sizeof(enc_reply
));
3283 memset(&interface_id
, 0, sizeof(interface_id
));
3286 * Get our encapsulated relay message.
3288 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_RELAY_MSG
);
3290 inet_ntop(AF_INET6
, &packet
->dhcpv6_link_address
,
3291 link_addr
, sizeof(link_addr
));
3292 inet_ntop(AF_INET6
, &packet
->dhcpv6_peer_address
,
3293 peer_addr
, sizeof(peer_addr
));
3294 log_info("Relay-forward from %s with link address=%s and "
3295 "peer address=%s missing Relay Message option.",
3296 piaddr(packet
->client_addr
), link_addr
, peer_addr
);
3300 memset(&enc_opt_data
, 0, sizeof(enc_opt_data
));
3301 if (!evaluate_option_cache(&enc_opt_data
, NULL
, NULL
, NULL
,
3302 NULL
, NULL
, &global_scope
, oc
, MDL
)) {
3303 log_error("dhcpv6_forw_relay: error evaluating "
3304 "relayed message.");
3308 if (!packet6_len_okay((char *)enc_opt_data
.data
, enc_opt_data
.len
)) {
3309 log_error("dhcpv6_forw_relay: encapsulated packet too short.");
3314 * Build a packet structure from this encapsulated packet.
3317 if (!packet_allocate(&enc_packet
, MDL
)) {
3318 log_error("dhcpv6_forw_relay: "
3319 "no memory for encapsulated packet.");
3323 if (!option_state_allocate(&enc_packet
->options
, MDL
)) {
3324 log_error("dhcpv6_forw_relay: "
3325 "no memory for encapsulated packet's options.");
3329 enc_packet
->client_port
= packet
->client_port
;
3330 enc_packet
->client_addr
= packet
->client_addr
;
3331 enc_packet
->dhcpv6_container_packet
= packet
;
3333 msg_type
= enc_opt_data
.data
[0];
3334 if ((msg_type
== DHCPV6_RELAY_FORW
) ||
3335 (msg_type
== DHCPV6_RELAY_REPL
)) {
3336 relay
= (struct dhcpv6_relay_packet
*)enc_opt_data
.data
;
3337 enc_packet
->dhcpv6_msg_type
= relay
->msg_type
;
3339 /* relay-specific data */
3340 enc_packet
->dhcpv6_hop_count
= relay
->hop_count
;
3341 memcpy(&enc_packet
->dhcpv6_link_address
,
3342 relay
->link_address
, sizeof(relay
->link_address
));
3343 memcpy(&enc_packet
->dhcpv6_peer_address
,
3344 relay
->peer_address
, sizeof(relay
->peer_address
));
3346 if (!parse_option_buffer(enc_packet
->options
,
3348 enc_opt_data
.len
-sizeof(*relay
),
3349 &dhcpv6_universe
)) {
3350 /* no logging here, as parse_option_buffer() logs all
3351 cases where it fails */
3355 msg
= (struct dhcpv6_packet
*)enc_opt_data
.data
;
3356 enc_packet
->dhcpv6_msg_type
= msg
->msg_type
;
3358 /* message-specific data */
3359 memcpy(enc_packet
->dhcpv6_transaction_id
,
3360 msg
->transaction_id
,
3361 sizeof(enc_packet
->dhcpv6_transaction_id
));
3363 if (!parse_option_buffer(enc_packet
->options
,
3365 enc_opt_data
.len
-sizeof(*msg
),
3366 &dhcpv6_universe
)) {
3367 /* no logging here, as parse_option_buffer() logs all
3368 cases where it fails */
3374 * This is recursive. It is possible to exceed maximum packet size.
3375 * XXX: This will cause the packet send to fail.
3377 build_dhcpv6_reply(&enc_reply
, enc_packet
);
3380 * If we got no encapsulated data, then it is discarded, and
3381 * our reply-forw is also discarded.
3383 if (enc_reply
.data
== NULL
) {
3388 * Append the interface-id if present
3390 oc
= lookup_option(&dhcpv6_universe
, packet
->options
, D6O_INTERFACE_ID
);
3392 memset(&interface_id
, 0, sizeof(interface_id
));
3393 if (!evaluate_option_cache(&interface_id
, NULL
, NULL
, NULL
,
3394 NULL
, NULL
, &global_scope
,
3396 log_error("dhcpv6_forw_relay: error evaluating "
3403 * Packet header stuff all comes from the forward message.
3405 reply
.msg_type
= DHCPV6_RELAY_REPL
;
3406 reply
.hop_count
= packet
->dhcpv6_hop_count
;
3407 memcpy(reply
.link_address
, &packet
->dhcpv6_link_address
,
3408 sizeof(reply
.link_address
));
3409 memcpy(reply
.peer_address
, &packet
->dhcpv6_peer_address
,
3410 sizeof(reply
.peer_address
));
3413 * Copy our encapsulated stuff for caller.
3415 reply_ret
->len
= sizeof(reply
) + 4 + enc_reply
.len
;
3416 if (interface_id
.data
!= NULL
) {
3417 reply_ret
->len
+= 4 + interface_id
.len
;
3420 * XXX: We should not allow this to happen, perhaps by letting
3421 * build_dhcp_reply() know our space remaining.
3423 if (reply_ret
->len
>= 65536) {
3424 log_error("dhcpv6_forw_relay: RELAY-REPL too big (%d bytes)",
3428 reply_ret
->buffer
= NULL
;
3429 if (!buffer_allocate(&reply_ret
->buffer
, reply_ret
->len
, MDL
)) {
3430 log_fatal("No memory to store reply.");
3432 reply_ret
->data
= reply_ret
->buffer
->data
;
3433 memcpy(reply_ret
->buffer
->data
, &reply
, sizeof(reply
));
3434 putShort(reply_ret
->buffer
->data
+sizeof(reply
), D6O_RELAY_MSG
);
3435 putShort(reply_ret
->buffer
->data
+sizeof(reply
)+2, enc_reply
.len
);
3436 memcpy(reply_ret
->buffer
->data
+sizeof(reply
)+4,
3437 enc_reply
.data
, enc_reply
.len
);
3438 if (interface_id
.data
!= NULL
) {
3439 putShort(reply_ret
->buffer
->data
+sizeof(reply
)+4+enc_reply
.len
,
3441 putShort(reply_ret
->buffer
->data
+sizeof(reply
)+6+enc_reply
.len
,
3443 memcpy(reply_ret
->buffer
->data
+sizeof(reply
)+8+enc_reply
.len
,
3444 interface_id
.data
, interface_id
.len
);
3448 if (interface_id
.data
!= NULL
) {
3449 data_string_forget(&interface_id
, MDL
);
3451 if (enc_reply
.data
!= NULL
) {
3452 data_string_forget(&enc_reply
, MDL
);
3454 if (enc_opt_data
.data
!= NULL
) {
3455 data_string_forget(&enc_opt_data
, MDL
);
3457 if (enc_packet
!= NULL
) {
3458 packet_dereference(&enc_packet
, MDL
);
3463 dhcpv6_discard(struct packet
*packet
) {
3464 /* INSIST(packet->msg_type > 0); */
3465 /* INSIST(packet->msg_type < dhcpv6_type_name_max); */
3467 log_debug("Discarding %s from %s; message type not handled by server",
3468 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
3469 piaddr(packet
->client_addr
));
3473 build_dhcpv6_reply(struct data_string
*reply
, struct packet
*packet
) {
3474 memset(reply
, 0, sizeof(*reply
));
3475 switch (packet
->dhcpv6_msg_type
) {
3476 case DHCPV6_SOLICIT
:
3477 dhcpv6_solicit(reply
, packet
);
3479 case DHCPV6_ADVERTISE
:
3480 dhcpv6_discard(packet
);
3482 case DHCPV6_REQUEST
:
3483 dhcpv6_request(reply
, packet
);
3485 case DHCPV6_CONFIRM
:
3486 dhcpv6_confirm(reply
, packet
);
3489 dhcpv6_renew(reply
, packet
);
3492 dhcpv6_rebind(reply
, packet
);
3495 dhcpv6_discard(packet
);
3497 case DHCPV6_RELEASE
:
3498 dhcpv6_release(reply
, packet
);
3500 case DHCPV6_DECLINE
:
3501 dhcpv6_decline(reply
, packet
);
3503 case DHCPV6_RECONFIGURE
:
3504 dhcpv6_discard(packet
);
3506 case DHCPV6_INFORMATION_REQUEST
:
3507 dhcpv6_information_request(reply
, packet
);
3509 case DHCPV6_RELAY_FORW
:
3510 dhcpv6_relay_forw(reply
, packet
);
3512 case DHCPV6_RELAY_REPL
:
3513 dhcpv6_discard(packet
);
3516 /* XXX: would be nice if we had "notice" level,
3517 as syslog, for this */
3518 log_info("Discarding unknown DHCPv6 message type %d "
3519 "from %s", packet
->dhcpv6_msg_type
,
3520 piaddr(packet
->client_addr
));
3525 log_packet_in(const struct packet
*packet
) {
3526 struct data_string s
;
3528 char tmp_addr
[INET6_ADDRSTRLEN
];
3531 memset(&s
, 0, sizeof(s
));
3533 if (packet
->dhcpv6_msg_type
< dhcpv6_type_name_max
) {
3534 data_string_sprintfa(&s
, "%s message from %s port %d",
3535 dhcpv6_type_names
[packet
->dhcpv6_msg_type
],
3536 piaddr(packet
->client_addr
),
3537 ntohs(packet
->client_port
));
3539 data_string_sprintfa(&s
,
3540 "Unknown message type %d from %s port %d",
3541 packet
->dhcpv6_msg_type
,
3542 piaddr(packet
->client_addr
),
3543 ntohs(packet
->client_port
));
3545 if ((packet
->dhcpv6_msg_type
== DHCPV6_RELAY_FORW
) ||
3546 (packet
->dhcpv6_msg_type
== DHCPV6_RELAY_REPL
)) {
3547 addr
= &packet
->dhcpv6_link_address
;
3548 data_string_sprintfa(&s
, ", link address %s",
3549 inet_ntop(AF_INET6
, addr
,
3550 tmp_addr
, sizeof(tmp_addr
)));
3551 addr
= &packet
->dhcpv6_peer_address
;
3552 data_string_sprintfa(&s
, ", peer address %s",
3553 inet_ntop(AF_INET6
, addr
,
3554 tmp_addr
, sizeof(tmp_addr
)));
3557 memcpy(((char *)&tid
)+1, packet
->dhcpv6_transaction_id
, 3);
3558 data_string_sprintfa(&s
, ", transaction ID 0x%06X", tid
);
3561 oc = lookup_option(&dhcpv6_universe, packet->options,
3564 memset(&tmp_ds, 0, sizeof(tmp_ds_));
3565 if (!evaluate_option_cache(&tmp_ds, packet, NULL, NULL,
3566 packet->options, NULL,
3567 &global_scope, oc, MDL)) {
3568 log_error("Error evaluating Client Identifier");
3570 data_strint_sprintf(&s, ", client ID %s",
3572 data_string_forget(&tmp_ds, MDL);
3578 log_info("%s", s
.data
);
3580 data_string_forget(&s
, MDL
);
3584 dhcpv6(struct packet
*packet
) {
3585 struct data_string reply
;
3586 struct sockaddr_in6 to_addr
;
3590 * Log a message that we received this packet.
3592 log_packet_in(packet
);
3595 * Build our reply packet.
3597 build_dhcpv6_reply(&reply
, packet
);
3599 if (reply
.data
!= NULL
) {
3601 * Send our reply, if we have one.
3603 memset(&to_addr
, 0, sizeof(to_addr
));
3604 to_addr
.sin6_family
= AF_INET6
;
3605 if ((packet
->dhcpv6_msg_type
== DHCPV6_RELAY_FORW
) ||
3606 (packet
->dhcpv6_msg_type
== DHCPV6_RELAY_REPL
)) {
3607 to_addr
.sin6_port
= local_port
;
3609 to_addr
.sin6_port
= remote_port
;
3611 /* For testing, we reply to the sending port, so we don't need a root client */
3612 to_addr
.sin6_port
= packet
->client_port
;
3613 memcpy(&to_addr
.sin6_addr
, packet
->client_addr
.iabuf
,
3614 sizeof(to_addr
.sin6_addr
));
3616 log_info("Sending %s to %s port %d",
3617 dhcpv6_type_names
[reply
.data
[0]],
3618 piaddr(packet
->client_addr
),
3619 ntohs(to_addr
.sin6_port
));
3621 send_ret
= send_packet6(packet
->interface
,
3622 reply
.data
, reply
.len
, &to_addr
);
3623 if (send_ret
!= reply
.len
) {
3624 log_error("dhcpv6: send_packet6() sent %d of %d bytes",
3625 send_ret
, reply
.len
);
3627 data_string_forget(&reply
, MDL
);
3632 seek_shared_host(struct host_decl
**hp
, struct shared_network
*shared
) {
3633 struct host_decl
*nofixed
= NULL
;
3634 struct host_decl
*seek
, *hold
= NULL
;
3637 * Seek forward through fixed addresses for the right broadcast
3640 host_reference(&hold
, *hp
, MDL
);
3641 host_dereference(hp
, MDL
);
3643 while (seek
!= NULL
) {
3644 if (seek
->fixed_addr
== NULL
)
3646 else if (fixed_matches_shared(seek
, shared
))
3649 seek
= seek
->n_ipaddr
;
3652 if ((seek
== NULL
) && (nofixed
!= NULL
))
3656 host_reference(hp
, seek
, MDL
);
3659 static isc_boolean_t
3660 fixed_matches_shared(struct host_decl
*host
, struct shared_network
*shared
) {
3661 struct subnet
*subnet
;
3662 struct data_string addr
;
3663 isc_boolean_t matched
;
3666 if (host
->fixed_addr
== NULL
)
3669 memset(&addr
, 0, sizeof(addr
));
3670 if (!evaluate_option_cache(&addr
, NULL
, NULL
, NULL
, NULL
, NULL
,
3671 &global_scope
, host
->fixed_addr
, MDL
))
3674 if (addr
.len
< 16) {
3675 data_string_forget(&addr
, MDL
);
3680 memcpy(fixed
.iabuf
, addr
.data
, 16);
3682 matched
= ISC_FALSE
;
3683 for (subnet
= shared
->subnets
; subnet
!= NULL
;
3684 subnet
= subnet
->next_sibling
) {
3685 if (addr_eq(subnet_number(fixed
, subnet
->netmask
),
3692 data_string_forget(&addr
, MDL
);