Remove building with NOCRYPTO option
[minix.git] / external / bsd / dhcp / dist / server / dhcpv6.c
blob6786df4d7dae374bcf0b35177ce9a8c46d30d483
1 /* $NetBSD: dhcpv6.c,v 1.5 2014/07/12 12:09:38 spz Exp $ */
2 /*
3 * Copyright (C) 2006-2013 by Internet Systems Consortium, Inc. ("ISC")
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 #include <sys/cdefs.h>
19 __RCSID("$NetBSD: dhcpv6.c,v 1.5 2014/07/12 12:09:38 spz Exp $");
21 /*! \file server/dhcpv6.c */
23 #include "dhcpd.h"
25 #ifdef DHCPv6
28 * We use print_hex_1() to output DUID values. We could actually output
29 * the DUID with more information... MAC address if using type 1 or 3,
30 * and so on. However, RFC 3315 contains Grave Warnings against actually
31 * attempting to understand a DUID.
34 /*
35 * TODO: gettext() or other method of localization for the messages
36 * for status codes (and probably for log formats eventually)
37 * TODO: refactoring (simplify, simplify, simplify)
38 * TODO: support multiple shared_networks on each interface (this
39 * will allow the server to issue multiple IPv6 addresses to
40 * a single interface)
44 * DHCPv6 Reply workflow assist. A Reply packet is built by various
45 * different functions; this gives us one location where we keep state
46 * regarding a reply.
48 struct reply_state {
49 /* root level persistent state */
50 struct shared_network *shared;
51 struct host_decl *host;
52 struct subnet *subnet; /* Used to match fixed-addrs to subnet scopes. */
53 struct option_state *opt_state;
54 struct packet *packet;
55 struct data_string client_id;
57 /* IA level persistent state */
58 unsigned ia_count;
59 unsigned pd_count;
60 unsigned client_resources;
61 isc_boolean_t resources_included;
62 isc_boolean_t static_lease;
63 unsigned static_prefixes;
64 struct ia_xx *ia;
65 struct ia_xx *old_ia;
66 struct option_state *reply_ia;
67 struct data_string fixed;
68 struct iaddrcidrnet fixed_pref; /* static prefix for logging */
70 /* IAADDR/PREFIX level persistent state */
71 struct iasubopt *lease;
74 * "t1", "t2", preferred, and valid lifetimes records for calculating
75 * t1 and t2 (min/max).
77 u_int32_t renew, rebind, prefer, valid;
79 /* Client-requested valid and preferred lifetimes. */
80 u_int32_t client_valid, client_prefer;
82 /* Chosen values to transmit for valid and preferred lifetimes. */
83 u_int32_t send_valid, send_prefer;
85 /* Preferred prefix length (-1 is any). */
86 int preflen;
88 /* Index into the data field that has been consumed. */
89 unsigned cursor;
91 /* Space for the on commit statements for a fixed host */
92 struct on_star on_star;
94 union reply_buffer {
95 unsigned char data[65536];
96 struct dhcpv6_packet reply;
97 } buf;
101 * Prototypes local to this file.
103 static int get_encapsulated_IA_state(struct option_state **enc_opt_state,
104 struct data_string *enc_opt_data,
105 struct packet *packet,
106 struct option_cache *oc,
107 int offset);
108 static void build_dhcpv6_reply(struct data_string *, struct packet *);
109 static isc_result_t shared_network_from_packet6(struct shared_network **shared,
110 struct packet *packet);
111 static void seek_shared_host(struct host_decl **hp,
112 struct shared_network *shared);
113 static isc_boolean_t fixed_matches_shared(struct host_decl *host,
114 struct shared_network *shared);
115 static isc_result_t reply_process_ia_na(struct reply_state *reply,
116 struct option_cache *ia);
117 static isc_result_t reply_process_ia_ta(struct reply_state *reply,
118 struct option_cache *ia);
119 static isc_result_t reply_process_addr(struct reply_state *reply,
120 struct option_cache *addr);
121 static isc_boolean_t address_is_owned(struct reply_state *reply,
122 struct iaddr *addr);
123 static isc_boolean_t temporary_is_available(struct reply_state *reply,
124 struct iaddr *addr);
125 static isc_result_t find_client_temporaries(struct reply_state *reply);
126 static isc_result_t reply_process_try_addr(struct reply_state *reply,
127 struct iaddr *addr);
128 static isc_result_t find_client_address(struct reply_state *reply);
129 static isc_result_t reply_process_is_addressed(struct reply_state *reply,
130 struct binding_scope **scope,
131 struct group *group);
132 static isc_result_t reply_process_send_addr(struct reply_state *reply,
133 struct iaddr *addr);
134 static struct iasubopt *lease_compare(struct iasubopt *alpha,
135 struct iasubopt *beta);
136 static isc_result_t reply_process_ia_pd(struct reply_state *reply,
137 struct option_cache *ia_pd);
138 static isc_result_t reply_process_prefix(struct reply_state *reply,
139 struct option_cache *pref);
140 static isc_boolean_t prefix_is_owned(struct reply_state *reply,
141 struct iaddrcidrnet *pref);
142 static isc_result_t find_client_prefix(struct reply_state *reply);
143 static isc_result_t reply_process_try_prefix(struct reply_state *reply,
144 struct iaddrcidrnet *pref);
145 static isc_result_t reply_process_is_prefixed(struct reply_state *reply,
146 struct binding_scope **scope,
147 struct group *group);
148 static isc_result_t reply_process_send_prefix(struct reply_state *reply,
149 struct iaddrcidrnet *pref);
150 static struct iasubopt *prefix_compare(struct reply_state *reply,
151 struct iasubopt *alpha,
152 struct iasubopt *beta);
153 static int find_hosts_by_duid_chaddr(struct host_decl **host,
154 const struct data_string *client_id);
156 * This function returns the time since DUID time start for the
157 * given time_t value.
159 static u_int32_t
160 duid_time(time_t when) {
162 * This time is modulo 2^32.
164 while ((when - DUID_TIME_EPOCH) > 4294967295u) {
165 /* use 2^31 to avoid spurious compiler warnings */
166 when -= 2147483648u;
167 when -= 2147483648u;
170 return when - DUID_TIME_EPOCH;
175 * Server DUID.
177 * This must remain the same for the lifetime of this server, because
178 * clients return the server DUID that we sent them in Request packets.
180 * We pick the server DUID like this:
182 * 1. Check dhcpd.conf - any value the administrator has configured
183 * overrides any possible values.
184 * 2. Check the leases.txt - we want to use the previous value if
185 * possible.
186 * 3. Check if dhcpd.conf specifies a type of server DUID to use,
187 * and generate that type.
188 * 4. Generate a type 1 (time + hardware address) DUID.
190 static struct data_string server_duid;
193 * Check if the server_duid has been set.
195 isc_boolean_t
196 server_duid_isset(void) {
197 return (server_duid.data != NULL);
201 * Return the server_duid.
203 void
204 copy_server_duid(struct data_string *ds, const char *file, int line) {
205 data_string_copy(ds, &server_duid, file, line);
209 * Set the server DUID to a specified value. This is used when
210 * the server DUID is stored in persistent memory (basically the
211 * leases.txt file).
213 void
214 set_server_duid(struct data_string *new_duid) {
215 /* INSIST(new_duid != NULL); */
216 /* INSIST(new_duid->data != NULL); */
218 if (server_duid_isset()) {
219 data_string_forget(&server_duid, MDL);
221 data_string_copy(&server_duid, new_duid, MDL);
226 * Set the server DUID based on the D6O_SERVERID option. This handles
227 * the case where the administrator explicitly put it in the dhcpd.conf
228 * file.
230 isc_result_t
231 set_server_duid_from_option(void) {
232 struct option_state *opt_state;
233 struct option_cache *oc;
234 struct data_string option_duid;
235 isc_result_t ret_val;
237 opt_state = NULL;
238 if (!option_state_allocate(&opt_state, MDL)) {
239 log_fatal("No memory for server DUID.");
242 execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
243 opt_state, &global_scope, root_group,
244 NULL, NULL);
246 oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
247 if (oc == NULL) {
248 ret_val = ISC_R_NOTFOUND;
249 } else {
250 memset(&option_duid, 0, sizeof(option_duid));
251 if (!evaluate_option_cache(&option_duid, NULL, NULL, NULL,
252 opt_state, NULL, &global_scope,
253 oc, MDL)) {
254 ret_val = ISC_R_UNEXPECTED;
255 } else {
256 set_server_duid(&option_duid);
257 data_string_forget(&option_duid, MDL);
258 ret_val = ISC_R_SUCCESS;
262 option_state_dereference(&opt_state, MDL);
264 return ret_val;
268 * DUID layout, as defined in RFC 3315, section 9.
270 * We support type 1 (hardware address plus time) and type 3 (hardware
271 * address).
273 * We can support type 2 for specific vendors in the future, if they
274 * publish the specification. And of course there may be additional
275 * types later.
277 static int server_duid_type = DUID_LLT;
280 * Set the DUID type.
282 void
283 set_server_duid_type(int type) {
284 server_duid_type = type;
288 * Generate a new server DUID. This is done if there was no DUID in
289 * the leases.txt or in the dhcpd.conf file.
291 isc_result_t
292 generate_new_server_duid(void) {
293 struct interface_info *p;
294 u_int32_t time_val;
295 struct data_string generated_duid;
298 * Verify we have a type that we support.
300 if ((server_duid_type != DUID_LL) && (server_duid_type != DUID_LLT)) {
301 log_error("Invalid DUID type %d specified, "
302 "only LL and LLT types supported", server_duid_type);
303 return DHCP_R_INVALIDARG;
307 * Find an interface with a hardware address.
308 * Any will do. :)
310 for (p = interfaces; p != NULL; p = p->next) {
311 if (p->hw_address.hlen > 0) {
312 break;
315 if (p == NULL) {
316 return ISC_R_UNEXPECTED;
320 * Build our DUID.
322 memset(&generated_duid, 0, sizeof(generated_duid));
323 if (server_duid_type == DUID_LLT) {
324 time_val = duid_time(time(NULL));
325 generated_duid.len = 8 + p->hw_address.hlen - 1;
326 if (!buffer_allocate(&generated_duid.buffer,
327 generated_duid.len, MDL)) {
328 log_fatal("No memory for server DUID.");
330 generated_duid.data = generated_duid.buffer->data;
331 putUShort(generated_duid.buffer->data, DUID_LLT);
332 putUShort(generated_duid.buffer->data + 2,
333 p->hw_address.hbuf[0]);
334 putULong(generated_duid.buffer->data + 4, time_val);
335 memcpy(generated_duid.buffer->data + 8,
336 p->hw_address.hbuf+1, p->hw_address.hlen-1);
337 } else if (server_duid_type == DUID_LL) {
338 generated_duid.len = 4 + p->hw_address.hlen - 1;
339 if (!buffer_allocate(&generated_duid.buffer,
340 generated_duid.len, MDL)) {
341 log_fatal("No memory for server DUID.");
343 generated_duid.data = generated_duid.buffer->data;
344 putUShort(generated_duid.buffer->data, DUID_LL);
345 putUShort(generated_duid.buffer->data + 2,
346 p->hw_address.hbuf[0]);
347 memcpy(generated_duid.buffer->data + 4,
348 p->hw_address.hbuf+1, p->hw_address.hlen-1);
349 } else {
350 log_fatal("Unsupported server DUID type %d.", server_duid_type);
353 set_server_duid(&generated_duid);
354 data_string_forget(&generated_duid, MDL);
356 return ISC_R_SUCCESS;
360 * Get the client identifier from the packet.
362 isc_result_t
363 get_client_id(struct packet *packet, struct data_string *client_id) {
364 struct option_cache *oc;
367 * Verify our client_id structure is empty.
369 if ((client_id->data != NULL) || (client_id->len != 0)) {
370 return DHCP_R_INVALIDARG;
373 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
374 if (oc == NULL) {
375 return ISC_R_NOTFOUND;
378 if (!evaluate_option_cache(client_id, packet, NULL, NULL,
379 packet->options, NULL,
380 &global_scope, oc, MDL)) {
381 return ISC_R_FAILURE;
384 return ISC_R_SUCCESS;
388 * Message validation, defined in RFC 3315, sections 15.2, 15.5, 15.7:
390 * Servers MUST discard any Solicit messages that do not include a
391 * Client Identifier option or that do include a Server Identifier
392 * option.
394 static int
395 valid_client_msg(struct packet *packet, struct data_string *client_id) {
396 int ret_val;
397 struct option_cache *oc;
398 struct data_string data;
400 ret_val = 0;
401 memset(client_id, 0, sizeof(*client_id));
402 memset(&data, 0, sizeof(data));
404 switch (get_client_id(packet, client_id)) {
405 case ISC_R_SUCCESS:
406 break;
407 case ISC_R_NOTFOUND:
408 log_debug("Discarding %s from %s; "
409 "client identifier missing",
410 dhcpv6_type_names[packet->dhcpv6_msg_type],
411 piaddr(packet->client_addr));
412 goto exit;
413 default:
414 log_error("Error processing %s from %s; "
415 "unable to evaluate Client Identifier",
416 dhcpv6_type_names[packet->dhcpv6_msg_type],
417 piaddr(packet->client_addr));
418 goto exit;
422 * Required by RFC 3315, section 15.
424 if (packet->unicast) {
425 log_debug("Discarding %s from %s; packet sent unicast "
426 "(CLIENTID %s)",
427 dhcpv6_type_names[packet->dhcpv6_msg_type],
428 piaddr(packet->client_addr),
429 print_hex_1(client_id->len, client_id->data, 60));
430 goto exit;
434 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
435 if (oc != NULL) {
436 if (evaluate_option_cache(&data, packet, NULL, NULL,
437 packet->options, NULL,
438 &global_scope, oc, MDL)) {
439 log_debug("Discarding %s from %s; "
440 "server identifier found "
441 "(CLIENTID %s, SERVERID %s)",
442 dhcpv6_type_names[packet->dhcpv6_msg_type],
443 piaddr(packet->client_addr),
444 print_hex_1(client_id->len,
445 client_id->data, 60),
446 print_hex_2(data.len,
447 data.data, 60));
448 } else {
449 log_debug("Discarding %s from %s; "
450 "server identifier found "
451 "(CLIENTID %s)",
452 dhcpv6_type_names[packet->dhcpv6_msg_type],
453 print_hex_1(client_id->len,
454 client_id->data, 60),
455 piaddr(packet->client_addr));
457 goto exit;
460 /* looks good */
461 ret_val = 1;
463 exit:
464 if (data.len > 0) {
465 data_string_forget(&data, MDL);
467 if (!ret_val) {
468 if (client_id->len > 0) {
469 data_string_forget(client_id, MDL);
472 return ret_val;
476 * Response validation, defined in RFC 3315, sections 15.4, 15.6, 15.8,
477 * 15.9 (slightly different wording, but same meaning):
479 * Servers MUST discard any received Request message that meet any of
480 * the following conditions:
482 * - the message does not include a Server Identifier option.
483 * - the contents of the Server Identifier option do not match the
484 * server's DUID.
485 * - the message does not include a Client Identifier option.
487 static int
488 valid_client_resp(struct packet *packet,
489 struct data_string *client_id,
490 struct data_string *server_id)
492 int ret_val;
493 struct option_cache *oc;
495 /* INSIST((duid.data != NULL) && (duid.len > 0)); */
497 ret_val = 0;
498 memset(client_id, 0, sizeof(*client_id));
499 memset(server_id, 0, sizeof(*server_id));
501 switch (get_client_id(packet, client_id)) {
502 case ISC_R_SUCCESS:
503 break;
504 case ISC_R_NOTFOUND:
505 log_debug("Discarding %s from %s; "
506 "client identifier missing",
507 dhcpv6_type_names[packet->dhcpv6_msg_type],
508 piaddr(packet->client_addr));
509 goto exit;
510 default:
511 log_error("Error processing %s from %s; "
512 "unable to evaluate Client Identifier",
513 dhcpv6_type_names[packet->dhcpv6_msg_type],
514 piaddr(packet->client_addr));
515 goto exit;
518 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
519 if (oc == NULL) {
520 log_debug("Discarding %s from %s: "
521 "server identifier missing (CLIENTID %s)",
522 dhcpv6_type_names[packet->dhcpv6_msg_type],
523 piaddr(packet->client_addr),
524 print_hex_1(client_id->len, client_id->data, 60));
525 goto exit;
527 if (!evaluate_option_cache(server_id, packet, NULL, NULL,
528 packet->options, NULL,
529 &global_scope, oc, MDL)) {
530 log_error("Error processing %s from %s; "
531 "unable to evaluate Server Identifier (CLIENTID %s)",
532 dhcpv6_type_names[packet->dhcpv6_msg_type],
533 piaddr(packet->client_addr),
534 print_hex_1(client_id->len, client_id->data, 60));
535 goto exit;
537 if ((server_duid.len != server_id->len) ||
538 (memcmp(server_duid.data, server_id->data, server_duid.len) != 0)) {
539 log_debug("Discarding %s from %s; "
540 "not our server identifier "
541 "(CLIENTID %s, SERVERID %s, server DUID %s)",
542 dhcpv6_type_names[packet->dhcpv6_msg_type],
543 piaddr(packet->client_addr),
544 print_hex_1(client_id->len, client_id->data, 60),
545 print_hex_2(server_id->len, server_id->data, 60),
546 print_hex_3(server_duid.len, server_duid.data, 60));
547 goto exit;
550 /* looks good */
551 ret_val = 1;
553 exit:
554 if (!ret_val) {
555 if (server_id->len > 0) {
556 data_string_forget(server_id, MDL);
558 if (client_id->len > 0) {
559 data_string_forget(client_id, MDL);
562 return ret_val;
566 * Information request validation, defined in RFC 3315, section 15.12:
568 * Servers MUST discard any received Information-request message that
569 * meets any of the following conditions:
571 * - The message includes a Server Identifier option and the DUID in
572 * the option does not match the server's DUID.
574 * - The message includes an IA option.
576 static int
577 valid_client_info_req(struct packet *packet, struct data_string *server_id) {
578 int ret_val;
579 struct option_cache *oc;
580 struct data_string client_id;
581 char client_id_str[80]; /* print_hex_1() uses maximum 60 characters,
582 plus a few more for extra information */
584 ret_val = 0;
585 memset(server_id, 0, sizeof(*server_id));
586 memset(&client_id, 0, sizeof(client_id));
589 * Make a string that we can print out to give more
590 * information about the client if we need to.
592 * By RFC 3315, Section 18.1.5 clients SHOULD have a
593 * client-id on an Information-request packet, but it
594 * is not strictly necessary.
596 if (get_client_id(packet, &client_id) == ISC_R_SUCCESS) {
597 snprintf(client_id_str, sizeof(client_id_str), " (CLIENTID %s)",
598 print_hex_1(client_id.len, client_id.data, 60));
599 data_string_forget(&client_id, MDL);
600 } else {
601 client_id_str[0] = '\0';
605 * Required by RFC 3315, section 15.
607 if (packet->unicast) {
608 log_debug("Discarding %s from %s; packet sent unicast%s",
609 dhcpv6_type_names[packet->dhcpv6_msg_type],
610 piaddr(packet->client_addr), client_id_str);
611 goto exit;
614 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
615 if (oc != NULL) {
616 log_debug("Discarding %s from %s; "
617 "IA_NA option present%s",
618 dhcpv6_type_names[packet->dhcpv6_msg_type],
619 piaddr(packet->client_addr), client_id_str);
620 goto exit;
622 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
623 if (oc != NULL) {
624 log_debug("Discarding %s from %s; "
625 "IA_TA option present%s",
626 dhcpv6_type_names[packet->dhcpv6_msg_type],
627 piaddr(packet->client_addr), client_id_str);
628 goto exit;
630 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
631 if (oc != NULL) {
632 log_debug("Discarding %s from %s; "
633 "IA_PD option present%s",
634 dhcpv6_type_names[packet->dhcpv6_msg_type],
635 piaddr(packet->client_addr), client_id_str);
636 goto exit;
639 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
640 if (oc != NULL) {
641 if (!evaluate_option_cache(server_id, packet, NULL, NULL,
642 packet->options, NULL,
643 &global_scope, oc, MDL)) {
644 log_error("Error processing %s from %s; "
645 "unable to evaluate Server Identifier%s",
646 dhcpv6_type_names[packet->dhcpv6_msg_type],
647 piaddr(packet->client_addr), client_id_str);
648 goto exit;
650 if ((server_duid.len != server_id->len) ||
651 (memcmp(server_duid.data, server_id->data,
652 server_duid.len) != 0)) {
653 log_debug("Discarding %s from %s; "
654 "not our server identifier "
655 "(SERVERID %s, server DUID %s)%s",
656 dhcpv6_type_names[packet->dhcpv6_msg_type],
657 piaddr(packet->client_addr),
658 print_hex_1(server_id->len,
659 server_id->data, 60),
660 print_hex_2(server_duid.len,
661 server_duid.data, 60),
662 client_id_str);
663 goto exit;
667 /* looks good */
668 ret_val = 1;
670 exit:
671 if (!ret_val) {
672 if (server_id->len > 0) {
673 data_string_forget(server_id, MDL);
676 return ret_val;
680 * Options that we want to send, in addition to what was requested
681 * via the ORO.
683 static const int required_opts[] = {
684 D6O_CLIENTID,
685 D6O_SERVERID,
686 D6O_STATUS_CODE,
687 D6O_PREFERENCE,
690 static const int required_opts_NAA[] = {
691 D6O_CLIENTID,
692 D6O_SERVERID,
693 D6O_STATUS_CODE,
696 static const int required_opts_solicit[] = {
697 D6O_CLIENTID,
698 D6O_SERVERID,
699 D6O_IA_NA,
700 D6O_IA_TA,
701 D6O_IA_PD,
702 D6O_RAPID_COMMIT,
703 D6O_STATUS_CODE,
704 D6O_RECONF_ACCEPT,
705 D6O_PREFERENCE,
708 static const int required_opts_agent[] = {
709 D6O_INTERFACE_ID,
710 D6O_RELAY_MSG,
713 static const int required_opts_IA[] = {
714 D6O_IAADDR,
715 D6O_STATUS_CODE,
718 static const int required_opts_IA_PD[] = {
719 D6O_IAPREFIX,
720 D6O_STATUS_CODE,
723 static const int required_opts_STATUS_CODE[] = {
724 D6O_STATUS_CODE,
729 * Extracts from packet contents an IA_* option, storing the IA structure
730 * in its entirety in enc_opt_data, and storing any decoded DHCPv6 options
731 * in enc_opt_state for later lookup and evaluation. The 'offset' indicates
732 * where in the IA_* the DHCPv6 options commence.
734 static int
735 get_encapsulated_IA_state(struct option_state **enc_opt_state,
736 struct data_string *enc_opt_data,
737 struct packet *packet,
738 struct option_cache *oc,
739 int offset)
742 * Get the raw data for the encapsulated options.
744 memset(enc_opt_data, 0, sizeof(*enc_opt_data));
745 if (!evaluate_option_cache(enc_opt_data, packet,
746 NULL, NULL, packet->options, NULL,
747 &global_scope, oc, MDL)) {
748 log_error("get_encapsulated_IA_state: "
749 "error evaluating raw option.");
750 return 0;
752 if (enc_opt_data->len < offset) {
753 log_error("get_encapsulated_IA_state: raw option too small.");
754 data_string_forget(enc_opt_data, MDL);
755 return 0;
759 * Now create the option state structure, and pass it to the
760 * function that parses options.
762 *enc_opt_state = NULL;
763 if (!option_state_allocate(enc_opt_state, MDL)) {
764 log_error("get_encapsulated_IA_state: no memory for options.");
765 data_string_forget(enc_opt_data, MDL);
766 return 0;
768 if (!parse_option_buffer(*enc_opt_state,
769 enc_opt_data->data + offset,
770 enc_opt_data->len - offset,
771 &dhcpv6_universe)) {
772 log_error("get_encapsulated_IA_state: error parsing options.");
773 option_state_dereference(enc_opt_state, MDL);
774 data_string_forget(enc_opt_data, MDL);
775 return 0;
778 return 1;
781 static int
782 set_status_code(u_int16_t status_code, const char *status_message,
783 struct option_state *opt_state)
785 struct data_string d;
786 int ret_val;
788 memset(&d, 0, sizeof(d));
789 d.len = sizeof(status_code) + strlen(status_message);
790 if (!buffer_allocate(&d.buffer, d.len, MDL)) {
791 log_fatal("set_status_code: no memory for status code.");
793 d.data = d.buffer->data;
794 putUShort(d.buffer->data, status_code);
795 memcpy(d.buffer->data + sizeof(status_code),
796 status_message, d.len - sizeof(status_code));
797 if (!save_option_buffer(&dhcpv6_universe, opt_state,
798 d.buffer, (unsigned char *)d.data, d.len,
799 D6O_STATUS_CODE, 0)) {
800 log_error("set_status_code: error saving status code.");
801 ret_val = 0;
802 } else {
803 ret_val = 1;
805 data_string_forget(&d, MDL);
806 return ret_val;
810 * We have a set of operations we do to set up the reply packet, which
811 * is the same for many message types.
813 static int
814 start_reply(struct packet *packet,
815 const struct data_string *client_id,
816 const struct data_string *server_id,
817 struct option_state **opt_state,
818 struct dhcpv6_packet *reply)
820 struct option_cache *oc;
821 const unsigned char *server_id_data;
822 int server_id_len;
825 * Build our option state for reply.
827 *opt_state = NULL;
828 if (!option_state_allocate(opt_state, MDL)) {
829 log_error("start_reply: no memory for option_state.");
830 return 0;
832 execute_statements_in_scope(NULL, packet, NULL, NULL,
833 packet->options, *opt_state,
834 &global_scope, root_group, NULL, NULL);
837 * A small bit of special handling for Solicit messages.
839 * We could move the logic into a flag, but for now just check
840 * explicitly.
842 if (packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
843 reply->msg_type = DHCPV6_ADVERTISE;
846 * If:
847 * - this message type supports rapid commit (Solicit), and
848 * - the server is configured to supply a rapid commit, and
849 * - the client requests a rapid commit,
850 * Then we add a rapid commit option, and send Reply (instead
851 * of an Advertise).
853 oc = lookup_option(&dhcpv6_universe,
854 *opt_state, D6O_RAPID_COMMIT);
855 if (oc != NULL) {
856 oc = lookup_option(&dhcpv6_universe,
857 packet->options, D6O_RAPID_COMMIT);
858 if (oc != NULL) {
859 /* Rapid-commit in action. */
860 reply->msg_type = DHCPV6_REPLY;
861 } else {
862 /* Don't want a rapid-commit in advertise. */
863 delete_option(&dhcpv6_universe,
864 *opt_state, D6O_RAPID_COMMIT);
867 } else {
868 reply->msg_type = DHCPV6_REPLY;
869 /* Delete the rapid-commit from the sent options. */
870 oc = lookup_option(&dhcpv6_universe,
871 *opt_state, D6O_RAPID_COMMIT);
872 if (oc != NULL) {
873 delete_option(&dhcpv6_universe,
874 *opt_state, D6O_RAPID_COMMIT);
879 * Use the client's transaction identifier for the reply.
881 memcpy(reply->transaction_id, packet->dhcpv6_transaction_id,
882 sizeof(reply->transaction_id));
885 * RFC 3315, section 18.2 says we need server identifier and
886 * client identifier.
888 * If the server ID is defined via the configuration file, then
889 * it will already be present in the option state at this point,
890 * so we don't need to set it.
892 * If we have a server ID passed in from the caller,
893 * use that, otherwise use the global DUID.
895 oc = lookup_option(&dhcpv6_universe, *opt_state, D6O_SERVERID);
896 if (oc == NULL) {
897 if (server_id == NULL) {
898 server_id_data = server_duid.data;
899 server_id_len = server_duid.len;
900 } else {
901 server_id_data = server_id->data;
902 server_id_len = server_id->len;
904 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
905 NULL, (unsigned char *)server_id_data,
906 server_id_len, D6O_SERVERID, 0)) {
907 log_error("start_reply: "
908 "error saving server identifier.");
909 return 0;
913 if (client_id->buffer != NULL) {
914 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
915 client_id->buffer,
916 (unsigned char *)client_id->data,
917 client_id->len,
918 D6O_CLIENTID, 0)) {
919 log_error("start_reply: error saving "
920 "client identifier.");
921 return 0;
926 * If the client accepts reconfiguration, let it know that we
927 * will send them.
929 * Note: we don't actually do this yet, but DOCSIS requires we
930 * claim to.
932 oc = lookup_option(&dhcpv6_universe, packet->options,
933 D6O_RECONF_ACCEPT);
934 if (oc != NULL) {
935 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
936 NULL, (unsigned char *)"", 0,
937 D6O_RECONF_ACCEPT, 0)) {
938 log_error("start_reply: "
939 "error saving RECONF_ACCEPT option.");
940 option_state_dereference(opt_state, MDL);
941 return 0;
945 return 1;
949 * Try to get the IPv6 address the client asked for from the
950 * pool.
952 * addr is the result (should be a pointer to NULL on entry)
953 * pool is the pool to search in
954 * requested_addr is the address the client wants
956 static isc_result_t
957 try_client_v6_address(struct iasubopt **addr,
958 struct ipv6_pool *pool,
959 const struct data_string *requested_addr)
961 struct in6_addr tmp_addr;
962 isc_result_t result;
964 if (requested_addr->len < sizeof(tmp_addr)) {
965 return DHCP_R_INVALIDARG;
967 memcpy(&tmp_addr, requested_addr->data, sizeof(tmp_addr));
968 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
969 return ISC_R_FAILURE;
973 * The address is not covered by this (or possibly any) dynamic
974 * range.
976 if (!ipv6_in_pool(&tmp_addr, pool)) {
977 return ISC_R_ADDRNOTAVAIL;
980 if (lease6_exists(pool, &tmp_addr)) {
981 return ISC_R_ADDRINUSE;
984 result = iasubopt_allocate(addr, MDL);
985 if (result != ISC_R_SUCCESS) {
986 return result;
988 (*addr)->addr = tmp_addr;
989 (*addr)->plen = 0;
991 /* Default is soft binding for 2 minutes. */
992 result = add_lease6(pool, *addr, cur_time + 120);
993 if (result != ISC_R_SUCCESS) {
994 iasubopt_dereference(addr, MDL);
996 return result;
1002 * \brief Get an IPv6 address for the client.
1004 * Attempt to find a usable address for the client. We walk through
1005 * the ponds checking for permit and deny then through the pools
1006 * seeing if they have an available address.
1008 * \param reply = the state structure for the current work on this request
1009 * if we create a lease we return it using reply->lease
1011 * \return
1012 * ISC_R_SUCCESS = we were able to find an address and are returning a
1013 * pointer to the lease
1014 * ISC_R_NORESOURCES = there don't appear to be any free addresses. This
1015 * is probabalistic. We don't exhaustively try the
1016 * address range, instead we hash the duid and if
1017 * the address derived from the hash is in use we
1018 * hash the address. After a number of failures we
1019 * conclude the pool is basically full.
1021 static isc_result_t
1022 pick_v6_address(struct reply_state *reply)
1024 struct ipv6_pool *p = NULL;
1025 struct ipv6_pond *pond;
1026 int i;
1027 int start_pool;
1028 unsigned int attempts;
1029 char tmp_buf[INET6_ADDRSTRLEN];
1030 struct iasubopt **addr = &reply->lease;
1033 * Do a quick walk through of the ponds and pools
1034 * to see if we have any NA address pools
1036 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
1037 if (pond->ipv6_pools == NULL)
1038 continue;
1040 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
1041 if (p->pool_type == D6O_IA_NA)
1042 break;
1044 if (p != NULL)
1045 break;
1048 /* If we get here and p is NULL we have no useful pools */
1049 if (p == NULL) {
1050 log_debug("Unable to pick client address: "
1051 "no IPv6 pools on this shared network");
1052 return ISC_R_NORESOURCES;
1056 * We have at least one pool that could provide an address
1057 * Now we walk through the ponds and pools again and check
1058 * to see if the client is permitted and if an address is
1059 * available
1061 * Within a given pond we start looking at the last pool we
1062 * allocated from, unless it had a collision trying to allocate
1063 * an address. This will tend to move us into less-filled pools.
1066 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
1067 if (((pond->prohibit_list != NULL) &&
1068 (permitted(reply->packet, pond->prohibit_list))) ||
1069 ((pond->permit_list != NULL) &&
1070 (!permitted(reply->packet, pond->permit_list))))
1071 continue;
1073 start_pool = pond->last_ipv6_pool;
1074 i = start_pool;
1075 do {
1076 p = pond->ipv6_pools[i];
1077 if ((p->pool_type == D6O_IA_NA) &&
1078 (create_lease6(p, addr, &attempts,
1079 &reply->ia->iaid_duid,
1080 cur_time + 120) == ISC_R_SUCCESS)) {
1082 * Record the pool used (or next one if there
1083 * was a collision).
1085 if (attempts > 1) {
1086 i++;
1087 if (pond->ipv6_pools[i] == NULL) {
1088 i = 0;
1091 pond->last_ipv6_pool = i;
1093 log_debug("Picking pool address %s",
1094 inet_ntop(AF_INET6, &((*addr)->addr),
1095 tmp_buf, sizeof(tmp_buf)));
1096 return (ISC_R_SUCCESS);
1099 i++;
1100 if (pond->ipv6_pools[i] == NULL) {
1101 i = 0;
1103 } while (i != start_pool);
1107 * If we failed to pick an IPv6 address from any of the subnets.
1108 * Presumably that means we have no addresses for the client.
1110 log_debug("Unable to pick client address: no addresses available");
1111 return ISC_R_NORESOURCES;
1115 * Try to get the IPv6 prefix the client asked for from the
1116 * prefix pool.
1118 * pref is the result (should be a pointer to NULL on entry)
1119 * pool is the prefix pool to search in
1120 * requested_pref is the address the client wants
1122 static isc_result_t
1123 try_client_v6_prefix(struct iasubopt **pref,
1124 struct ipv6_pool *pool,
1125 const struct data_string *requested_pref)
1127 u_int8_t tmp_plen;
1128 struct in6_addr tmp_pref;
1129 struct iaddr ia;
1130 isc_result_t result;
1132 if (requested_pref->len < sizeof(tmp_plen) + sizeof(tmp_pref)) {
1133 return DHCP_R_INVALIDARG;
1135 tmp_plen = (int) requested_pref->data[0];
1136 if ((tmp_plen < 3) || (tmp_plen > 128) ||
1137 ((int)tmp_plen != pool->units)) {
1138 return ISC_R_FAILURE;
1140 memcpy(&tmp_pref, requested_pref->data + 1, sizeof(tmp_pref));
1141 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
1142 return ISC_R_FAILURE;
1144 ia.len = 16;
1145 memcpy(&ia.iabuf, &tmp_pref, 16);
1146 if (!is_cidr_mask_valid(&ia, (int) tmp_plen)) {
1147 return ISC_R_FAILURE;
1150 if (!ipv6_in_pool(&tmp_pref, pool)) {
1151 return ISC_R_ADDRNOTAVAIL;
1154 if (prefix6_exists(pool, &tmp_pref, tmp_plen)) {
1155 return ISC_R_ADDRINUSE;
1158 result = iasubopt_allocate(pref, MDL);
1159 if (result != ISC_R_SUCCESS) {
1160 return result;
1162 (*pref)->addr = tmp_pref;
1163 (*pref)->plen = tmp_plen;
1165 /* Default is soft binding for 2 minutes. */
1166 result = add_lease6(pool, *pref, cur_time + 120);
1167 if (result != ISC_R_SUCCESS) {
1168 iasubopt_dereference(pref, MDL);
1170 return result;
1175 * \brief Get an IPv6 prefix for the client.
1177 * Attempt to find a usable prefix for the client. We walk through
1178 * the ponds checking for permit and deny then through the pools
1179 * seeing if they have an available prefix.
1181 * \param reply = the state structure for the current work on this request
1182 * if we create a lease we return it using reply->lease
1184 * \return
1185 * ISC_R_SUCCESS = we were able to find an prefix and are returning a
1186 * pointer to the lease
1187 * ISC_R_NORESOURCES = there don't appear to be any free addresses. This
1188 * is probabalistic. We don't exhaustively try the
1189 * address range, instead we hash the duid and if
1190 * the address derived from the hash is in use we
1191 * hash the address. After a number of failures we
1192 * conclude the pool is basically full.
1195 static isc_result_t
1196 pick_v6_prefix(struct reply_state *reply)
1198 struct ipv6_pool *p = NULL;
1199 struct ipv6_pond *pond;
1200 int i;
1201 unsigned int attempts;
1202 char tmp_buf[INET6_ADDRSTRLEN];
1203 struct iasubopt **pref = &reply->lease;
1206 * Do a quick walk through of the ponds and pools
1207 * to see if we have any prefix pools
1209 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
1210 if (pond->ipv6_pools == NULL)
1211 continue;
1213 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
1214 if (p->pool_type == D6O_IA_PD)
1215 break;
1217 if (p != NULL)
1218 break;
1221 /* If we get here and p is NULL we have no useful pools */
1222 if (p == NULL) {
1223 log_debug("Unable to pick client prefix: "
1224 "no IPv6 pools on this shared network");
1225 return ISC_R_NORESOURCES;
1229 * We have at least one pool that could provide a prefix
1230 * Now we walk through the ponds and pools again and check
1231 * to see if the client is permitted and if an prefix is
1232 * available
1236 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
1237 if (((pond->prohibit_list != NULL) &&
1238 (permitted(reply->packet, pond->prohibit_list))) ||
1239 ((pond->permit_list != NULL) &&
1240 (!permitted(reply->packet, pond->permit_list))))
1241 continue;
1243 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
1244 if (p->pool_type != D6O_IA_PD) {
1245 continue;
1249 * Try only pools with the requested prefix length if any.
1251 if ((reply->preflen >= 0) && (p->units != reply->preflen)) {
1252 continue;
1255 if (create_prefix6(p, pref, &attempts, &reply->ia->iaid_duid,
1256 cur_time + 120) == ISC_R_SUCCESS) {
1257 log_debug("Picking pool prefix %s/%u",
1258 inet_ntop(AF_INET6, &((*pref)->addr),
1259 tmp_buf, sizeof(tmp_buf)),
1260 (unsigned) (*pref)->plen);
1262 return (ISC_R_SUCCESS);
1268 * If we failed to pick an IPv6 prefix
1269 * Presumably that means we have no prefixes for the client.
1271 log_debug("Unable to pick client prefix: no prefixes available");
1272 return ISC_R_NORESOURCES;
1276 *! \file server/dhcpv6.c
1278 * \brief construct a reply containing information about a client's lease
1280 * lease_to_client() is called from several messages to construct a
1281 * reply that contains all that we know about the client's correct lease
1282 * (or projected lease).
1284 * Solicit - "Soft" binding, ignore unknown addresses or bindings, just
1285 * send what we "may" give them on a request.
1287 * Request - "Hard" binding, but ignore supplied addresses (just provide what
1288 * the client should really use).
1290 * Renew - "Hard" binding, but client-supplied addresses are 'real'. Error
1291 * Rebind out any "wrong" addresses the client sends. This means we send
1292 * an empty IA_NA with a status code of NoBinding or NotOnLink or
1293 * possibly send the address with zeroed lifetimes.
1295 * Information-Request - No binding.
1297 * The basic structure is to traverse the client-supplied data first, and
1298 * validate and echo back any contents that can be. If the client-supplied
1299 * data does not error out (on renew/rebind as above), but we did not send
1300 * any addresses, attempt to allocate one.
1302 * At the end of the this function we call commit_leases_timed() to
1303 * fsync and rotate the file as necessary. commit_leases_timed() will
1304 * check that we have written at least one lease to the file and that
1305 * some time has passed before doing any fsync or file rewrite so we
1306 * don't bother tracking if we did a write_ia during this function.
1308 /* TODO: look at client hints for lease times */
1310 static void
1311 lease_to_client(struct data_string *reply_ret,
1312 struct packet *packet,
1313 const struct data_string *client_id,
1314 const struct data_string *server_id)
1316 static struct reply_state reply;
1317 struct option_cache *oc;
1318 struct data_string packet_oro;
1319 #if defined (RFC3315_PRE_ERRATA_2010_08)
1320 isc_boolean_t no_resources_avail = ISC_FALSE;
1321 #endif
1322 int i;
1324 memset(&packet_oro, 0, sizeof(packet_oro));
1326 /* Locate the client. */
1327 if (shared_network_from_packet6(&reply.shared,
1328 packet) != ISC_R_SUCCESS)
1329 goto exit;
1332 * Initialize the reply.
1334 packet_reference(&reply.packet, packet, MDL);
1335 data_string_copy(&reply.client_id, client_id, MDL);
1337 if (!start_reply(packet, client_id, server_id, &reply.opt_state,
1338 &reply.buf.reply))
1339 goto exit;
1341 /* Set the write cursor to just past the reply header. */
1342 reply.cursor = REPLY_OPTIONS_INDEX;
1345 * Get the ORO from the packet, if any.
1347 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ORO);
1348 if (oc != NULL) {
1349 if (!evaluate_option_cache(&packet_oro, packet,
1350 NULL, NULL,
1351 packet->options, NULL,
1352 &global_scope, oc, MDL)) {
1353 log_error("lease_to_client: error evaluating ORO.");
1354 goto exit;
1359 * Find a host record that matches from the packet, if any, and is
1360 * valid for the shared network the client is on.
1362 if (find_hosts_by_uid(&reply.host, client_id->data, client_id->len,
1363 MDL)) {
1364 packet->known = 1;
1365 seek_shared_host(&reply.host, reply.shared);
1368 if ((reply.host == NULL) &&
1369 find_hosts_by_option(&reply.host, packet, packet->options, MDL)) {
1370 packet->known = 1;
1371 seek_shared_host(&reply.host, reply.shared);
1375 * Check for 'hardware' matches last, as some of the synthesis methods
1376 * are not considered to be as reliable.
1378 if ((reply.host == NULL) &&
1379 find_hosts_by_duid_chaddr(&reply.host, client_id)) {
1380 packet->known = 1;
1381 seek_shared_host(&reply.host, reply.shared);
1384 /* Process the client supplied IA's onto the reply buffer. */
1385 reply.ia_count = 0;
1386 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
1388 for (; oc != NULL ; oc = oc->next) {
1389 isc_result_t status;
1391 /* Start counting resources (addresses) offered. */
1392 reply.client_resources = 0;
1393 reply.resources_included = ISC_FALSE;
1395 status = reply_process_ia_na(&reply, oc);
1398 * We continue to try other IA's whether we can address
1399 * this one or not. Any other result is an immediate fail.
1401 if ((status != ISC_R_SUCCESS) &&
1402 (status != ISC_R_NORESOURCES))
1403 goto exit;
1405 #if defined (RFC3315_PRE_ERRATA_2010_08)
1407 * If any address cannot be given to any IA, then set the
1408 * NoAddrsAvail status code.
1410 if (reply.client_resources == 0)
1411 no_resources_avail = ISC_TRUE;
1412 #endif
1414 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
1415 for (; oc != NULL ; oc = oc->next) {
1416 isc_result_t status;
1418 /* Start counting resources (addresses) offered. */
1419 reply.client_resources = 0;
1420 reply.resources_included = ISC_FALSE;
1422 status = reply_process_ia_ta(&reply, oc);
1425 * We continue to try other IA's whether we can address
1426 * this one or not. Any other result is an immediate fail.
1428 if ((status != ISC_R_SUCCESS) &&
1429 (status != ISC_R_NORESOURCES))
1430 goto exit;
1432 #if defined (RFC3315_PRE_ERRATA_2010_08)
1434 * If any address cannot be given to any IA, then set the
1435 * NoAddrsAvail status code.
1437 if (reply.client_resources == 0)
1438 no_resources_avail = ISC_TRUE;
1439 #endif
1442 /* Same for IA_PD's. */
1443 reply.pd_count = 0;
1444 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
1445 for (; oc != NULL ; oc = oc->next) {
1446 isc_result_t status;
1448 /* Start counting resources (prefixes) offered. */
1449 reply.client_resources = 0;
1450 reply.resources_included = ISC_FALSE;
1452 status = reply_process_ia_pd(&reply, oc);
1455 * We continue to try other IA_PD's whether we can address
1456 * this one or not. Any other result is an immediate fail.
1458 if ((status != ISC_R_SUCCESS) &&
1459 (status != ISC_R_NORESOURCES))
1460 goto exit;
1464 * Make no reply if we gave no resources and is not
1465 * for Information-Request.
1467 if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
1468 if (reply.packet->dhcpv6_msg_type !=
1469 DHCPV6_INFORMATION_REQUEST)
1470 goto exit;
1473 * Because we only execute statements on a per-IA basis,
1474 * we need to execute statements in any non-IA reply to
1475 * source configuration.
1477 execute_statements_in_scope(NULL, reply.packet, NULL, NULL,
1478 reply.packet->options,
1479 reply.opt_state, &global_scope,
1480 reply.shared->group, root_group,
1481 NULL);
1483 /* Execute statements from class scopes. */
1484 for (i = reply.packet->class_count; i > 0; i--) {
1485 execute_statements_in_scope(NULL, reply.packet,
1486 NULL, NULL,
1487 reply.packet->options,
1488 reply.opt_state,
1489 &global_scope,
1490 reply.packet->classes[i - 1]->group,
1491 reply.shared->group, NULL);
1494 /* Bring in any configuration from a host record. */
1495 if (reply.host != NULL)
1496 execute_statements_in_scope(NULL, reply.packet,
1497 NULL, NULL,
1498 reply.packet->options,
1499 reply.opt_state,
1500 &global_scope,
1501 reply.host->group,
1502 reply.shared->group, NULL);
1506 * RFC3315 section 17.2.2 (Solicit):
1508 * If the server will not assign any addresses to any IAs in a
1509 * subsequent Request from the client, the server MUST send an
1510 * Advertise message to the client that includes only a Status
1511 * Code option with code NoAddrsAvail and a status message for
1512 * the user, a Server Identifier option with the server's DUID,
1513 * and a Client Identifier option with the client's DUID.
1515 * Section 18.2.1 (Request):
1517 * If the server cannot assign any addresses to an IA in the
1518 * message from the client, the server MUST include the IA in
1519 * the Reply message with no addresses in the IA and a Status
1520 * Code option in the IA containing status code NoAddrsAvail.
1522 * Section 18.1.8 (Client Behavior):
1524 * Leave unchanged any information about addresses the client has
1525 * recorded in the IA but that were not included in the IA from
1526 * the server.
1527 * Sends a Renew/Rebind if the IA is not in the Reply message.
1529 #if defined (RFC3315_PRE_ERRATA_2010_08)
1530 if (no_resources_avail && (reply.ia_count != 0) &&
1531 (reply.packet->dhcpv6_msg_type == DHCPV6_SOLICIT))
1533 /* Set the NoAddrsAvail status code. */
1534 if (!set_status_code(STATUS_NoAddrsAvail,
1535 "No addresses available for this "
1536 "interface.", reply.opt_state)) {
1537 log_error("lease_to_client: Unable to set "
1538 "NoAddrsAvail status code.");
1539 goto exit;
1542 /* Rewind the cursor to the start. */
1543 reply.cursor = REPLY_OPTIONS_INDEX;
1546 * Produce an advertise that includes only:
1548 * Status code.
1549 * Server DUID.
1550 * Client DUID.
1552 reply.buf.reply.msg_type = DHCPV6_ADVERTISE;
1553 reply.cursor += store_options6((char *)reply.buf.data +
1554 reply.cursor,
1555 sizeof(reply.buf) -
1556 reply.cursor,
1557 reply.opt_state, reply.packet,
1558 required_opts_NAA,
1559 NULL);
1560 } else {
1562 * Having stored the client's IA's, store any options that
1563 * will fit in the remaining space.
1565 reply.cursor += store_options6((char *)reply.buf.data +
1566 reply.cursor,
1567 sizeof(reply.buf) -
1568 reply.cursor,
1569 reply.opt_state, reply.packet,
1570 required_opts_solicit,
1571 &packet_oro);
1573 #else /* defined (RFC3315_PRE_ERRATA_2010_08) */
1575 * Having stored the client's IA's, store any options that
1576 * will fit in the remaining space.
1578 reply.cursor += store_options6((char *)reply.buf.data + reply.cursor,
1579 sizeof(reply.buf) - reply.cursor,
1580 reply.opt_state, reply.packet,
1581 required_opts_solicit,
1582 &packet_oro);
1583 #endif /* defined (RFC3315_PRE_ERRATA_2010_08) */
1585 /* Return our reply to the caller. */
1586 reply_ret->len = reply.cursor;
1587 reply_ret->buffer = NULL;
1588 if (!buffer_allocate(&reply_ret->buffer, reply.cursor, MDL)) {
1589 log_fatal("No memory to store Reply.");
1591 memcpy(reply_ret->buffer->data, reply.buf.data, reply.cursor);
1592 reply_ret->data = reply_ret->buffer->data;
1594 /* If appropriate commit and rotate the lease file */
1595 (void) commit_leases_timed();
1597 exit:
1598 /* Cleanup. */
1599 if (reply.shared != NULL)
1600 shared_network_dereference(&reply.shared, MDL);
1601 if (reply.host != NULL)
1602 host_dereference(&reply.host, MDL);
1603 if (reply.opt_state != NULL)
1604 option_state_dereference(&reply.opt_state, MDL);
1605 if (reply.packet != NULL)
1606 packet_dereference(&reply.packet, MDL);
1607 if (reply.client_id.data != NULL)
1608 data_string_forget(&reply.client_id, MDL);
1609 if (packet_oro.buffer != NULL)
1610 data_string_forget(&packet_oro, MDL);
1611 reply.renew = reply.rebind = reply.prefer = reply.valid = 0;
1612 reply.cursor = 0;
1615 /* Process a client-supplied IA_NA. This may append options to the tail of
1616 * the reply packet being built in the reply_state structure.
1618 static isc_result_t
1619 reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
1620 isc_result_t status = ISC_R_SUCCESS;
1621 u_int32_t iaid;
1622 unsigned ia_cursor;
1623 struct option_state *packet_ia;
1624 struct option_cache *oc;
1625 struct data_string ia_data, data;
1627 /* Initialize values that will get cleaned up on return. */
1628 packet_ia = NULL;
1629 memset(&ia_data, 0, sizeof(ia_data));
1630 memset(&data, 0, sizeof(data));
1632 * Note that find_client_address() may set reply->lease.
1635 /* Make sure there is at least room for the header. */
1636 if ((reply->cursor + IA_NA_OFFSET + 4) > sizeof(reply->buf)) {
1637 log_error("reply_process_ia_na: Reply too long for IA.");
1638 return ISC_R_NOSPACE;
1642 /* Fetch the IA_NA contents. */
1643 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
1644 ia, IA_NA_OFFSET)) {
1645 log_error("reply_process_ia_na: error evaluating ia");
1646 status = ISC_R_FAILURE;
1647 goto cleanup;
1650 /* Extract IA_NA header contents. */
1651 iaid = getULong(ia_data.data);
1652 reply->renew = getULong(ia_data.data + 4);
1653 reply->rebind = getULong(ia_data.data + 8);
1655 /* Create an IA_NA structure. */
1656 if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
1657 reply->client_id.len, MDL) != ISC_R_SUCCESS) {
1658 log_error("reply_process_ia_na: no memory for ia.");
1659 status = ISC_R_NOMEMORY;
1660 goto cleanup;
1662 reply->ia->ia_type = D6O_IA_NA;
1664 /* Cache pre-existing IA, if any. */
1665 ia_hash_lookup(&reply->old_ia, ia_na_active,
1666 (unsigned char *)reply->ia->iaid_duid.data,
1667 reply->ia->iaid_duid.len, MDL);
1670 * Create an option cache to carry the IA_NA option contents, and
1671 * execute any user-supplied values into it.
1673 if (!option_state_allocate(&reply->reply_ia, MDL)) {
1674 status = ISC_R_NOMEMORY;
1675 goto cleanup;
1678 /* Check & cache the fixed host record. */
1679 if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
1680 struct iaddr tmp_addr;
1682 if (!evaluate_option_cache(&reply->fixed, NULL, NULL, NULL,
1683 NULL, NULL, &global_scope,
1684 reply->host->fixed_addr, MDL)) {
1685 log_error("reply_process_ia_na: unable to evaluate "
1686 "fixed address.");
1687 status = ISC_R_FAILURE;
1688 goto cleanup;
1691 if (reply->fixed.len < 16) {
1692 log_error("reply_process_ia_na: invalid fixed address.");
1693 status = DHCP_R_INVALIDARG;
1694 goto cleanup;
1697 /* Find the static lease's subnet. */
1698 tmp_addr.len = 16;
1699 memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
1701 if (find_grouped_subnet(&reply->subnet, reply->shared,
1702 tmp_addr, MDL) == 0)
1703 log_fatal("Impossible condition at %s:%d.", MDL);
1705 reply->static_lease = ISC_TRUE;
1706 } else
1707 reply->static_lease = ISC_FALSE;
1710 * Save the cursor position at the start of the IA, so we can
1711 * set length and adjust t1/t2 values later. We write a temporary
1712 * header out now just in case we decide to adjust the packet
1713 * within sub-process functions.
1715 ia_cursor = reply->cursor;
1717 /* Initialize the IA_NA header. First the code. */
1718 putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_NA);
1719 reply->cursor += 2;
1721 /* Then option length. */
1722 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
1723 reply->cursor += 2;
1725 /* Then IA_NA header contents; IAID. */
1726 putULong(reply->buf.data + reply->cursor, iaid);
1727 reply->cursor += 4;
1729 /* We store the client's t1 for now, and may over-ride it later. */
1730 putULong(reply->buf.data + reply->cursor, reply->renew);
1731 reply->cursor += 4;
1733 /* We store the client's t2 for now, and may over-ride it later. */
1734 putULong(reply->buf.data + reply->cursor, reply->rebind);
1735 reply->cursor += 4;
1738 * For each address in this IA_NA, decide what to do about it.
1740 * Guidelines:
1742 * The client leaves unchanged any information about addresses
1743 * it has recorded but are not included ("cancel/break" below).
1744 * A not included IA ("cleanup" below) could give a Renew/Rebind.
1746 oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
1747 reply->valid = reply->prefer = 0xffffffff;
1748 reply->client_valid = reply->client_prefer = 0;
1749 for (; oc != NULL ; oc = oc->next) {
1750 status = reply_process_addr(reply, oc);
1753 * Canceled means we did not allocate addresses to the
1754 * client, but we're "done" with this IA - we set a status
1755 * code. So transmit this reply, e.g., move on to the next
1756 * IA.
1758 if (status == ISC_R_CANCELED)
1759 break;
1761 if ((status != ISC_R_SUCCESS) &&
1762 (status != ISC_R_ADDRINUSE) &&
1763 (status != ISC_R_ADDRNOTAVAIL))
1764 goto cleanup;
1767 reply->ia_count++;
1770 * If we fell through the above and never gave the client
1771 * an address, give it one now.
1773 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
1774 status = find_client_address(reply);
1776 if (status == ISC_R_NORESOURCES) {
1777 switch (reply->packet->dhcpv6_msg_type) {
1778 case DHCPV6_SOLICIT:
1780 * No address for any IA is handled
1781 * by the caller.
1783 /* FALL THROUGH */
1785 case DHCPV6_REQUEST:
1786 /* Section 18.2.1 (Request):
1788 * If the server cannot assign any addresses to
1789 * an IA in the message from the client, the
1790 * server MUST include the IA in the Reply
1791 * message with no addresses in the IA and a
1792 * Status Code option in the IA containing
1793 * status code NoAddrsAvail.
1795 option_state_dereference(&reply->reply_ia, MDL);
1796 if (!option_state_allocate(&reply->reply_ia,
1797 MDL))
1799 log_error("reply_process_ia_na: No "
1800 "memory for option state "
1801 "wipe.");
1802 status = ISC_R_NOMEMORY;
1803 goto cleanup;
1806 if (!set_status_code(STATUS_NoAddrsAvail,
1807 "No addresses available "
1808 "for this interface.",
1809 reply->reply_ia)) {
1810 log_error("reply_process_ia_na: Unable "
1811 "to set NoAddrsAvail status "
1812 "code.");
1813 status = ISC_R_FAILURE;
1814 goto cleanup;
1817 status = ISC_R_SUCCESS;
1818 break;
1820 default:
1822 * RFC 3315 does not tell us to emit a status
1823 * code in this condition, or anything else.
1825 * If we included non-allocated addresses
1826 * (zeroed lifetimes) in an IA, then the client
1827 * will deconfigure them.
1829 * So we want to include the IA even if we
1830 * can't give it a new address if it includes
1831 * zeroed lifetime addresses.
1833 * We don't want to include the IA if we
1834 * provide zero addresses including zeroed
1835 * lifetimes.
1837 if (reply->resources_included)
1838 status = ISC_R_SUCCESS;
1839 else
1840 goto cleanup;
1841 break;
1845 if (status != ISC_R_SUCCESS)
1846 goto cleanup;
1849 reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
1850 sizeof(reply->buf) - reply->cursor,
1851 reply->reply_ia, reply->packet,
1852 required_opts_IA, NULL);
1854 /* Reset the length of this IA to match what was just written. */
1855 putUShort(reply->buf.data + ia_cursor + 2,
1856 reply->cursor - (ia_cursor + 4));
1859 * T1/T2 time selection is kind of weird. We actually use DHCP
1860 * (v4) scoped options as handy existing places where these might
1861 * be configured by an administrator. A value of zero tells the
1862 * client it may choose its own renewal time.
1864 reply->renew = 0;
1865 oc = lookup_option(&dhcp_universe, reply->opt_state,
1866 DHO_DHCP_RENEWAL_TIME);
1867 if (oc != NULL) {
1868 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
1869 reply->packet->options,
1870 reply->opt_state, &global_scope,
1871 oc, MDL) ||
1872 (data.len != 4)) {
1873 log_error("Invalid renewal time.");
1874 } else {
1875 reply->renew = getULong(data.data);
1878 if (data.data != NULL)
1879 data_string_forget(&data, MDL);
1881 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
1883 /* Now T2. */
1884 reply->rebind = 0;
1885 oc = lookup_option(&dhcp_universe, reply->opt_state,
1886 DHO_DHCP_REBINDING_TIME);
1887 if (oc != NULL) {
1888 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
1889 reply->packet->options,
1890 reply->opt_state, &global_scope,
1891 oc, MDL) ||
1892 (data.len != 4)) {
1893 log_error("Invalid rebinding time.");
1894 } else {
1895 reply->rebind = getULong(data.data);
1898 if (data.data != NULL)
1899 data_string_forget(&data, MDL);
1901 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
1904 * yes, goto's aren't the best but we also want to avoid extra
1905 * indents
1907 if (status == ISC_R_CANCELED)
1908 goto cleanup;
1911 * Handle static leases, we always log stuff and if it's
1912 * a hard binding we run any commit statements that we have
1914 if (reply->static_lease) {
1915 char tmp_addr[INET6_ADDRSTRLEN];
1916 log_info("%s NA: address %s to client with duid %s iaid = %d "
1917 "static",
1918 dhcpv6_type_names[reply->buf.reply.msg_type],
1919 inet_ntop(AF_INET6, reply->fixed.data, tmp_addr,
1920 sizeof(tmp_addr)),
1921 print_hex_1(reply->client_id.len,
1922 reply->client_id.data, 60),
1923 iaid);
1925 if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
1926 (reply->on_star.on_commit != NULL)) {
1927 execute_statements(NULL, reply->packet, NULL, NULL,
1928 reply->packet->options,
1929 reply->opt_state, NULL,
1930 reply->on_star.on_commit, NULL);
1931 executable_statement_dereference
1932 (&reply->on_star.on_commit, MDL);
1934 goto cleanup;
1938 * If we have any addresses log what we are doing.
1940 if (reply->ia->num_iasubopt != 0) {
1941 struct iasubopt *tmp;
1942 int i;
1943 char tmp_addr[INET6_ADDRSTRLEN];
1945 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
1946 tmp = reply->ia->iasubopt[i];
1948 log_info("%s NA: address %s to client with duid %s "
1949 "iaid = %d valid for %d seconds",
1950 dhcpv6_type_names[reply->buf.reply.msg_type],
1951 inet_ntop(AF_INET6, &tmp->addr,
1952 tmp_addr, sizeof(tmp_addr)),
1953 print_hex_1(reply->client_id.len,
1954 reply->client_id.data, 60),
1955 iaid, tmp->valid);
1960 * If this is not a 'soft' binding, consume the new changes into
1961 * the database (if any have been attached to the ia_na).
1963 * Loop through the assigned dynamic addresses, referencing the
1964 * leases onto this IA_NA rather than any old ones, and updating
1965 * pool timers for each (if any).
1968 if ((reply->ia->num_iasubopt != 0) &&
1969 (reply->buf.reply.msg_type == DHCPV6_REPLY)) {
1970 struct iasubopt *tmp;
1971 struct data_string *ia_id;
1972 int i;
1974 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
1975 tmp = reply->ia->iasubopt[i];
1977 if (tmp->ia != NULL)
1978 ia_dereference(&tmp->ia, MDL);
1979 ia_reference(&tmp->ia, reply->ia, MDL);
1981 /* Commit 'hard' bindings. */
1982 renew_lease6(tmp->ipv6_pool, tmp);
1983 schedule_lease_timeout(tmp->ipv6_pool);
1985 /* If we have anything to do on commit do it now */
1986 if (tmp->on_star.on_commit != NULL) {
1987 execute_statements(NULL, reply->packet,
1988 NULL, NULL,
1989 reply->packet->options,
1990 reply->opt_state,
1991 &tmp->scope,
1992 tmp->on_star.on_commit,
1993 &tmp->on_star);
1994 executable_statement_dereference
1995 (&tmp->on_star.on_commit, MDL);
1998 #if defined (NSUPDATE)
2000 * Perform ddns updates.
2002 oc = lookup_option(&server_universe, reply->opt_state,
2003 SV_DDNS_UPDATES);
2004 if ((oc == NULL) ||
2005 evaluate_boolean_option_cache(NULL, reply->packet,
2006 NULL, NULL,
2007 reply->packet->options,
2008 reply->opt_state,
2009 &tmp->scope,
2010 oc, MDL)) {
2011 ddns_updates(reply->packet, NULL, NULL,
2012 tmp, NULL, reply->opt_state);
2014 #endif
2017 /* Remove any old ia from the hash. */
2018 if (reply->old_ia != NULL) {
2019 ia_id = &reply->old_ia->iaid_duid;
2020 ia_hash_delete(ia_na_active,
2021 (unsigned char *)ia_id->data,
2022 ia_id->len, MDL);
2023 ia_dereference(&reply->old_ia, MDL);
2026 /* Put new ia into the hash. */
2027 reply->ia->cltt = cur_time;
2028 ia_id = &reply->ia->iaid_duid;
2029 ia_hash_add(ia_na_active, (unsigned char *)ia_id->data,
2030 ia_id->len, reply->ia, MDL);
2032 write_ia(reply->ia);
2035 cleanup:
2036 if (packet_ia != NULL)
2037 option_state_dereference(&packet_ia, MDL);
2038 if (reply->reply_ia != NULL)
2039 option_state_dereference(&reply->reply_ia, MDL);
2040 if (ia_data.data != NULL)
2041 data_string_forget(&ia_data, MDL);
2042 if (data.data != NULL)
2043 data_string_forget(&data, MDL);
2044 if (reply->ia != NULL)
2045 ia_dereference(&reply->ia, MDL);
2046 if (reply->old_ia != NULL)
2047 ia_dereference(&reply->old_ia, MDL);
2048 if (reply->lease != NULL)
2049 iasubopt_dereference(&reply->lease, MDL);
2050 if (reply->fixed.data != NULL)
2051 data_string_forget(&reply->fixed, MDL);
2052 if (reply->subnet != NULL)
2053 subnet_dereference(&reply->subnet, MDL);
2054 if (reply->on_star.on_expiry != NULL)
2055 executable_statement_dereference
2056 (&reply->on_star.on_expiry, MDL);
2057 if (reply->on_star.on_release != NULL)
2058 executable_statement_dereference
2059 (&reply->on_star.on_release, MDL);
2062 * ISC_R_CANCELED is a status code used by the addr processing to
2063 * indicate we're replying with a status code. This is still a
2064 * success at higher layers.
2066 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2070 * Process an IAADDR within a given IA_xA, storing any IAADDR reply contents
2071 * into the reply's current ia-scoped option cache. Returns ISC_R_CANCELED
2072 * in the event we are replying with a status code and do not wish to process
2073 * more IAADDRs within this IA.
2075 static isc_result_t
2076 reply_process_addr(struct reply_state *reply, struct option_cache *addr) {
2077 u_int32_t pref_life, valid_life;
2078 struct binding_scope **scope;
2079 struct group *group;
2080 struct subnet *subnet;
2081 struct iaddr tmp_addr;
2082 struct option_cache *oc;
2083 struct data_string iaaddr, data;
2084 isc_result_t status = ISC_R_SUCCESS;
2086 /* Initializes values that will be cleaned up. */
2087 memset(&iaaddr, 0, sizeof(iaaddr));
2088 memset(&data, 0, sizeof(data));
2089 /* Note that reply->lease may be set by address_is_owned() */
2092 * There is no point trying to process an incoming address if there
2093 * is no room for an outgoing address.
2095 if ((reply->cursor + 28) > sizeof(reply->buf)) {
2096 log_error("reply_process_addr: Out of room for address.");
2097 return ISC_R_NOSPACE;
2100 /* Extract this IAADDR option. */
2101 if (!evaluate_option_cache(&iaaddr, reply->packet, NULL, NULL,
2102 reply->packet->options, NULL, &global_scope,
2103 addr, MDL) ||
2104 (iaaddr.len < IAADDR_OFFSET)) {
2105 log_error("reply_process_addr: error evaluating IAADDR.");
2106 status = ISC_R_FAILURE;
2107 goto cleanup;
2110 /* The first 16 bytes are the IPv6 address. */
2111 pref_life = getULong(iaaddr.data + 16);
2112 valid_life = getULong(iaaddr.data + 20);
2114 if ((reply->client_valid == 0) ||
2115 (reply->client_valid > valid_life))
2116 reply->client_valid = valid_life;
2118 if ((reply->client_prefer == 0) ||
2119 (reply->client_prefer > pref_life))
2120 reply->client_prefer = pref_life;
2123 * Clients may choose to send :: as an address, with the idea to give
2124 * hints about preferred-lifetime or valid-lifetime.
2126 tmp_addr.len = 16;
2127 memset(tmp_addr.iabuf, 0, 16);
2128 if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
2129 /* Status remains success; we just ignore this one. */
2130 goto cleanup;
2133 /* tmp_addr len remains 16 */
2134 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2137 * Verify that this address is on the client's network.
2139 for (subnet = reply->shared->subnets ; subnet != NULL ;
2140 subnet = subnet->next_sibling) {
2141 if (addr_eq(subnet_number(tmp_addr, subnet->netmask),
2142 subnet->net))
2143 break;
2146 /* Address not found on shared network. */
2147 if (subnet == NULL) {
2148 /* Ignore this address on 'soft' bindings. */
2149 if (reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
2150 /* disable rapid commit */
2151 reply->buf.reply.msg_type = DHCPV6_ADVERTISE;
2152 delete_option(&dhcpv6_universe,
2153 reply->opt_state,
2154 D6O_RAPID_COMMIT);
2155 /* status remains success */
2156 goto cleanup;
2160 * RFC3315 section 18.2.1:
2162 * If the server finds that the prefix on one or more IP
2163 * addresses in any IA in the message from the client is not
2164 * appropriate for the link to which the client is connected,
2165 * the server MUST return the IA to the client with a Status
2166 * Code option with the value NotOnLink.
2168 if (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) {
2169 /* Rewind the IA_NA to empty. */
2170 option_state_dereference(&reply->reply_ia, MDL);
2171 if (!option_state_allocate(&reply->reply_ia, MDL)) {
2172 log_error("reply_process_addr: No memory for "
2173 "option state wipe.");
2174 status = ISC_R_NOMEMORY;
2175 goto cleanup;
2178 /* Append a NotOnLink status code. */
2179 if (!set_status_code(STATUS_NotOnLink,
2180 "Address not for use on this "
2181 "link.", reply->reply_ia)) {
2182 log_error("reply_process_addr: Failure "
2183 "setting status code.");
2184 status = ISC_R_FAILURE;
2185 goto cleanup;
2188 /* Fin (no more IAADDRs). */
2189 status = ISC_R_CANCELED;
2190 goto cleanup;
2194 * RFC3315 sections 18.2.3 and 18.2.4 have identical language:
2196 * If the server finds that any of the addresses are not
2197 * appropriate for the link to which the client is attached,
2198 * the server returns the address to the client with lifetimes
2199 * of 0.
2201 if ((reply->packet->dhcpv6_msg_type != DHCPV6_RENEW) &&
2202 (reply->packet->dhcpv6_msg_type != DHCPV6_REBIND)) {
2203 log_error("It is impossible to lease a client that is "
2204 "not sending a solicit, request, renew, or "
2205 "rebind.");
2206 status = ISC_R_FAILURE;
2207 goto cleanup;
2210 reply->send_prefer = reply->send_valid = 0;
2211 goto send_addr;
2214 /* Verify the address belongs to the client. */
2215 if (!address_is_owned(reply, &tmp_addr)) {
2217 * For solicit and request, any addresses included are
2218 * 'requested' addresses. For rebind, we actually have
2219 * no direction on what to do from 3315 section 18.2.4!
2220 * So I think the best bet is to try and give it out, and if
2221 * we can't, zero lifetimes.
2223 if ((reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) ||
2224 (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) ||
2225 (reply->packet->dhcpv6_msg_type == DHCPV6_REBIND)) {
2226 status = reply_process_try_addr(reply, &tmp_addr);
2229 * If the address is in use, or isn't in any dynamic
2230 * range, continue as normal. If any other error was
2231 * found, error out.
2233 if ((status != ISC_R_SUCCESS) &&
2234 (status != ISC_R_ADDRINUSE) &&
2235 (status != ISC_R_ADDRNOTAVAIL))
2236 goto cleanup;
2239 * If we didn't honor this lease, for solicit and
2240 * request we simply omit it from our answer. For
2241 * rebind, we send it with zeroed lifetimes.
2243 if (reply->lease == NULL) {
2244 if (reply->packet->dhcpv6_msg_type ==
2245 DHCPV6_REBIND) {
2246 reply->send_prefer = 0;
2247 reply->send_valid = 0;
2248 goto send_addr;
2251 /* status remains success - ignore */
2252 goto cleanup;
2255 * RFC3315 section 18.2.3:
2257 * If the server cannot find a client entry for the IA the
2258 * server returns the IA containing no addresses with a Status
2259 * Code option set to NoBinding in the Reply message.
2261 * On mismatch we (ab)use this pretending we have not the IA
2262 * as soon as we have not an address.
2264 } else if (reply->packet->dhcpv6_msg_type == DHCPV6_RENEW) {
2265 /* Rewind the IA_NA to empty. */
2266 option_state_dereference(&reply->reply_ia, MDL);
2267 if (!option_state_allocate(&reply->reply_ia, MDL)) {
2268 log_error("reply_process_addr: No memory for "
2269 "option state wipe.");
2270 status = ISC_R_NOMEMORY;
2271 goto cleanup;
2274 /* Append a NoBinding status code. */
2275 if (!set_status_code(STATUS_NoBinding,
2276 "Address not bound to this "
2277 "interface.", reply->reply_ia)) {
2278 log_error("reply_process_addr: Unable to "
2279 "attach status code.");
2280 status = ISC_R_FAILURE;
2281 goto cleanup;
2284 /* Fin (no more IAADDRs). */
2285 status = ISC_R_CANCELED;
2286 goto cleanup;
2287 } else {
2288 log_error("It is impossible to lease a client that is "
2289 "not sending a solicit, request, renew, or "
2290 "rebind message.");
2291 status = ISC_R_FAILURE;
2292 goto cleanup;
2296 if (reply->static_lease) {
2297 if (reply->host == NULL)
2298 log_fatal("Impossible condition at %s:%d.", MDL);
2300 scope = &global_scope;
2301 group = reply->subnet->group;
2302 } else {
2303 if (reply->lease == NULL)
2304 log_fatal("Impossible condition at %s:%d.", MDL);
2306 scope = &reply->lease->scope;
2307 group = reply->lease->ipv6_pool->ipv6_pond->group;
2311 * If client_resources is nonzero, then the reply_process_is_addressed
2312 * function has executed configuration state into the reply option
2313 * cache. We will use that valid cache to derive configuration for
2314 * whether or not to engage in additional addresses, and similar.
2316 if (reply->client_resources != 0) {
2317 unsigned limit = 1;
2320 * Does this client have "enough" addresses already? Default
2321 * to one. Everybody gets one, and one should be enough for
2322 * anybody.
2324 oc = lookup_option(&server_universe, reply->opt_state,
2325 SV_LIMIT_ADDRS_PER_IA);
2326 if (oc != NULL) {
2327 if (!evaluate_option_cache(&data, reply->packet,
2328 NULL, NULL,
2329 reply->packet->options,
2330 reply->opt_state,
2331 scope, oc, MDL) ||
2332 (data.len != 4)) {
2333 log_error("reply_process_addr: unable to "
2334 "evaluate addrs-per-ia value.");
2335 status = ISC_R_FAILURE;
2336 goto cleanup;
2339 limit = getULong(data.data);
2340 data_string_forget(&data, MDL);
2344 * If we wish to limit the client to a certain number of
2345 * addresses, then omit the address from the reply.
2347 if (reply->client_resources >= limit)
2348 goto cleanup;
2351 status = reply_process_is_addressed(reply, scope, group);
2352 if (status != ISC_R_SUCCESS)
2353 goto cleanup;
2355 send_addr:
2356 status = reply_process_send_addr(reply, &tmp_addr);
2358 cleanup:
2359 if (iaaddr.data != NULL)
2360 data_string_forget(&iaaddr, MDL);
2361 if (data.data != NULL)
2362 data_string_forget(&data, MDL);
2363 if (reply->lease != NULL)
2364 iasubopt_dereference(&reply->lease, MDL);
2366 return status;
2370 * Verify the address belongs to the client. If we've got a host
2371 * record with a fixed address, it has to be the assigned address
2372 * (fault out all else). Otherwise it's a dynamic address, so lookup
2373 * that address and make sure it belongs to this DUID:IAID pair.
2375 static isc_boolean_t
2376 address_is_owned(struct reply_state *reply, struct iaddr *addr) {
2377 int i;
2378 struct ipv6_pond *pond;
2381 * This faults out addresses that don't match fixed addresses.
2383 if (reply->static_lease) {
2384 if (reply->fixed.data == NULL)
2385 log_fatal("Impossible condition at %s:%d.", MDL);
2387 if (memcmp(addr->iabuf, reply->fixed.data, 16) == 0)
2388 return (ISC_TRUE);
2390 return (ISC_FALSE);
2393 if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
2394 return (ISC_FALSE);
2396 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2397 struct iasubopt *tmp;
2399 tmp = reply->old_ia->iasubopt[i];
2401 if (memcmp(addr->iabuf, &tmp->addr, 16) == 0) {
2402 if (lease6_usable(tmp) == ISC_FALSE) {
2403 return (ISC_FALSE);
2406 pond = tmp->ipv6_pool->ipv6_pond;
2407 if (((pond->prohibit_list != NULL) &&
2408 (permitted(reply->packet, pond->prohibit_list))) ||
2409 ((pond->permit_list != NULL) &&
2410 (!permitted(reply->packet, pond->permit_list))))
2411 return (ISC_FALSE);
2413 iasubopt_reference(&reply->lease, tmp, MDL);
2415 return (ISC_TRUE);
2419 return (ISC_FALSE);
2422 /* Process a client-supplied IA_TA. This may append options to the tail of
2423 * the reply packet being built in the reply_state structure.
2425 static isc_result_t
2426 reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
2427 isc_result_t status = ISC_R_SUCCESS;
2428 u_int32_t iaid;
2429 unsigned ia_cursor;
2430 struct option_state *packet_ia;
2431 struct option_cache *oc;
2432 struct data_string ia_data, data;
2433 struct data_string iaaddr;
2434 u_int32_t pref_life, valid_life;
2435 struct iaddr tmp_addr;
2437 /* Initialize values that will get cleaned up on return. */
2438 packet_ia = NULL;
2439 memset(&ia_data, 0, sizeof(ia_data));
2440 memset(&data, 0, sizeof(data));
2441 memset(&iaaddr, 0, sizeof(iaaddr));
2443 /* Make sure there is at least room for the header. */
2444 if ((reply->cursor + IA_TA_OFFSET + 4) > sizeof(reply->buf)) {
2445 log_error("reply_process_ia_ta: Reply too long for IA.");
2446 return ISC_R_NOSPACE;
2450 /* Fetch the IA_TA contents. */
2451 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2452 ia, IA_TA_OFFSET)) {
2453 log_error("reply_process_ia_ta: error evaluating ia");
2454 status = ISC_R_FAILURE;
2455 goto cleanup;
2458 /* Extract IA_TA header contents. */
2459 iaid = getULong(ia_data.data);
2461 /* Create an IA_TA structure. */
2462 if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
2463 reply->client_id.len, MDL) != ISC_R_SUCCESS) {
2464 log_error("reply_process_ia_ta: no memory for ia.");
2465 status = ISC_R_NOMEMORY;
2466 goto cleanup;
2468 reply->ia->ia_type = D6O_IA_TA;
2470 /* Cache pre-existing IA, if any. */
2471 ia_hash_lookup(&reply->old_ia, ia_ta_active,
2472 (unsigned char *)reply->ia->iaid_duid.data,
2473 reply->ia->iaid_duid.len, MDL);
2476 * Create an option cache to carry the IA_TA option contents, and
2477 * execute any user-supplied values into it.
2479 if (!option_state_allocate(&reply->reply_ia, MDL)) {
2480 status = ISC_R_NOMEMORY;
2481 goto cleanup;
2485 * Temporary leases are dynamic by definition.
2487 reply->static_lease = ISC_FALSE;
2490 * Save the cursor position at the start of the IA, so we can
2491 * set length later. We write a temporary
2492 * header out now just in case we decide to adjust the packet
2493 * within sub-process functions.
2495 ia_cursor = reply->cursor;
2497 /* Initialize the IA_TA header. First the code. */
2498 putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_TA);
2499 reply->cursor += 2;
2501 /* Then option length. */
2502 putUShort(reply->buf.data + reply->cursor, 0x04u);
2503 reply->cursor += 2;
2505 /* Then IA_TA header contents; IAID. */
2506 putULong(reply->buf.data + reply->cursor, iaid);
2507 reply->cursor += 4;
2510 * Deal with an IAADDR for lifetimes.
2511 * For all or none, process IAADDRs as hints.
2513 reply->valid = reply->prefer = 0xffffffff;
2514 reply->client_valid = reply->client_prefer = 0;
2515 oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
2516 for (; oc != NULL; oc = oc->next) {
2517 memset(&iaaddr, 0, sizeof(iaaddr));
2518 if (!evaluate_option_cache(&iaaddr, reply->packet,
2519 NULL, NULL,
2520 reply->packet->options, NULL,
2521 &global_scope, oc, MDL) ||
2522 (iaaddr.len < IAADDR_OFFSET)) {
2523 log_error("reply_process_ia_ta: error "
2524 "evaluating IAADDR.");
2525 status = ISC_R_FAILURE;
2526 goto cleanup;
2528 /* The first 16 bytes are the IPv6 address. */
2529 pref_life = getULong(iaaddr.data + 16);
2530 valid_life = getULong(iaaddr.data + 20);
2532 if ((reply->client_valid == 0) ||
2533 (reply->client_valid > valid_life))
2534 reply->client_valid = valid_life;
2536 if ((reply->client_prefer == 0) ||
2537 (reply->client_prefer > pref_life))
2538 reply->client_prefer = pref_life;
2540 /* Nothing more if something has failed. */
2541 if (status == ISC_R_CANCELED)
2542 continue;
2544 tmp_addr.len = 16;
2545 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2546 if (!temporary_is_available(reply, &tmp_addr))
2547 goto bad_temp;
2548 status = reply_process_is_addressed(reply,
2549 &reply->lease->scope,
2550 reply->lease->ipv6_pool->ipv6_pond->group);
2551 if (status != ISC_R_SUCCESS)
2552 goto bad_temp;
2553 status = reply_process_send_addr(reply, &tmp_addr);
2554 if (status != ISC_R_SUCCESS)
2555 goto bad_temp;
2556 if (reply->lease != NULL)
2557 iasubopt_dereference(&reply->lease, MDL);
2558 continue;
2560 bad_temp:
2561 /* Rewind the IA_TA to empty. */
2562 option_state_dereference(&reply->reply_ia, MDL);
2563 if (!option_state_allocate(&reply->reply_ia, MDL)) {
2564 status = ISC_R_NOMEMORY;
2565 goto cleanup;
2567 status = ISC_R_CANCELED;
2568 reply->client_resources = 0;
2569 reply->resources_included = ISC_FALSE;
2570 if (reply->lease != NULL)
2571 iasubopt_dereference(&reply->lease, MDL);
2573 reply->ia_count++;
2576 * Give the client temporary addresses.
2578 if (reply->client_resources != 0)
2579 goto store;
2580 status = find_client_temporaries(reply);
2581 if (status == ISC_R_NORESOURCES) {
2582 switch (reply->packet->dhcpv6_msg_type) {
2583 case DHCPV6_SOLICIT:
2585 * No address for any IA is handled
2586 * by the caller.
2588 /* FALL THROUGH */
2590 case DHCPV6_REQUEST:
2591 /* Section 18.2.1 (Request):
2593 * If the server cannot assign any addresses to
2594 * an IA in the message from the client, the
2595 * server MUST include the IA in the Reply
2596 * message with no addresses in the IA and a
2597 * Status Code option in the IA containing
2598 * status code NoAddrsAvail.
2600 option_state_dereference(&reply->reply_ia, MDL);
2601 if (!option_state_allocate(&reply->reply_ia, MDL)) {
2602 log_error("reply_process_ia_ta: No "
2603 "memory for option state wipe.");
2604 status = ISC_R_NOMEMORY;
2605 goto cleanup;
2608 if (!set_status_code(STATUS_NoAddrsAvail,
2609 "No addresses available "
2610 "for this interface.",
2611 reply->reply_ia)) {
2612 log_error("reply_process_ia_ta: Unable "
2613 "to set NoAddrsAvail status code.");
2614 status = ISC_R_FAILURE;
2615 goto cleanup;
2618 status = ISC_R_SUCCESS;
2619 break;
2621 default:
2623 * We don't want to include the IA if we
2624 * provide zero addresses including zeroed
2625 * lifetimes.
2627 if (reply->resources_included)
2628 status = ISC_R_SUCCESS;
2629 else
2630 goto cleanup;
2631 break;
2633 } else if (status != ISC_R_SUCCESS)
2634 goto cleanup;
2636 store:
2637 reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
2638 sizeof(reply->buf) - reply->cursor,
2639 reply->reply_ia, reply->packet,
2640 required_opts_IA, NULL);
2642 /* Reset the length of this IA to match what was just written. */
2643 putUShort(reply->buf.data + ia_cursor + 2,
2644 reply->cursor - (ia_cursor + 4));
2647 * yes, goto's aren't the best but we also want to avoid extra
2648 * indents
2650 if (status == ISC_R_CANCELED)
2651 goto cleanup;
2654 * If we have any addresses log what we are doing.
2656 if (reply->ia->num_iasubopt != 0) {
2657 struct iasubopt *tmp;
2658 int i;
2659 char tmp_addr[INET6_ADDRSTRLEN];
2661 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2662 tmp = reply->ia->iasubopt[i];
2664 log_info("%s TA: address %s to client with duid %s "
2665 "iaid = %d valid for %d seconds",
2666 dhcpv6_type_names[reply->buf.reply.msg_type],
2667 inet_ntop(AF_INET6, &tmp->addr,
2668 tmp_addr, sizeof(tmp_addr)),
2669 print_hex_1(reply->client_id.len,
2670 reply->client_id.data, 60),
2671 iaid,
2672 tmp->valid);
2677 * For hard bindings we consume the new changes into
2678 * the database (if any have been attached to the ia_ta).
2680 * Loop through the assigned dynamic addresses, referencing the
2681 * leases onto this IA_TA rather than any old ones, and updating
2682 * pool timers for each (if any).
2684 if ((reply->ia->num_iasubopt != 0) &&
2685 (reply->buf.reply.msg_type == DHCPV6_REPLY)) {
2686 struct iasubopt *tmp;
2687 struct data_string *ia_id;
2688 int i;
2690 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2691 tmp = reply->ia->iasubopt[i];
2693 if (tmp->ia != NULL)
2694 ia_dereference(&tmp->ia, MDL);
2695 ia_reference(&tmp->ia, reply->ia, MDL);
2697 /* Commit 'hard' bindings. */
2698 renew_lease6(tmp->ipv6_pool, tmp);
2699 schedule_lease_timeout(tmp->ipv6_pool);
2701 /* If we have anything to do on commit do it now */
2702 if (tmp->on_star.on_commit != NULL) {
2703 execute_statements(NULL, reply->packet,
2704 NULL, NULL,
2705 reply->packet->options,
2706 reply->opt_state,
2707 &tmp->scope,
2708 tmp->on_star.on_commit,
2709 &tmp->on_star);
2710 executable_statement_dereference
2711 (&tmp->on_star.on_commit, MDL);
2714 #if defined (NSUPDATE)
2716 * Perform ddns updates.
2718 oc = lookup_option(&server_universe, reply->opt_state,
2719 SV_DDNS_UPDATES);
2720 if ((oc == NULL) ||
2721 evaluate_boolean_option_cache(NULL, reply->packet,
2722 NULL, NULL,
2723 reply->packet->options,
2724 reply->opt_state,
2725 &tmp->scope,
2726 oc, MDL)) {
2727 ddns_updates(reply->packet, NULL, NULL,
2728 tmp, NULL, reply->opt_state);
2730 #endif
2733 /* Remove any old ia from the hash. */
2734 if (reply->old_ia != NULL) {
2735 ia_id = &reply->old_ia->iaid_duid;
2736 ia_hash_delete(ia_ta_active,
2737 (unsigned char *)ia_id->data,
2738 ia_id->len, MDL);
2739 ia_dereference(&reply->old_ia, MDL);
2742 /* Put new ia into the hash. */
2743 reply->ia->cltt = cur_time;
2744 ia_id = &reply->ia->iaid_duid;
2745 ia_hash_add(ia_ta_active, (unsigned char *)ia_id->data,
2746 ia_id->len, reply->ia, MDL);
2748 write_ia(reply->ia);
2751 cleanup:
2752 if (packet_ia != NULL)
2753 option_state_dereference(&packet_ia, MDL);
2754 if (iaaddr.data != NULL)
2755 data_string_forget(&iaaddr, MDL);
2756 if (reply->reply_ia != NULL)
2757 option_state_dereference(&reply->reply_ia, MDL);
2758 if (ia_data.data != NULL)
2759 data_string_forget(&ia_data, MDL);
2760 if (data.data != NULL)
2761 data_string_forget(&data, MDL);
2762 if (reply->ia != NULL)
2763 ia_dereference(&reply->ia, MDL);
2764 if (reply->old_ia != NULL)
2765 ia_dereference(&reply->old_ia, MDL);
2766 if (reply->lease != NULL)
2767 iasubopt_dereference(&reply->lease, MDL);
2770 * ISC_R_CANCELED is a status code used by the addr processing to
2771 * indicate we're replying with other addresses. This is still a
2772 * success at higher layers.
2774 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2778 * Verify the temporary address is available.
2780 static isc_boolean_t
2781 temporary_is_available(struct reply_state *reply, struct iaddr *addr) {
2782 struct in6_addr tmp_addr;
2783 struct subnet *subnet;
2784 struct ipv6_pool *pool = NULL;
2785 struct ipv6_pond *pond = NULL;
2786 int i;
2788 memcpy(&tmp_addr, addr->iabuf, sizeof(tmp_addr));
2790 * Clients may choose to send :: as an address, with the idea to give
2791 * hints about preferred-lifetime or valid-lifetime.
2792 * So this is not a request for this address.
2794 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
2795 return ISC_FALSE;
2798 * Verify that this address is on the client's network.
2800 for (subnet = reply->shared->subnets ; subnet != NULL ;
2801 subnet = subnet->next_sibling) {
2802 if (addr_eq(subnet_number(*addr, subnet->netmask),
2803 subnet->net))
2804 break;
2807 /* Address not found on shared network. */
2808 if (subnet == NULL)
2809 return ISC_FALSE;
2812 * Check if this address is owned (must be before next step).
2814 if (address_is_owned(reply, addr))
2815 return ISC_TRUE;
2818 * Verify that this address is in a temporary pool and try to get it.
2820 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
2821 if (((pond->prohibit_list != NULL) &&
2822 (permitted(reply->packet, pond->prohibit_list))) ||
2823 ((pond->permit_list != NULL) &&
2824 (!permitted(reply->packet, pond->permit_list))))
2825 continue;
2827 for (i = 0 ; (pool = pond->ipv6_pools[i]) != NULL ; i++) {
2828 if (pool->pool_type != D6O_IA_TA)
2829 continue;
2831 if (ipv6_in_pool(&tmp_addr, pool))
2832 break;
2835 if (pool != NULL)
2836 break;
2839 if (pool == NULL)
2840 return ISC_FALSE;
2841 if (lease6_exists(pool, &tmp_addr))
2842 return ISC_FALSE;
2843 if (iasubopt_allocate(&reply->lease, MDL) != ISC_R_SUCCESS)
2844 return ISC_FALSE;
2845 reply->lease->addr = tmp_addr;
2846 reply->lease->plen = 0;
2847 /* Default is soft binding for 2 minutes. */
2848 if (add_lease6(pool, reply->lease, cur_time + 120) != ISC_R_SUCCESS)
2849 return ISC_FALSE;
2851 return ISC_TRUE;
2855 * Get a temporary address per prefix.
2857 static isc_result_t
2858 find_client_temporaries(struct reply_state *reply) {
2859 int i;
2860 struct ipv6_pool *p = NULL;
2861 struct ipv6_pond *pond;
2862 isc_result_t status = ISC_R_NORESOURCES;;
2863 unsigned int attempts;
2864 struct iaddr send_addr;
2867 * Do a quick walk through of the ponds and pools
2868 * to see if we have any prefix pools
2870 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
2871 if (pond->ipv6_pools == NULL)
2872 continue;
2874 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
2875 if (p->pool_type == D6O_IA_TA)
2876 break;
2878 if (p != NULL)
2879 break;
2882 /* If we get here and p is NULL we have no useful pools */
2883 if (p == NULL) {
2884 log_debug("Unable to get client addresses: "
2885 "no IPv6 pools on this shared network");
2886 return ISC_R_NORESOURCES;
2890 * We have at least one pool that could provide an address
2891 * Now we walk through the ponds and pools again and check
2892 * to see if the client is permitted and if an address is
2893 * available
2896 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
2897 if (((pond->prohibit_list != NULL) &&
2898 (permitted(reply->packet, pond->prohibit_list))) ||
2899 ((pond->permit_list != NULL) &&
2900 (!permitted(reply->packet, pond->permit_list))))
2901 continue;
2903 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
2904 if (p->pool_type != D6O_IA_TA) {
2905 continue;
2909 * Get an address in this temporary pool.
2911 status = create_lease6(p, &reply->lease, &attempts,
2912 &reply->client_id, cur_time + 120);
2913 if (status != ISC_R_SUCCESS) {
2914 log_debug("Unable to get a temporary address.");
2915 goto cleanup;
2918 status = reply_process_is_addressed(reply,
2919 &reply->lease->scope,
2920 pond->group);
2921 if (status != ISC_R_SUCCESS) {
2922 goto cleanup;
2924 send_addr.len = 16;
2925 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
2926 status = reply_process_send_addr(reply, &send_addr);
2927 if (status != ISC_R_SUCCESS) {
2928 goto cleanup;
2931 * reply->lease can't be null as we use it above
2932 * add check if that changes
2934 iasubopt_dereference(&reply->lease, MDL);
2938 cleanup:
2939 if (reply->lease != NULL) {
2940 iasubopt_dereference(&reply->lease, MDL);
2942 return status;
2946 * This function only returns failure on 'hard' failures. If it succeeds,
2947 * it will leave a lease structure behind.
2949 static isc_result_t
2950 reply_process_try_addr(struct reply_state *reply, struct iaddr *addr) {
2951 isc_result_t status = ISC_R_ADDRNOTAVAIL;
2952 struct ipv6_pool *pool = NULL;
2953 struct ipv6_pond *pond = NULL;
2954 int i;
2955 struct data_string data_addr;
2957 if ((reply == NULL) || (reply->shared == NULL) ||
2958 (addr == NULL) || (reply->lease != NULL))
2959 return (DHCP_R_INVALIDARG);
2962 * Do a quick walk through of the ponds and pools
2963 * to see if we have any NA address pools
2965 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
2966 if (pond->ipv6_pools == NULL)
2967 continue;
2969 for (i = 0; ; i++) {
2970 pool = pond->ipv6_pools[i];
2971 if ((pool == NULL) ||
2972 (pool->pool_type == D6O_IA_NA))
2973 break;
2975 if (pool != NULL)
2976 break;
2979 /* If we get here and p is NULL we have no useful pools */
2980 if (pool == NULL) {
2981 return (ISC_R_ADDRNOTAVAIL);
2984 memset(&data_addr, 0, sizeof(data_addr));
2985 data_addr.len = addr->len;
2986 data_addr.data = addr->iabuf;
2989 * We have at least one pool that could provide an address
2990 * Now we walk through the ponds and pools again and check
2991 * to see if the client is permitted and if an address is
2992 * available
2994 * Within a given pond we start looking at the last pool we
2995 * allocated from, unless it had a collision trying to allocate
2996 * an address. This will tend to move us into less-filled pools.
2999 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
3000 if (((pond->prohibit_list != NULL) &&
3001 (permitted(reply->packet, pond->prohibit_list))) ||
3002 ((pond->permit_list != NULL) &&
3003 (!permitted(reply->packet, pond->permit_list))))
3004 continue;
3006 for (i = 0 ; (pool = pond->ipv6_pools[i]) != NULL ; i++) {
3007 if (pool->pool_type != D6O_IA_NA)
3008 continue;
3010 status = try_client_v6_address(&reply->lease, pool,
3011 &data_addr);
3012 if (status == ISC_R_SUCCESS)
3013 break;
3016 if (status == ISC_R_SUCCESS)
3017 break;
3020 /* Note that this is just pedantry. There is no allocation to free. */
3021 data_string_forget(&data_addr, MDL);
3022 /* Return just the most recent status... */
3023 return (status);
3026 /* Look around for an address to give the client. First, look through the
3027 * old IA for addresses we can extend. Second, try to allocate a new address.
3028 * Finally, actually add that address into the current reply IA.
3030 static isc_result_t
3031 find_client_address(struct reply_state *reply) {
3032 struct iaddr send_addr;
3033 isc_result_t status = ISC_R_NORESOURCES;
3034 struct iasubopt *lease, *best_lease = NULL;
3035 struct binding_scope **scope;
3036 struct group *group;
3037 int i;
3039 if (reply->static_lease) {
3040 if (reply->host == NULL)
3041 return DHCP_R_INVALIDARG;
3043 send_addr.len = 16;
3044 memcpy(send_addr.iabuf, reply->fixed.data, 16);
3046 scope = &global_scope;
3047 group = reply->subnet->group;
3048 goto send_addr;
3051 if (reply->old_ia != NULL) {
3052 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
3053 struct shared_network *candidate_shared;
3054 struct ipv6_pond *pond;
3056 lease = reply->old_ia->iasubopt[i];
3057 candidate_shared = lease->ipv6_pool->shared_network;
3058 pond = lease->ipv6_pool->ipv6_pond;
3061 * Look for the best lease on the client's shared
3062 * network, that is still permitted
3065 if ((candidate_shared != reply->shared) ||
3066 (lease6_usable(lease) != ISC_TRUE))
3067 continue;
3069 if (((pond->prohibit_list != NULL) &&
3070 (permitted(reply->packet, pond->prohibit_list))) ||
3071 ((pond->permit_list != NULL) &&
3072 (!permitted(reply->packet, pond->permit_list))))
3073 continue;
3075 best_lease = lease_compare(lease, best_lease);
3079 /* Try to pick a new address if we didn't find one, or if we found an
3080 * abandoned lease.
3082 if ((best_lease == NULL) || (best_lease->state == FTS_ABANDONED)) {
3083 status = pick_v6_address(reply);
3084 } else if (best_lease != NULL) {
3085 iasubopt_reference(&reply->lease, best_lease, MDL);
3086 status = ISC_R_SUCCESS;
3089 /* Pick the abandoned lease as a last resort. */
3090 if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
3091 /* I don't see how this is supposed to be done right now. */
3092 log_error("Reclaiming abandoned addresses is not yet "
3093 "supported. Treating this as an out of space "
3094 "condition.");
3095 /* iasubopt_reference(&reply->lease, best_lease, MDL); */
3098 /* Give up now if we didn't find a lease. */
3099 if (status != ISC_R_SUCCESS)
3100 return status;
3102 if (reply->lease == NULL)
3103 log_fatal("Impossible condition at %s:%d.", MDL);
3105 /* Draw binding scopes from the lease's binding scope, and config
3106 * from the lease's containing subnet and higher. Note that it may
3107 * be desirable to place the group attachment directly in the pool.
3109 scope = &reply->lease->scope;
3110 group = reply->lease->ipv6_pool->ipv6_pond->group;
3112 send_addr.len = 16;
3113 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3115 send_addr:
3116 status = reply_process_is_addressed(reply, scope, group);
3117 if (status != ISC_R_SUCCESS)
3118 return status;
3120 status = reply_process_send_addr(reply, &send_addr);
3121 return status;
3124 /* Once an address is found for a client, perform several common functions;
3125 * Calculate and store valid and preferred lease times, draw client options
3126 * into the option state.
3128 static isc_result_t
3129 reply_process_is_addressed(struct reply_state *reply,
3130 struct binding_scope **scope, struct group *group)
3132 isc_result_t status = ISC_R_SUCCESS;
3133 struct data_string data;
3134 struct option_cache *oc;
3135 struct option_state *tmp_options = NULL;
3136 struct on_star *on_star;
3137 int i;
3139 /* Initialize values we will cleanup. */
3140 memset(&data, 0, sizeof(data));
3143 * Find the proper on_star block to use. We use the
3144 * one in the lease if we have a lease or the one in
3145 * the reply if we don't have a lease because this is
3146 * a static instance
3148 if (reply->lease) {
3149 on_star = &reply->lease->on_star;
3150 } else {
3151 on_star = &reply->on_star;
3155 * Bring in the root configuration. We only do this to bring
3156 * in the on * statements, as we didn't have the lease available
3157 * we did it the first time.
3159 option_state_allocate(&tmp_options, MDL);
3160 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3161 reply->packet->options, tmp_options,
3162 &global_scope, root_group, NULL,
3163 on_star);
3164 if (tmp_options != NULL) {
3165 option_state_dereference(&tmp_options, MDL);
3169 * Bring configured options into the root packet level cache - start
3170 * with the lease's closest enclosing group (passed in by the caller
3171 * as 'group').
3173 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3174 reply->packet->options, reply->opt_state,
3175 scope, group, root_group, on_star);
3177 /* Execute statements from class scopes. */
3178 for (i = reply->packet->class_count; i > 0; i--) {
3179 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3180 reply->packet->options,
3181 reply->opt_state, scope,
3182 reply->packet->classes[i - 1]->group,
3183 group, on_star);
3187 * If there is a host record, over-ride with values configured there,
3188 * without re-evaluating configuration from the previously executed
3189 * group or its common enclosers.
3191 if (reply->host != NULL)
3192 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3193 reply->packet->options,
3194 reply->opt_state, scope,
3195 reply->host->group, group,
3196 on_star);
3198 /* Determine valid lifetime. */
3199 if (reply->client_valid == 0)
3200 reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
3201 else
3202 reply->send_valid = reply->client_valid;
3204 oc = lookup_option(&server_universe, reply->opt_state,
3205 SV_DEFAULT_LEASE_TIME);
3206 if (oc != NULL) {
3207 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
3208 reply->packet->options,
3209 reply->opt_state,
3210 scope, oc, MDL) ||
3211 (data.len != 4)) {
3212 log_error("reply_process_is_addressed: unable to "
3213 "evaluate default lease time");
3214 status = ISC_R_FAILURE;
3215 goto cleanup;
3218 reply->send_valid = getULong(data.data);
3219 data_string_forget(&data, MDL);
3222 if (reply->client_prefer == 0)
3223 reply->send_prefer = reply->send_valid;
3224 else
3225 reply->send_prefer = reply->client_prefer;
3227 if (reply->send_prefer >= reply->send_valid)
3228 reply->send_prefer = (reply->send_valid / 2) +
3229 (reply->send_valid / 8);
3231 oc = lookup_option(&server_universe, reply->opt_state,
3232 SV_PREFER_LIFETIME);
3233 if (oc != NULL) {
3234 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
3235 reply->packet->options,
3236 reply->opt_state,
3237 scope, oc, MDL) ||
3238 (data.len != 4)) {
3239 log_error("reply_process_is_addressed: unable to "
3240 "evaluate preferred lease time");
3241 status = ISC_R_FAILURE;
3242 goto cleanup;
3245 reply->send_prefer = getULong(data.data);
3246 data_string_forget(&data, MDL);
3249 /* Note lowest values for later calculation of renew/rebind times. */
3250 if (reply->prefer > reply->send_prefer)
3251 reply->prefer = reply->send_prefer;
3253 if (reply->valid > reply->send_valid)
3254 reply->valid = reply->send_valid;
3256 #if 0
3258 * XXX: Old 4.0.0 alpha code would change the host {} record
3259 * XXX: uid upon lease assignment. This was intended to cover the
3260 * XXX: case where a client first identifies itself using vendor
3261 * XXX: options in a solicit, or request, but later neglects to include
3262 * XXX: these options in a Renew or Rebind. It is not clear that this
3263 * XXX: is required, and has some startling ramifications (such as
3264 * XXX: how to recover this dynamic host {} state across restarts).
3266 if (reply->host != NULL)
3267 change_host_uid(host, reply->client_id->data,
3268 reply->client_id->len);
3269 #endif /* 0 */
3271 /* Perform dynamic lease related update work. */
3272 if (reply->lease != NULL) {
3273 /* Cached lifetimes */
3274 reply->lease->prefer = reply->send_prefer;
3275 reply->lease->valid = reply->send_valid;
3277 /* Advance (or rewind) the valid lifetime. */
3278 if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
3279 reply->lease->soft_lifetime_end_time =
3280 cur_time + reply->send_valid;
3281 /* Wait before renew! */
3284 status = ia_add_iasubopt(reply->ia, reply->lease, MDL);
3285 if (status != ISC_R_SUCCESS) {
3286 log_fatal("reply_process_is_addressed: Unable to "
3287 "attach lease to new IA: %s",
3288 isc_result_totext(status));
3292 * If this is a new lease, make sure it is attached somewhere.
3294 if (reply->lease->ia == NULL) {
3295 ia_reference(&reply->lease->ia, reply->ia, MDL);
3299 /* Bring a copy of the relevant options into the IA scope. */
3300 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3301 reply->packet->options, reply->reply_ia,
3302 scope, group, root_group, NULL);
3304 /* Execute statements from class scopes. */
3305 for (i = reply->packet->class_count; i > 0; i--) {
3306 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3307 reply->packet->options,
3308 reply->reply_ia, scope,
3309 reply->packet->classes[i - 1]->group,
3310 group, NULL);
3314 * And bring in host record configuration, if any, but not to overlap
3315 * the previous group or its common enclosers.
3317 if (reply->host != NULL)
3318 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3319 reply->packet->options,
3320 reply->reply_ia, scope,
3321 reply->host->group, group, NULL);
3323 cleanup:
3324 if (data.data != NULL)
3325 data_string_forget(&data, MDL);
3327 if (status == ISC_R_SUCCESS)
3328 reply->client_resources++;
3330 return status;
3333 /* Simply send an IAADDR within the IA scope as described. */
3334 static isc_result_t
3335 reply_process_send_addr(struct reply_state *reply, struct iaddr *addr) {
3336 isc_result_t status = ISC_R_SUCCESS;
3337 struct data_string data;
3339 memset(&data, 0, sizeof(data));
3341 /* Now append the lease. */
3342 data.len = IAADDR_OFFSET;
3343 if (!buffer_allocate(&data.buffer, data.len, MDL)) {
3344 log_error("reply_process_send_addr: out of memory"
3345 "allocating new IAADDR buffer.");
3346 status = ISC_R_NOMEMORY;
3347 goto cleanup;
3349 data.data = data.buffer->data;
3351 memcpy(data.buffer->data, addr->iabuf, 16);
3352 putULong(data.buffer->data + 16, reply->send_prefer);
3353 putULong(data.buffer->data + 20, reply->send_valid);
3355 if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
3356 data.buffer, data.buffer->data,
3357 data.len, D6O_IAADDR, 0)) {
3358 log_error("reply_process_send_addr: unable "
3359 "to save IAADDR option");
3360 status = ISC_R_FAILURE;
3361 goto cleanup;
3364 reply->resources_included = ISC_TRUE;
3366 cleanup:
3367 if (data.data != NULL)
3368 data_string_forget(&data, MDL);
3370 return status;
3373 /* Choose the better of two leases. */
3374 static struct iasubopt *
3375 lease_compare(struct iasubopt *alpha, struct iasubopt *beta) {
3376 if (alpha == NULL)
3377 return beta;
3378 if (beta == NULL)
3379 return alpha;
3381 switch(alpha->state) {
3382 case FTS_ACTIVE:
3383 switch(beta->state) {
3384 case FTS_ACTIVE:
3385 /* Choose the lease with the longest lifetime (most
3386 * likely the most recently allocated).
3388 if (alpha->hard_lifetime_end_time <
3389 beta->hard_lifetime_end_time)
3390 return beta;
3391 else
3392 return alpha;
3394 case FTS_EXPIRED:
3395 case FTS_ABANDONED:
3396 return alpha;
3398 default:
3399 log_fatal("Impossible condition at %s:%d.", MDL);
3401 break;
3403 case FTS_EXPIRED:
3404 switch (beta->state) {
3405 case FTS_ACTIVE:
3406 return beta;
3408 case FTS_EXPIRED:
3409 /* Choose the most recently expired lease. */
3410 if (alpha->hard_lifetime_end_time <
3411 beta->hard_lifetime_end_time)
3412 return beta;
3413 else if ((alpha->hard_lifetime_end_time ==
3414 beta->hard_lifetime_end_time) &&
3415 (alpha->soft_lifetime_end_time <
3416 beta->soft_lifetime_end_time))
3417 return beta;
3418 else
3419 return alpha;
3421 case FTS_ABANDONED:
3422 return alpha;
3424 default:
3425 log_fatal("Impossible condition at %s:%d.", MDL);
3427 break;
3429 case FTS_ABANDONED:
3430 switch (beta->state) {
3431 case FTS_ACTIVE:
3432 case FTS_EXPIRED:
3433 return alpha;
3435 case FTS_ABANDONED:
3436 /* Choose the lease that was abandoned longest ago. */
3437 if (alpha->hard_lifetime_end_time <
3438 beta->hard_lifetime_end_time)
3439 return alpha;
3441 default:
3442 log_fatal("Impossible condition at %s:%d.", MDL);
3444 break;
3446 default:
3447 log_fatal("Impossible condition at %s:%d.", MDL);
3450 log_fatal("Triple impossible condition at %s:%d.", MDL);
3451 return NULL;
3454 /* Process a client-supplied IA_PD. This may append options to the tail of
3455 * the reply packet being built in the reply_state structure.
3457 static isc_result_t
3458 reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
3459 isc_result_t status = ISC_R_SUCCESS;
3460 u_int32_t iaid;
3461 unsigned ia_cursor;
3462 struct option_state *packet_ia;
3463 struct option_cache *oc;
3464 struct data_string ia_data, data;
3466 /* Initialize values that will get cleaned up on return. */
3467 packet_ia = NULL;
3468 memset(&ia_data, 0, sizeof(ia_data));
3469 memset(&data, 0, sizeof(data));
3471 * Note that find_client_prefix() may set reply->lease.
3474 /* Make sure there is at least room for the header. */
3475 if ((reply->cursor + IA_PD_OFFSET + 4) > sizeof(reply->buf)) {
3476 log_error("reply_process_ia_pd: Reply too long for IA.");
3477 return ISC_R_NOSPACE;
3481 /* Fetch the IA_PD contents. */
3482 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
3483 ia, IA_PD_OFFSET)) {
3484 log_error("reply_process_ia_pd: error evaluating ia");
3485 status = ISC_R_FAILURE;
3486 goto cleanup;
3489 /* Extract IA_PD header contents. */
3490 iaid = getULong(ia_data.data);
3491 reply->renew = getULong(ia_data.data + 4);
3492 reply->rebind = getULong(ia_data.data + 8);
3494 /* Create an IA_PD structure. */
3495 if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
3496 reply->client_id.len, MDL) != ISC_R_SUCCESS) {
3497 log_error("reply_process_ia_pd: no memory for ia.");
3498 status = ISC_R_NOMEMORY;
3499 goto cleanup;
3501 reply->ia->ia_type = D6O_IA_PD;
3503 /* Cache pre-existing IA_PD, if any. */
3504 ia_hash_lookup(&reply->old_ia, ia_pd_active,
3505 (unsigned char *)reply->ia->iaid_duid.data,
3506 reply->ia->iaid_duid.len, MDL);
3509 * Create an option cache to carry the IA_PD option contents, and
3510 * execute any user-supplied values into it.
3512 if (!option_state_allocate(&reply->reply_ia, MDL)) {
3513 status = ISC_R_NOMEMORY;
3514 goto cleanup;
3517 /* Check & count the fixed prefix host records. */
3518 reply->static_prefixes = 0;
3519 if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
3520 struct iaddrcidrnetlist *fp;
3522 for (fp = reply->host->fixed_prefix; fp != NULL;
3523 fp = fp->next) {
3524 reply->static_prefixes += 1;
3529 * Save the cursor position at the start of the IA_PD, so we can
3530 * set length and adjust t1/t2 values later. We write a temporary
3531 * header out now just in case we decide to adjust the packet
3532 * within sub-process functions.
3534 ia_cursor = reply->cursor;
3536 /* Initialize the IA_PD header. First the code. */
3537 putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_PD);
3538 reply->cursor += 2;
3540 /* Then option length. */
3541 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
3542 reply->cursor += 2;
3544 /* Then IA_PD header contents; IAID. */
3545 putULong(reply->buf.data + reply->cursor, iaid);
3546 reply->cursor += 4;
3548 /* We store the client's t1 for now, and may over-ride it later. */
3549 putULong(reply->buf.data + reply->cursor, reply->renew);
3550 reply->cursor += 4;
3552 /* We store the client's t2 for now, and may over-ride it later. */
3553 putULong(reply->buf.data + reply->cursor, reply->rebind);
3554 reply->cursor += 4;
3557 * For each prefix in this IA_PD, decide what to do about it.
3559 oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAPREFIX);
3560 reply->valid = reply->prefer = 0xffffffff;
3561 reply->client_valid = reply->client_prefer = 0;
3562 reply->preflen = -1;
3563 for (; oc != NULL ; oc = oc->next) {
3564 status = reply_process_prefix(reply, oc);
3567 * Canceled means we did not allocate prefixes to the
3568 * client, but we're "done" with this IA - we set a status
3569 * code. So transmit this reply, e.g., move on to the next
3570 * IA.
3572 if (status == ISC_R_CANCELED)
3573 break;
3575 if ((status != ISC_R_SUCCESS) &&
3576 (status != ISC_R_ADDRINUSE) &&
3577 (status != ISC_R_ADDRNOTAVAIL))
3578 goto cleanup;
3581 reply->pd_count++;
3584 * If we fell through the above and never gave the client
3585 * a prefix, give it one now.
3587 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
3588 status = find_client_prefix(reply);
3590 if (status == ISC_R_NORESOURCES) {
3591 switch (reply->packet->dhcpv6_msg_type) {
3592 case DHCPV6_SOLICIT:
3594 * No prefix for any IA is handled
3595 * by the caller.
3597 /* FALL THROUGH */
3599 case DHCPV6_REQUEST:
3600 /* Same than for addresses. */
3601 option_state_dereference(&reply->reply_ia, MDL);
3602 if (!option_state_allocate(&reply->reply_ia,
3603 MDL))
3605 log_error("reply_process_ia_pd: No "
3606 "memory for option state "
3607 "wipe.");
3608 status = ISC_R_NOMEMORY;
3609 goto cleanup;
3612 if (!set_status_code(STATUS_NoPrefixAvail,
3613 "No prefixes available "
3614 "for this interface.",
3615 reply->reply_ia)) {
3616 log_error("reply_process_ia_pd: "
3617 "Unable to set "
3618 "NoPrefixAvail status "
3619 "code.");
3620 status = ISC_R_FAILURE;
3621 goto cleanup;
3624 status = ISC_R_SUCCESS;
3625 break;
3627 default:
3628 if (reply->resources_included)
3629 status = ISC_R_SUCCESS;
3630 else
3631 goto cleanup;
3632 break;
3636 if (status != ISC_R_SUCCESS)
3637 goto cleanup;
3640 reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
3641 sizeof(reply->buf) - reply->cursor,
3642 reply->reply_ia, reply->packet,
3643 required_opts_IA_PD, NULL);
3645 /* Reset the length of this IA_PD to match what was just written. */
3646 putUShort(reply->buf.data + ia_cursor + 2,
3647 reply->cursor - (ia_cursor + 4));
3650 * T1/T2 time selection is kind of weird. We actually use DHCP
3651 * (v4) scoped options as handy existing places where these might
3652 * be configured by an administrator. A value of zero tells the
3653 * client it may choose its own renewal time.
3655 reply->renew = 0;
3656 oc = lookup_option(&dhcp_universe, reply->opt_state,
3657 DHO_DHCP_RENEWAL_TIME);
3658 if (oc != NULL) {
3659 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
3660 reply->packet->options,
3661 reply->opt_state, &global_scope,
3662 oc, MDL) ||
3663 (data.len != 4)) {
3664 log_error("Invalid renewal time.");
3665 } else {
3666 reply->renew = getULong(data.data);
3669 if (data.data != NULL)
3670 data_string_forget(&data, MDL);
3672 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
3674 /* Now T2. */
3675 reply->rebind = 0;
3676 oc = lookup_option(&dhcp_universe, reply->opt_state,
3677 DHO_DHCP_REBINDING_TIME);
3678 if (oc != NULL) {
3679 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
3680 reply->packet->options,
3681 reply->opt_state, &global_scope,
3682 oc, MDL) ||
3683 (data.len != 4)) {
3684 log_error("Invalid rebinding time.");
3685 } else {
3686 reply->rebind = getULong(data.data);
3689 if (data.data != NULL)
3690 data_string_forget(&data, MDL);
3692 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
3695 * yes, goto's aren't the best but we also want to avoid extra
3696 * indents
3698 if (status == ISC_R_CANCELED)
3699 goto cleanup;
3702 * Handle static prefixes, we always log stuff and if it's
3703 * a hard binding we run any commit statements that we have
3705 if (reply->static_prefixes != 0) {
3706 char tmp_addr[INET6_ADDRSTRLEN];
3707 log_info("%s PD: address %s/%d to client with duid %s "
3708 "iaid = %d static",
3709 dhcpv6_type_names[reply->buf.reply.msg_type],
3710 inet_ntop(AF_INET6, reply->fixed_pref.lo_addr.iabuf,
3711 tmp_addr, sizeof(tmp_addr)),
3712 reply->fixed_pref.bits,
3713 print_hex_1(reply->client_id.len,
3714 reply->client_id.data, 60),
3715 iaid);
3716 if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
3717 (reply->on_star.on_commit != NULL)) {
3718 execute_statements(NULL, reply->packet, NULL, NULL,
3719 reply->packet->options,
3720 reply->opt_state,
3721 NULL, reply->on_star.on_commit,
3722 NULL);
3723 executable_statement_dereference
3724 (&reply->on_star.on_commit, MDL);
3726 goto cleanup;
3730 * If we have any addresses log what we are doing.
3732 if (reply->ia->num_iasubopt != 0) {
3733 struct iasubopt *tmp;
3734 int i;
3735 char tmp_addr[INET6_ADDRSTRLEN];
3737 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3738 tmp = reply->ia->iasubopt[i];
3740 log_info("%s PD: address %s/%d to client with duid %s"
3741 " iaid = %d valid for %d seconds",
3742 dhcpv6_type_names[reply->buf.reply.msg_type],
3743 inet_ntop(AF_INET6, &tmp->addr,
3744 tmp_addr, sizeof(tmp_addr)),
3745 (int)tmp->plen,
3746 print_hex_1(reply->client_id.len,
3747 reply->client_id.data, 60),
3748 iaid, tmp->valid);
3753 * If this is not a 'soft' binding, consume the new changes into
3754 * the database (if any have been attached to the ia_pd).
3756 * Loop through the assigned dynamic prefixes, referencing the
3757 * prefixes onto this IA_PD rather than any old ones, and updating
3758 * prefix pool timers for each (if any).
3760 if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
3761 (reply->ia->num_iasubopt != 0)) {
3762 struct iasubopt *tmp;
3763 struct data_string *ia_id;
3764 int i;
3766 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3767 tmp = reply->ia->iasubopt[i];
3769 if (tmp->ia != NULL)
3770 ia_dereference(&tmp->ia, MDL);
3771 ia_reference(&tmp->ia, reply->ia, MDL);
3773 /* Commit 'hard' bindings. */
3774 renew_lease6(tmp->ipv6_pool, tmp);
3775 schedule_lease_timeout(tmp->ipv6_pool);
3777 /* If we have anything to do on commit do it now */
3778 if (tmp->on_star.on_commit != NULL) {
3779 execute_statements(NULL, reply->packet,
3780 NULL, NULL,
3781 reply->packet->options,
3782 reply->opt_state,
3783 &tmp->scope,
3784 tmp->on_star.on_commit,
3785 &tmp->on_star);
3786 executable_statement_dereference
3787 (&tmp->on_star.on_commit, MDL);
3791 /* Remove any old ia from the hash. */
3792 if (reply->old_ia != NULL) {
3793 ia_id = &reply->old_ia->iaid_duid;
3794 ia_hash_delete(ia_pd_active,
3795 (unsigned char *)ia_id->data,
3796 ia_id->len, MDL);
3797 ia_dereference(&reply->old_ia, MDL);
3800 /* Put new ia into the hash. */
3801 reply->ia->cltt = cur_time;
3802 ia_id = &reply->ia->iaid_duid;
3803 ia_hash_add(ia_pd_active, (unsigned char *)ia_id->data,
3804 ia_id->len, reply->ia, MDL);
3806 write_ia(reply->ia);
3809 cleanup:
3810 if (packet_ia != NULL)
3811 option_state_dereference(&packet_ia, MDL);
3812 if (reply->reply_ia != NULL)
3813 option_state_dereference(&reply->reply_ia, MDL);
3814 if (ia_data.data != NULL)
3815 data_string_forget(&ia_data, MDL);
3816 if (data.data != NULL)
3817 data_string_forget(&data, MDL);
3818 if (reply->ia != NULL)
3819 ia_dereference(&reply->ia, MDL);
3820 if (reply->old_ia != NULL)
3821 ia_dereference(&reply->old_ia, MDL);
3822 if (reply->lease != NULL)
3823 iasubopt_dereference(&reply->lease, MDL);
3824 if (reply->on_star.on_expiry != NULL)
3825 executable_statement_dereference
3826 (&reply->on_star.on_expiry, MDL);
3827 if (reply->on_star.on_release != NULL)
3828 executable_statement_dereference
3829 (&reply->on_star.on_release, MDL);
3832 * ISC_R_CANCELED is a status code used by the prefix processing to
3833 * indicate we're replying with a status code. This is still a
3834 * success at higher layers.
3836 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
3840 * Process an IAPREFIX within a given IA_PD, storing any IAPREFIX reply
3841 * contents into the reply's current ia_pd-scoped option cache. Returns
3842 * ISC_R_CANCELED in the event we are replying with a status code and do
3843 * not wish to process more IAPREFIXes within this IA_PD.
3845 static isc_result_t
3846 reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
3847 u_int32_t pref_life, valid_life;
3848 struct binding_scope **scope;
3849 struct iaddrcidrnet tmp_pref;
3850 struct option_cache *oc;
3851 struct data_string iapref, data;
3852 isc_result_t status = ISC_R_SUCCESS;
3853 struct group *group;
3855 /* Initializes values that will be cleaned up. */
3856 memset(&iapref, 0, sizeof(iapref));
3857 memset(&data, 0, sizeof(data));
3858 /* Note that reply->lease may be set by prefix_is_owned() */
3861 * There is no point trying to process an incoming prefix if there
3862 * is no room for an outgoing prefix.
3864 if ((reply->cursor + 29) > sizeof(reply->buf)) {
3865 log_error("reply_process_prefix: Out of room for prefix.");
3866 return ISC_R_NOSPACE;
3869 /* Extract this IAPREFIX option. */
3870 if (!evaluate_option_cache(&iapref, reply->packet, NULL, NULL,
3871 reply->packet->options, NULL, &global_scope,
3872 pref, MDL) ||
3873 (iapref.len < IAPREFIX_OFFSET)) {
3874 log_error("reply_process_prefix: error evaluating IAPREFIX.");
3875 status = ISC_R_FAILURE;
3876 goto cleanup;
3880 * Layout: preferred and valid lifetimes followed by the prefix
3881 * length and the IPv6 address.
3883 pref_life = getULong(iapref.data);
3884 valid_life = getULong(iapref.data + 4);
3886 if ((reply->client_valid == 0) ||
3887 (reply->client_valid > valid_life))
3888 reply->client_valid = valid_life;
3890 if ((reply->client_prefer == 0) ||
3891 (reply->client_prefer > pref_life))
3892 reply->client_prefer = pref_life;
3895 * Clients may choose to send ::/0 as a prefix, with the idea to give
3896 * hints about preferred-lifetime or valid-lifetime.
3898 tmp_pref.lo_addr.len = 16;
3899 memset(tmp_pref.lo_addr.iabuf, 0, 16);
3900 if ((iapref.data[8] == 0) &&
3901 (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
3902 /* Status remains success; we just ignore this one. */
3903 goto cleanup;
3907 * Clients may choose to send ::/X as a prefix to specify a
3908 * preferred/requested prefix length. Note X is never zero here.
3910 tmp_pref.bits = (int) iapref.data[8];
3911 if (reply->preflen < 0) {
3912 /* Cache the first preferred prefix length. */
3913 reply->preflen = tmp_pref.bits;
3915 if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
3916 goto cleanup;
3919 memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
3921 /* Verify the prefix belongs to the client. */
3922 if (!prefix_is_owned(reply, &tmp_pref)) {
3923 /* Same than for addresses. */
3924 if ((reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) ||
3925 (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) ||
3926 (reply->packet->dhcpv6_msg_type == DHCPV6_REBIND)) {
3927 status = reply_process_try_prefix(reply, &tmp_pref);
3929 /* Either error out or skip this prefix. */
3930 if ((status != ISC_R_SUCCESS) &&
3931 (status != ISC_R_ADDRINUSE) &&
3932 (status != ISC_R_ADDRNOTAVAIL))
3933 goto cleanup;
3935 if (reply->lease == NULL) {
3936 if (reply->packet->dhcpv6_msg_type ==
3937 DHCPV6_REBIND) {
3938 reply->send_prefer = 0;
3939 reply->send_valid = 0;
3940 goto send_pref;
3943 /* status remains success - ignore */
3944 goto cleanup;
3947 * RFC3633 section 18.2.3:
3949 * If the delegating router cannot find a binding
3950 * for the requesting router's IA_PD the delegating
3951 * router returns the IA_PD containing no prefixes
3952 * with a Status Code option set to NoBinding in the
3953 * Reply message.
3955 * On mismatch we (ab)use this pretending we have not the IA
3956 * as soon as we have not a prefix.
3958 } else if (reply->packet->dhcpv6_msg_type == DHCPV6_RENEW) {
3959 /* Rewind the IA_PD to empty. */
3960 option_state_dereference(&reply->reply_ia, MDL);
3961 if (!option_state_allocate(&reply->reply_ia, MDL)) {
3962 log_error("reply_process_prefix: No memory "
3963 "for option state wipe.");
3964 status = ISC_R_NOMEMORY;
3965 goto cleanup;
3968 /* Append a NoBinding status code. */
3969 if (!set_status_code(STATUS_NoBinding,
3970 "Prefix not bound to this "
3971 "interface.", reply->reply_ia)) {
3972 log_error("reply_process_prefix: Unable to "
3973 "attach status code.");
3974 status = ISC_R_FAILURE;
3975 goto cleanup;
3978 /* Fin (no more IAPREFIXes). */
3979 status = ISC_R_CANCELED;
3980 goto cleanup;
3981 } else {
3982 log_error("It is impossible to lease a client that is "
3983 "not sending a solicit, request, renew, or "
3984 "rebind message.");
3985 status = ISC_R_FAILURE;
3986 goto cleanup;
3990 if (reply->static_prefixes > 0) {
3991 if (reply->host == NULL)
3992 log_fatal("Impossible condition at %s:%d.", MDL);
3994 scope = &global_scope;
3996 /* Find the static prefixe's subnet. */
3997 if (find_grouped_subnet(&reply->subnet, reply->shared,
3998 tmp_pref.lo_addr, MDL) == 0)
3999 log_fatal("Impossible condition at %s:%d.", MDL);
4000 group = reply->subnet->group;
4001 subnet_dereference(&reply->subnet, MDL);
4003 /* Copy the static prefix for logging purposes */
4004 memcpy(&reply->fixed_pref, &tmp_pref, sizeof(tmp_pref));
4005 } else {
4006 if (reply->lease == NULL)
4007 log_fatal("Impossible condition at %s:%d.", MDL);
4009 scope = &reply->lease->scope;
4010 group = reply->lease->ipv6_pool->ipv6_pond->group;
4014 * If client_resources is nonzero, then the reply_process_is_prefixed
4015 * function has executed configuration state into the reply option
4016 * cache. We will use that valid cache to derive configuration for
4017 * whether or not to engage in additional prefixes, and similar.
4019 if (reply->client_resources != 0) {
4020 unsigned limit = 1;
4023 * Does this client have "enough" prefixes already? Default
4024 * to one. Everybody gets one, and one should be enough for
4025 * anybody.
4027 oc = lookup_option(&server_universe, reply->opt_state,
4028 SV_LIMIT_PREFS_PER_IA);
4029 if (oc != NULL) {
4030 if (!evaluate_option_cache(&data, reply->packet,
4031 NULL, NULL,
4032 reply->packet->options,
4033 reply->opt_state,
4034 scope, oc, MDL) ||
4035 (data.len != 4)) {
4036 log_error("reply_process_prefix: unable to "
4037 "evaluate prefs-per-ia value.");
4038 status = ISC_R_FAILURE;
4039 goto cleanup;
4042 limit = getULong(data.data);
4043 data_string_forget(&data, MDL);
4047 * If we wish to limit the client to a certain number of
4048 * prefixes, then omit the prefix from the reply.
4050 if (reply->client_resources >= limit)
4051 goto cleanup;
4054 status = reply_process_is_prefixed(reply, scope, group);
4055 if (status != ISC_R_SUCCESS)
4056 goto cleanup;
4058 send_pref:
4059 status = reply_process_send_prefix(reply, &tmp_pref);
4061 cleanup:
4062 if (iapref.data != NULL)
4063 data_string_forget(&iapref, MDL);
4064 if (data.data != NULL)
4065 data_string_forget(&data, MDL);
4066 if (reply->lease != NULL)
4067 iasubopt_dereference(&reply->lease, MDL);
4069 return status;
4073 * Verify the prefix belongs to the client. If we've got a host
4074 * record with fixed prefixes, it has to be an assigned prefix
4075 * (fault out all else). Otherwise it's a dynamic prefix, so lookup
4076 * that prefix and make sure it belongs to this DUID:IAID pair.
4078 static isc_boolean_t
4079 prefix_is_owned(struct reply_state *reply, struct iaddrcidrnet *pref) {
4080 struct iaddrcidrnetlist *l;
4081 int i;
4082 struct ipv6_pond *pond;
4085 * This faults out prefixes that don't match fixed prefixes.
4087 if (reply->static_prefixes > 0) {
4088 for (l = reply->host->fixed_prefix; l != NULL; l = l->next) {
4089 if ((pref->bits == l->cidrnet.bits) &&
4090 (memcmp(pref->lo_addr.iabuf,
4091 l->cidrnet.lo_addr.iabuf, 16) == 0))
4092 return (ISC_TRUE);
4094 return (ISC_FALSE);
4097 if ((reply->old_ia == NULL) ||
4098 (reply->old_ia->num_iasubopt == 0))
4099 return (ISC_FALSE);
4101 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4102 struct iasubopt *tmp;
4104 tmp = reply->old_ia->iasubopt[i];
4106 if ((pref->bits == (int) tmp->plen) &&
4107 (memcmp(pref->lo_addr.iabuf, &tmp->addr, 16) == 0)) {
4108 if (lease6_usable(tmp) == ISC_FALSE) {
4109 return (ISC_FALSE);
4112 pond = tmp->ipv6_pool->ipv6_pond;
4113 if (((pond->prohibit_list != NULL) &&
4114 (permitted(reply->packet, pond->prohibit_list))) ||
4115 ((pond->permit_list != NULL) &&
4116 (!permitted(reply->packet, pond->permit_list))))
4117 return (ISC_FALSE);
4119 iasubopt_reference(&reply->lease, tmp, MDL);
4120 return (ISC_TRUE);
4124 return (ISC_FALSE);
4128 * This function only returns failure on 'hard' failures. If it succeeds,
4129 * it will leave a prefix structure behind.
4131 static isc_result_t
4132 reply_process_try_prefix(struct reply_state *reply,
4133 struct iaddrcidrnet *pref) {
4134 isc_result_t status = ISC_R_ADDRNOTAVAIL;
4135 struct ipv6_pool *pool = NULL;
4136 struct ipv6_pond *pond = NULL;
4137 int i;
4138 struct data_string data_pref;
4140 if ((reply == NULL) || (reply->shared == NULL) ||
4141 (pref == NULL) || (reply->lease != NULL))
4142 return (DHCP_R_INVALIDARG);
4145 * Do a quick walk through of the ponds and pools
4146 * to see if we have any prefix pools
4148 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
4149 if (pond->ipv6_pools == NULL)
4150 continue;
4152 for (i = 0; (pool = pond->ipv6_pools[i]) != NULL; i++) {
4153 if (pool->pool_type == D6O_IA_PD)
4154 break;
4156 if (pool != NULL)
4157 break;
4160 /* If we get here and p is NULL we have no useful pools */
4161 if (pool == NULL) {
4162 return (ISC_R_ADDRNOTAVAIL);
4165 memset(&data_pref, 0, sizeof(data_pref));
4166 data_pref.len = 17;
4167 if (!buffer_allocate(&data_pref.buffer, data_pref.len, MDL)) {
4168 log_error("reply_process_try_prefix: out of memory.");
4169 return (ISC_R_NOMEMORY);
4171 data_pref.data = data_pref.buffer->data;
4172 data_pref.buffer->data[0] = (u_int8_t) pref->bits;
4173 memcpy(data_pref.buffer->data + 1, pref->lo_addr.iabuf, 16);
4176 * We have at least one pool that could provide a prefix
4177 * Now we walk through the ponds and pools again and check
4178 * to see if the client is permitted and if an prefix is
4179 * available
4183 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
4184 if (((pond->prohibit_list != NULL) &&
4185 (permitted(reply->packet, pond->prohibit_list))) ||
4186 ((pond->permit_list != NULL) &&
4187 (!permitted(reply->packet, pond->permit_list))))
4188 continue;
4190 for (i = 0; (pool = pond->ipv6_pools[i]) != NULL; i++) {
4191 if (pool->pool_type != D6O_IA_PD) {
4192 continue;
4195 status = try_client_v6_prefix(&reply->lease, pool,
4196 &data_pref);
4197 /* If we found it in this pool (either in use or available),
4198 there is no need to look further. */
4199 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4200 break;
4202 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4203 break;
4206 data_string_forget(&data_pref, MDL);
4207 /* Return just the most recent status... */
4208 return (status);
4211 /* Look around for a prefix to give the client. First, look through the old
4212 * IA_PD for prefixes we can extend. Second, try to allocate a new prefix.
4213 * Finally, actually add that prefix into the current reply IA_PD.
4215 static isc_result_t
4216 find_client_prefix(struct reply_state *reply) {
4217 struct iaddrcidrnet send_pref;
4218 isc_result_t status = ISC_R_NORESOURCES;
4219 struct iasubopt *prefix, *best_prefix = NULL;
4220 struct binding_scope **scope;
4221 int i;
4222 struct group *group;
4224 if (reply->static_prefixes > 0) {
4225 struct iaddrcidrnetlist *l;
4227 if (reply->host == NULL)
4228 return DHCP_R_INVALIDARG;
4230 for (l = reply->host->fixed_prefix; l != NULL; l = l->next) {
4231 if (l->cidrnet.bits == reply->preflen)
4232 break;
4234 if (l == NULL) {
4236 * If no fixed prefix has the preferred length,
4237 * get the first one.
4239 l = reply->host->fixed_prefix;
4241 memcpy(&send_pref, &l->cidrnet, sizeof(send_pref));
4243 scope = &global_scope;
4245 /* Find the static prefixe's subnet. */
4246 if (find_grouped_subnet(&reply->subnet, reply->shared,
4247 send_pref.lo_addr, MDL) == 0)
4248 log_fatal("Impossible condition at %s:%d.", MDL);
4249 group = reply->subnet->group;
4250 subnet_dereference(&reply->subnet, MDL);
4252 /* Copy the prefix for logging purposes */
4253 memcpy(&reply->fixed_pref, &l->cidrnet, sizeof(send_pref));
4255 goto send_pref;
4258 if (reply->old_ia != NULL) {
4259 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4260 struct shared_network *candidate_shared;
4261 struct ipv6_pond *pond;
4263 prefix = reply->old_ia->iasubopt[i];
4264 candidate_shared = prefix->ipv6_pool->shared_network;
4265 pond = prefix->ipv6_pool->ipv6_pond;
4268 * Consider this prefix if it is in a global pool or
4269 * if it is scoped in a pool under the client's shared
4270 * network.
4272 if (((candidate_shared != NULL) &&
4273 (candidate_shared != reply->shared)) ||
4274 (lease6_usable(prefix) != ISC_TRUE))
4275 continue;
4278 * And check if the prefix is still permitted
4281 if (((pond->prohibit_list != NULL) &&
4282 (permitted(reply->packet, pond->prohibit_list))) ||
4283 ((pond->permit_list != NULL) &&
4284 (!permitted(reply->packet, pond->permit_list))))
4285 continue;
4287 best_prefix = prefix_compare(reply, prefix,
4288 best_prefix);
4292 /* Try to pick a new prefix if we didn't find one, or if we found an
4293 * abandoned prefix.
4295 if ((best_prefix == NULL) || (best_prefix->state == FTS_ABANDONED)) {
4296 status = pick_v6_prefix(reply);
4297 } else if (best_prefix != NULL) {
4298 iasubopt_reference(&reply->lease, best_prefix, MDL);
4299 status = ISC_R_SUCCESS;
4302 /* Pick the abandoned prefix as a last resort. */
4303 if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
4304 /* I don't see how this is supposed to be done right now. */
4305 log_error("Reclaiming abandoned prefixes is not yet "
4306 "supported. Treating this as an out of space "
4307 "condition.");
4308 /* iasubopt_reference(&reply->lease, best_prefix, MDL); */
4311 /* Give up now if we didn't find a prefix. */
4312 if (status != ISC_R_SUCCESS)
4313 return status;
4315 if (reply->lease == NULL)
4316 log_fatal("Impossible condition at %s:%d.", MDL);
4318 scope = &reply->lease->scope;
4319 group = reply->lease->ipv6_pool->ipv6_pond->group;
4321 send_pref.lo_addr.len = 16;
4322 memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
4323 send_pref.bits = (int) reply->lease->plen;
4325 send_pref:
4326 status = reply_process_is_prefixed(reply, scope, group);
4327 if (status != ISC_R_SUCCESS)
4328 return status;
4330 status = reply_process_send_prefix(reply, &send_pref);
4331 return status;
4334 /* Once a prefix is found for a client, perform several common functions;
4335 * Calculate and store valid and preferred prefix times, draw client options
4336 * into the option state.
4338 static isc_result_t
4339 reply_process_is_prefixed(struct reply_state *reply,
4340 struct binding_scope **scope, struct group *group)
4342 isc_result_t status = ISC_R_SUCCESS;
4343 struct data_string data;
4344 struct option_cache *oc;
4345 struct option_state *tmp_options = NULL;
4346 struct on_star *on_star;
4347 int i;
4349 /* Initialize values we will cleanup. */
4350 memset(&data, 0, sizeof(data));
4353 * Find the proper on_star block to use. We use the
4354 * one in the lease if we have a lease or the one in
4355 * the reply if we don't have a lease because this is
4356 * a static instance
4358 if (reply->lease) {
4359 on_star = &reply->lease->on_star;
4360 } else {
4361 on_star = &reply->on_star;
4365 * Bring in the root configuration. We only do this to bring
4366 * in the on * statements, as we didn't have the lease available
4367 * we we did it the first time.
4369 option_state_allocate(&tmp_options, MDL);
4370 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4371 reply->packet->options, tmp_options,
4372 &global_scope, root_group, NULL,
4373 on_star);
4374 if (tmp_options != NULL) {
4375 option_state_dereference(&tmp_options, MDL);
4379 * Bring configured options into the root packet level cache - start
4380 * with the lease's closest enclosing group (passed in by the caller
4381 * as 'group').
4383 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4384 reply->packet->options, reply->opt_state,
4385 scope, group, root_group, on_star);
4387 /* Execute statements from class scopes. */
4388 for (i = reply->packet->class_count; i > 0; i--) {
4389 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4390 reply->packet->options,
4391 reply->opt_state, scope,
4392 reply->packet->classes[i - 1]->group,
4393 group, on_star);
4397 * If there is a host record, over-ride with values configured there,
4398 * without re-evaluating configuration from the previously executed
4399 * group or its common enclosers.
4401 if (reply->host != NULL)
4402 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4403 reply->packet->options,
4404 reply->opt_state, scope,
4405 reply->host->group, group,
4406 on_star);
4408 /* Determine valid lifetime. */
4409 if (reply->client_valid == 0)
4410 reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
4411 else
4412 reply->send_valid = reply->client_valid;
4414 oc = lookup_option(&server_universe, reply->opt_state,
4415 SV_DEFAULT_LEASE_TIME);
4416 if (oc != NULL) {
4417 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
4418 reply->packet->options,
4419 reply->opt_state,
4420 scope, oc, MDL) ||
4421 (data.len != 4)) {
4422 log_error("reply_process_is_prefixed: unable to "
4423 "evaluate default prefix time");
4424 status = ISC_R_FAILURE;
4425 goto cleanup;
4428 reply->send_valid = getULong(data.data);
4429 data_string_forget(&data, MDL);
4432 if (reply->client_prefer == 0)
4433 reply->send_prefer = reply->send_valid;
4434 else
4435 reply->send_prefer = reply->client_prefer;
4437 if (reply->send_prefer >= reply->send_valid)
4438 reply->send_prefer = (reply->send_valid / 2) +
4439 (reply->send_valid / 8);
4441 oc = lookup_option(&server_universe, reply->opt_state,
4442 SV_PREFER_LIFETIME);
4443 if (oc != NULL) {
4444 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
4445 reply->packet->options,
4446 reply->opt_state,
4447 scope, oc, MDL) ||
4448 (data.len != 4)) {
4449 log_error("reply_process_is_prefixed: unable to "
4450 "evaluate preferred prefix time");
4451 status = ISC_R_FAILURE;
4452 goto cleanup;
4455 reply->send_prefer = getULong(data.data);
4456 data_string_forget(&data, MDL);
4459 /* Note lowest values for later calculation of renew/rebind times. */
4460 if (reply->prefer > reply->send_prefer)
4461 reply->prefer = reply->send_prefer;
4463 if (reply->valid > reply->send_valid)
4464 reply->valid = reply->send_valid;
4466 /* Perform dynamic prefix related update work. */
4467 if (reply->lease != NULL) {
4468 /* Cached lifetimes */
4469 reply->lease->prefer = reply->send_prefer;
4470 reply->lease->valid = reply->send_valid;
4472 /* Advance (or rewind) the valid lifetime. */
4473 if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
4474 reply->lease->soft_lifetime_end_time =
4475 cur_time + reply->send_valid;
4476 /* Wait before renew! */
4479 status = ia_add_iasubopt(reply->ia, reply->lease, MDL);
4480 if (status != ISC_R_SUCCESS) {
4481 log_fatal("reply_process_is_prefixed: Unable to "
4482 "attach prefix to new IA_PD: %s",
4483 isc_result_totext(status));
4487 * If this is a new prefix, make sure it is attached somewhere.
4489 if (reply->lease->ia == NULL) {
4490 ia_reference(&reply->lease->ia, reply->ia, MDL);
4494 /* Bring a copy of the relevant options into the IA_PD scope. */
4495 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4496 reply->packet->options, reply->reply_ia,
4497 scope, group, root_group, NULL);
4499 /* Execute statements from class scopes. */
4500 for (i = reply->packet->class_count; i > 0; i--) {
4501 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4502 reply->packet->options,
4503 reply->reply_ia, scope,
4504 reply->packet->classes[i - 1]->group,
4505 group, NULL);
4509 * And bring in host record configuration, if any, but not to overlap
4510 * the previous group or its common enclosers.
4512 if (reply->host != NULL)
4513 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4514 reply->packet->options,
4515 reply->reply_ia, scope,
4516 reply->host->group, group, NULL);
4518 cleanup:
4519 if (data.data != NULL)
4520 data_string_forget(&data, MDL);
4522 if (status == ISC_R_SUCCESS)
4523 reply->client_resources++;
4525 return status;
4528 /* Simply send an IAPREFIX within the IA_PD scope as described. */
4529 static isc_result_t
4530 reply_process_send_prefix(struct reply_state *reply,
4531 struct iaddrcidrnet *pref) {
4532 isc_result_t status = ISC_R_SUCCESS;
4533 struct data_string data;
4535 memset(&data, 0, sizeof(data));
4537 /* Now append the prefix. */
4538 data.len = IAPREFIX_OFFSET;
4539 if (!buffer_allocate(&data.buffer, data.len, MDL)) {
4540 log_error("reply_process_send_prefix: out of memory"
4541 "allocating new IAPREFIX buffer.");
4542 status = ISC_R_NOMEMORY;
4543 goto cleanup;
4545 data.data = data.buffer->data;
4547 putULong(data.buffer->data, reply->send_prefer);
4548 putULong(data.buffer->data + 4, reply->send_valid);
4549 data.buffer->data[8] = pref->bits;
4550 memcpy(data.buffer->data + 9, pref->lo_addr.iabuf, 16);
4552 if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
4553 data.buffer, data.buffer->data,
4554 data.len, D6O_IAPREFIX, 0)) {
4555 log_error("reply_process_send_prefix: unable "
4556 "to save IAPREFIX option");
4557 status = ISC_R_FAILURE;
4558 goto cleanup;
4561 reply->resources_included = ISC_TRUE;
4563 cleanup:
4564 if (data.data != NULL)
4565 data_string_forget(&data, MDL);
4567 return status;
4570 /* Choose the better of two prefixes. */
4571 static struct iasubopt *
4572 prefix_compare(struct reply_state *reply,
4573 struct iasubopt *alpha, struct iasubopt *beta) {
4574 if (alpha == NULL)
4575 return beta;
4576 if (beta == NULL)
4577 return alpha;
4579 if (reply->preflen >= 0) {
4580 if ((alpha->plen == reply->preflen) &&
4581 (beta->plen != reply->preflen))
4582 return alpha;
4583 if ((beta->plen == reply->preflen) &&
4584 (alpha->plen != reply->preflen))
4585 return beta;
4588 switch(alpha->state) {
4589 case FTS_ACTIVE:
4590 switch(beta->state) {
4591 case FTS_ACTIVE:
4592 /* Choose the prefix with the longest lifetime (most
4593 * likely the most recently allocated).
4595 if (alpha->hard_lifetime_end_time <
4596 beta->hard_lifetime_end_time)
4597 return beta;
4598 else
4599 return alpha;
4601 case FTS_EXPIRED:
4602 case FTS_ABANDONED:
4603 return alpha;
4605 default:
4606 log_fatal("Impossible condition at %s:%d.", MDL);
4608 break;
4610 case FTS_EXPIRED:
4611 switch (beta->state) {
4612 case FTS_ACTIVE:
4613 return beta;
4615 case FTS_EXPIRED:
4616 /* Choose the most recently expired prefix. */
4617 if (alpha->hard_lifetime_end_time <
4618 beta->hard_lifetime_end_time)
4619 return beta;
4620 else if ((alpha->hard_lifetime_end_time ==
4621 beta->hard_lifetime_end_time) &&
4622 (alpha->soft_lifetime_end_time <
4623 beta->soft_lifetime_end_time))
4624 return beta;
4625 else
4626 return alpha;
4628 case FTS_ABANDONED:
4629 return alpha;
4631 default:
4632 log_fatal("Impossible condition at %s:%d.", MDL);
4634 break;
4636 case FTS_ABANDONED:
4637 switch (beta->state) {
4638 case FTS_ACTIVE:
4639 case FTS_EXPIRED:
4640 return alpha;
4642 case FTS_ABANDONED:
4643 /* Choose the prefix that was abandoned longest ago. */
4644 if (alpha->hard_lifetime_end_time <
4645 beta->hard_lifetime_end_time)
4646 return alpha;
4648 default:
4649 log_fatal("Impossible condition at %s:%d.", MDL);
4651 break;
4653 default:
4654 log_fatal("Impossible condition at %s:%d.", MDL);
4657 log_fatal("Triple impossible condition at %s:%d.", MDL);
4658 return NULL;
4662 * Solicit is how a client starts requesting addresses.
4664 * If the client asks for rapid commit, and we support it, we will
4665 * allocate the addresses and reply.
4667 * Otherwise we will send an advertise message.
4670 static void
4671 dhcpv6_solicit(struct data_string *reply_ret, struct packet *packet) {
4672 struct data_string client_id;
4675 * Validate our input.
4677 if (!valid_client_msg(packet, &client_id)) {
4678 return;
4681 lease_to_client(reply_ret, packet, &client_id, NULL);
4684 * Clean up.
4686 data_string_forget(&client_id, MDL);
4690 * Request is how a client actually requests addresses.
4692 * Very similar to Solicit handling, except the server DUID is required.
4695 /* TODO: reject unicast messages, unless we set unicast option */
4696 static void
4697 dhcpv6_request(struct data_string *reply_ret, struct packet *packet) {
4698 struct data_string client_id;
4699 struct data_string server_id;
4702 * Validate our input.
4704 if (!valid_client_resp(packet, &client_id, &server_id)) {
4705 return;
4709 * Issue our lease.
4711 lease_to_client(reply_ret, packet, &client_id, &server_id);
4714 * Cleanup.
4716 data_string_forget(&client_id, MDL);
4717 data_string_forget(&server_id, MDL);
4720 /* Find a DHCPv6 packet's shared network from hints in the packet.
4722 static isc_result_t
4723 shared_network_from_packet6(struct shared_network **shared,
4724 struct packet *packet)
4726 const struct packet *chk_packet;
4727 const struct in6_addr *link_addr, *first_link_addr;
4728 struct iaddr tmp_addr;
4729 struct subnet *subnet;
4730 isc_result_t status;
4732 if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
4733 return DHCP_R_INVALIDARG;
4736 * First, find the link address where the packet from the client
4737 * first appeared (if this packet was relayed).
4739 first_link_addr = NULL;
4740 chk_packet = packet->dhcpv6_container_packet;
4741 while (chk_packet != NULL) {
4742 link_addr = &chk_packet->dhcpv6_link_address;
4743 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
4744 !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
4745 first_link_addr = link_addr;
4746 break;
4748 chk_packet = chk_packet->dhcpv6_container_packet;
4752 * If there is a relayed link address, find the subnet associated
4753 * with that, and use that to get the appropriate
4754 * shared_network.
4756 if (first_link_addr != NULL) {
4757 tmp_addr.len = sizeof(*first_link_addr);
4758 memcpy(tmp_addr.iabuf,
4759 first_link_addr, sizeof(*first_link_addr));
4760 subnet = NULL;
4761 if (!find_subnet(&subnet, tmp_addr, MDL)) {
4762 log_debug("No subnet found for link-address %s.",
4763 piaddr(tmp_addr));
4764 return ISC_R_NOTFOUND;
4766 status = shared_network_reference(shared,
4767 subnet->shared_network, MDL);
4768 subnet_dereference(&subnet, MDL);
4771 * If there is no link address, we will use the interface
4772 * that this packet came in on to pick the shared_network.
4774 } else if (packet->interface != NULL) {
4775 status = shared_network_reference(shared,
4776 packet->interface->shared_network,
4777 MDL);
4778 if (packet->dhcpv6_container_packet != NULL) {
4779 log_info("[L2 Relay] No link address in relay packet "
4780 "assuming L2 relay and using receiving "
4781 "interface");
4784 } else {
4786 * We shouldn't be able to get here but if there is no link
4787 * address and no interface we don't know where to get the
4788 * pool from log an error and return an error.
4790 log_error("No interface and no link address "
4791 "can't determine pool");
4792 status = DHCP_R_INVALIDARG;
4795 return status;
4799 * When a client thinks it might be on a new link, it sends a
4800 * Confirm message.
4802 * From RFC3315 section 18.2.2:
4804 * When the server receives a Confirm message, the server determines
4805 * whether the addresses in the Confirm message are appropriate for the
4806 * link to which the client is attached. If all of the addresses in the
4807 * Confirm message pass this test, the server returns a status of
4808 * Success. If any of the addresses do not pass this test, the server
4809 * returns a status of NotOnLink. If the server is unable to perform
4810 * this test (for example, the server does not have information about
4811 * prefixes on the link to which the client is connected), or there were
4812 * no addresses in any of the IAs sent by the client, the server MUST
4813 * NOT send a reply to the client.
4816 static void
4817 dhcpv6_confirm(struct data_string *reply_ret, struct packet *packet) {
4818 struct shared_network *shared;
4819 struct subnet *subnet;
4820 struct option_cache *ia, *ta, *oc;
4821 struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
4822 struct option_state *cli_enc_opt_state, *opt_state;
4823 struct iaddr cli_addr;
4824 int pass;
4825 isc_boolean_t inappropriate, has_addrs;
4826 char reply_data[65536];
4827 struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
4828 int reply_ofs = (int)(offsetof(struct dhcpv6_packet, options));
4831 * Basic client message validation.
4833 memset(&client_id, 0, sizeof(client_id));
4834 if (!valid_client_msg(packet, &client_id)) {
4835 return;
4839 * Do not process Confirms that do not have IA's we do not recognize.
4841 ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
4842 ta = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
4843 if ((ia == NULL) && (ta == NULL))
4844 return;
4847 * IA_PD's are simply ignored.
4849 delete_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
4852 * Bit of variable initialization.
4854 opt_state = cli_enc_opt_state = NULL;
4855 memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
4856 memset(&iaaddr, 0, sizeof(iaaddr));
4857 memset(&packet_oro, 0, sizeof(packet_oro));
4859 /* Determine what shared network the client is connected to. We
4860 * must not respond if we don't have any information about the
4861 * network the client is on.
4863 shared = NULL;
4864 if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
4865 (shared == NULL))
4866 goto exit;
4868 /* If there are no recorded subnets, then we have no
4869 * information about this subnet - ignore Confirms.
4871 subnet = shared->subnets;
4872 if (subnet == NULL)
4873 goto exit;
4875 /* Are the addresses in all the IA's appropriate for that link? */
4876 has_addrs = inappropriate = ISC_FALSE;
4877 pass = D6O_IA_NA;
4878 while(!inappropriate) {
4879 /* If we've reached the end of the IA_NA pass, move to the
4880 * IA_TA pass.
4882 if ((pass == D6O_IA_NA) && (ia == NULL)) {
4883 pass = D6O_IA_TA;
4884 ia = ta;
4887 /* If we've reached the end of all passes, we're done. */
4888 if (ia == NULL)
4889 break;
4891 if (((pass == D6O_IA_NA) &&
4892 !get_encapsulated_IA_state(&cli_enc_opt_state,
4893 &cli_enc_opt_data,
4894 packet, ia, IA_NA_OFFSET)) ||
4895 ((pass == D6O_IA_TA) &&
4896 !get_encapsulated_IA_state(&cli_enc_opt_state,
4897 &cli_enc_opt_data,
4898 packet, ia, IA_TA_OFFSET))) {
4899 goto exit;
4902 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
4903 D6O_IAADDR);
4905 for ( ; oc != NULL ; oc = oc->next) {
4906 if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL,
4907 packet->options, NULL,
4908 &global_scope, oc, MDL) ||
4909 (iaaddr.len < IAADDR_OFFSET)) {
4910 log_error("dhcpv6_confirm: "
4911 "error evaluating IAADDR.");
4912 goto exit;
4915 /* Copy out the IPv6 address for processing. */
4916 cli_addr.len = 16;
4917 memcpy(cli_addr.iabuf, iaaddr.data, 16);
4919 data_string_forget(&iaaddr, MDL);
4921 /* Record that we've processed at least one address. */
4922 has_addrs = ISC_TRUE;
4924 /* Find out if any subnets cover this address. */
4925 for (subnet = shared->subnets ; subnet != NULL ;
4926 subnet = subnet->next_sibling) {
4927 if (addr_eq(subnet_number(cli_addr,
4928 subnet->netmask),
4929 subnet->net))
4930 break;
4933 /* If we reach the end of the subnet list, and no
4934 * subnet matches the client address, then it must
4935 * be inappropriate to the link (so far as our
4936 * configuration says). Once we've found one
4937 * inappropriate address, there is no reason to
4938 * continue searching.
4940 if (subnet == NULL) {
4941 inappropriate = ISC_TRUE;
4942 break;
4946 option_state_dereference(&cli_enc_opt_state, MDL);
4947 data_string_forget(&cli_enc_opt_data, MDL);
4949 /* Advance to the next IA_*. */
4950 ia = ia->next;
4953 /* If the client supplied no addresses, do not reply. */
4954 if (!has_addrs)
4955 goto exit;
4958 * Set up reply.
4960 if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
4961 goto exit;
4965 * Set our status.
4967 if (inappropriate) {
4968 if (!set_status_code(STATUS_NotOnLink,
4969 "Some of the addresses are not on link.",
4970 opt_state)) {
4971 goto exit;
4973 } else {
4974 if (!set_status_code(STATUS_Success,
4975 "All addresses still on link.",
4976 opt_state)) {
4977 goto exit;
4982 * Only one option: add it.
4984 reply_ofs += store_options6(reply_data+reply_ofs,
4985 sizeof(reply_data)-reply_ofs,
4986 opt_state, packet,
4987 required_opts, &packet_oro);
4990 * Return our reply to the caller.
4992 reply_ret->len = reply_ofs;
4993 reply_ret->buffer = NULL;
4994 if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
4995 log_fatal("No memory to store reply.");
4997 reply_ret->data = reply_ret->buffer->data;
4998 memcpy(reply_ret->buffer->data, reply, reply_ofs);
5000 exit:
5001 /* Cleanup any stale data strings. */
5002 if (cli_enc_opt_data.buffer != NULL)
5003 data_string_forget(&cli_enc_opt_data, MDL);
5004 if (iaaddr.buffer != NULL)
5005 data_string_forget(&iaaddr, MDL);
5006 if (client_id.buffer != NULL)
5007 data_string_forget(&client_id, MDL);
5008 if (packet_oro.buffer != NULL)
5009 data_string_forget(&packet_oro, MDL);
5011 /* Release any stale option states. */
5012 if (cli_enc_opt_state != NULL)
5013 option_state_dereference(&cli_enc_opt_state, MDL);
5014 if (opt_state != NULL)
5015 option_state_dereference(&opt_state, MDL);
5019 * Renew is when a client wants to extend its lease/prefix, at time T1.
5021 * We handle this the same as if the client wants a new lease/prefix,
5022 * except for the error code of when addresses don't match.
5025 /* TODO: reject unicast messages, unless we set unicast option */
5026 static void
5027 dhcpv6_renew(struct data_string *reply, struct packet *packet) {
5028 struct data_string client_id;
5029 struct data_string server_id;
5032 * Validate the request.
5034 if (!valid_client_resp(packet, &client_id, &server_id)) {
5035 return;
5039 * Renew our lease.
5041 lease_to_client(reply, packet, &client_id, &server_id);
5044 * Cleanup.
5046 data_string_forget(&server_id, MDL);
5047 data_string_forget(&client_id, MDL);
5051 * Rebind is when a client wants to extend its lease, at time T2.
5053 * We handle this the same as if the client wants a new lease, except
5054 * for the error code of when addresses don't match.
5057 static void
5058 dhcpv6_rebind(struct data_string *reply, struct packet *packet) {
5059 struct data_string client_id;
5061 if (!valid_client_msg(packet, &client_id)) {
5062 return;
5065 lease_to_client(reply, packet, &client_id, NULL);
5067 data_string_forget(&client_id, MDL);
5070 static void
5071 ia_na_match_decline(const struct data_string *client_id,
5072 const struct data_string *iaaddr,
5073 struct iasubopt *lease)
5075 char tmp_addr[INET6_ADDRSTRLEN];
5077 log_error("Client %s reports address %s is "
5078 "already in use by another host!",
5079 print_hex_1(client_id->len, client_id->data, 60),
5080 inet_ntop(AF_INET6, iaaddr->data,
5081 tmp_addr, sizeof(tmp_addr)));
5082 if (lease != NULL) {
5083 decline_lease6(lease->ipv6_pool, lease);
5084 lease->ia->cltt = cur_time;
5085 write_ia(lease->ia);
5089 static void
5090 ia_na_nomatch_decline(const struct data_string *client_id,
5091 const struct data_string *iaaddr,
5092 u_int32_t *ia_na_id,
5093 struct packet *packet,
5094 char *reply_data,
5095 int *reply_ofs,
5096 int reply_len)
5098 char tmp_addr[INET6_ADDRSTRLEN];
5099 struct option_state *host_opt_state;
5100 int len;
5102 log_info("Client %s declines address %s, which is not offered to it.",
5103 print_hex_1(client_id->len, client_id->data, 60),
5104 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
5107 * Create state for this IA_NA.
5109 host_opt_state = NULL;
5110 if (!option_state_allocate(&host_opt_state, MDL)) {
5111 log_error("ia_na_nomatch_decline: out of memory "
5112 "allocating option_state.");
5113 goto exit;
5116 if (!set_status_code(STATUS_NoBinding, "Decline for unknown address.",
5117 host_opt_state)) {
5118 goto exit;
5122 * Insure we have enough space
5124 if (reply_len < (*reply_ofs + 16)) {
5125 log_error("ia_na_nomatch_decline: "
5126 "out of space for reply packet.");
5127 goto exit;
5131 * Put our status code into the reply packet.
5133 len = store_options6(reply_data+(*reply_ofs)+16,
5134 reply_len-(*reply_ofs)-16,
5135 host_opt_state, packet,
5136 required_opts_STATUS_CODE, NULL);
5139 * Store the non-encapsulated option data for this
5140 * IA_NA into our reply packet. Defined in RFC 3315,
5141 * section 22.4.
5143 /* option number */
5144 putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
5145 /* option length */
5146 putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5147 /* IA_NA, copied from the client */
5148 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5149 /* t1 and t2, odd that we need them, but here it is */
5150 putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
5151 putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
5154 * Get ready for next IA_NA.
5156 *reply_ofs += (len + 16);
5158 exit:
5159 option_state_dereference(&host_opt_state, MDL);
5162 static void
5163 iterate_over_ia_na(struct data_string *reply_ret,
5164 struct packet *packet,
5165 const struct data_string *client_id,
5166 const struct data_string *server_id,
5167 const char *packet_type,
5168 void (*ia_na_match)(const struct data_string *,
5169 const struct data_string *,
5170 struct iasubopt *),
5171 void (*ia_na_nomatch)(const struct data_string *,
5172 const struct data_string *,
5173 u_int32_t *, struct packet *, char *,
5174 int *, int))
5176 struct option_state *opt_state;
5177 struct host_decl *packet_host;
5178 struct option_cache *ia;
5179 struct option_cache *oc;
5180 /* cli_enc_... variables come from the IA_NA/IA_TA options */
5181 struct data_string cli_enc_opt_data;
5182 struct option_state *cli_enc_opt_state;
5183 struct host_decl *host;
5184 struct option_state *host_opt_state;
5185 struct data_string iaaddr;
5186 struct data_string fixed_addr;
5187 char reply_data[65536];
5188 struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
5189 int reply_ofs = (int)(offsetof(struct dhcpv6_packet, options));
5190 char status_msg[32];
5191 struct iasubopt *lease;
5192 struct ia_xx *existing_ia_na;
5193 int i;
5194 struct data_string key;
5195 u_int32_t iaid;
5198 * Initialize to empty values, in case we have to exit early.
5200 opt_state = NULL;
5201 memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
5202 cli_enc_opt_state = NULL;
5203 memset(&iaaddr, 0, sizeof(iaaddr));
5204 memset(&fixed_addr, 0, sizeof(fixed_addr));
5205 host_opt_state = NULL;
5206 lease = NULL;
5209 * Find the host record that matches from the packet, if any.
5211 packet_host = NULL;
5212 if (!find_hosts_by_uid(&packet_host,
5213 client_id->data, client_id->len, MDL)) {
5214 packet_host = NULL;
5216 * Note: In general, we don't expect a client to provide
5217 * enough information to match by option for these
5218 * types of messages, but if we don't have a UID
5219 * match we can check anyway.
5221 if (!find_hosts_by_option(&packet_host,
5222 packet, packet->options, MDL)) {
5223 packet_host = NULL;
5225 if (!find_hosts_by_duid_chaddr(&packet_host,
5226 client_id))
5227 packet_host = NULL;
5232 * Set our reply information.
5234 reply->msg_type = DHCPV6_REPLY;
5235 memcpy(reply->transaction_id, packet->dhcpv6_transaction_id,
5236 sizeof(reply->transaction_id));
5239 * Build our option state for reply.
5241 opt_state = NULL;
5242 if (!option_state_allocate(&opt_state, MDL)) {
5243 log_error("iterate_over_ia_na: no memory for option_state.");
5244 goto exit;
5246 execute_statements_in_scope(NULL, packet, NULL, NULL,
5247 packet->options, opt_state,
5248 &global_scope, root_group, NULL, NULL);
5251 * RFC 3315, section 18.2.7 tells us which options to include.
5253 oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
5254 if (oc == NULL) {
5255 if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
5256 (unsigned char *)server_duid.data,
5257 server_duid.len, D6O_SERVERID, 0)) {
5258 log_error("iterate_over_ia_na: "
5259 "error saving server identifier.");
5260 goto exit;
5264 if (!save_option_buffer(&dhcpv6_universe, opt_state,
5265 client_id->buffer,
5266 (unsigned char *)client_id->data,
5267 client_id->len,
5268 D6O_CLIENTID, 0)) {
5269 log_error("iterate_over_ia_na: "
5270 "error saving client identifier.");
5271 goto exit;
5274 snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type);
5275 if (!set_status_code(STATUS_Success, status_msg, opt_state)) {
5276 goto exit;
5280 * Add our options that are not associated with any IA_NA or IA_TA.
5282 reply_ofs += store_options6(reply_data+reply_ofs,
5283 sizeof(reply_data)-reply_ofs,
5284 opt_state, packet,
5285 required_opts, NULL);
5288 * Loop through the IA_NA reported by the client, and deal with
5289 * addresses reported as already in use.
5291 for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
5292 ia != NULL; ia = ia->next) {
5294 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5295 &cli_enc_opt_data,
5296 packet, ia, IA_NA_OFFSET)) {
5297 goto exit;
5300 iaid = getULong(cli_enc_opt_data.data);
5303 * XXX: It is possible that we can get multiple addresses
5304 * sent by the client. We don't send multiple
5305 * addresses, so this indicates a client error.
5306 * We should check for multiple IAADDR options, log
5307 * if found, and set as an error.
5309 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
5310 D6O_IAADDR);
5311 if (oc == NULL) {
5312 /* no address given for this IA, ignore */
5313 option_state_dereference(&cli_enc_opt_state, MDL);
5314 data_string_forget(&cli_enc_opt_data, MDL);
5315 continue;
5318 memset(&iaaddr, 0, sizeof(iaaddr));
5319 if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL,
5320 packet->options, NULL,
5321 &global_scope, oc, MDL)) {
5322 log_error("iterate_over_ia_na: "
5323 "error evaluating IAADDR.");
5324 goto exit;
5328 * Now we need to figure out which host record matches
5329 * this IA_NA and IAADDR (encapsulated option contents
5330 * matching a host record by option).
5332 * XXX: We don't currently track IA_NA separately, but
5333 * we will need to do this!
5335 host = NULL;
5336 if (!find_hosts_by_option(&host, packet,
5337 cli_enc_opt_state, MDL)) {
5338 if (packet_host != NULL) {
5339 host = packet_host;
5340 } else {
5341 host = NULL;
5344 while (host != NULL) {
5345 if (host->fixed_addr != NULL) {
5346 if (!evaluate_option_cache(&fixed_addr, NULL,
5347 NULL, NULL, NULL,
5348 NULL, &global_scope,
5349 host->fixed_addr,
5350 MDL)) {
5351 log_error("iterate_over_ia_na: error "
5352 "evaluating host address.");
5353 goto exit;
5355 if ((iaaddr.len >= 16) &&
5356 !memcmp(fixed_addr.data, iaaddr.data, 16)) {
5357 data_string_forget(&fixed_addr, MDL);
5358 break;
5360 data_string_forget(&fixed_addr, MDL);
5362 host = host->n_ipaddr;
5365 if ((host == NULL) && (iaaddr.len >= IAADDR_OFFSET)) {
5367 * Find existing IA_NA.
5369 if (ia_make_key(&key, iaid,
5370 (char *)client_id->data,
5371 client_id->len,
5372 MDL) != ISC_R_SUCCESS) {
5373 log_fatal("iterate_over_ia_na: no memory for "
5374 "key.");
5377 existing_ia_na = NULL;
5378 if (ia_hash_lookup(&existing_ia_na, ia_na_active,
5379 (unsigned char *)key.data,
5380 key.len, MDL)) {
5382 * Make sure this address is in the IA_NA.
5384 for (i=0; i<existing_ia_na->num_iasubopt; i++) {
5385 struct iasubopt *tmp;
5386 struct in6_addr *in6_addr;
5388 tmp = existing_ia_na->iasubopt[i];
5389 in6_addr = &tmp->addr;
5390 if (memcmp(in6_addr,
5391 iaaddr.data, 16) == 0) {
5392 iasubopt_reference(&lease,
5393 tmp, MDL);
5394 break;
5399 data_string_forget(&key, MDL);
5402 if ((host != NULL) || (lease != NULL)) {
5403 ia_na_match(client_id, &iaaddr, lease);
5404 } else {
5405 ia_na_nomatch(client_id, &iaaddr,
5406 (u_int32_t *)cli_enc_opt_data.data,
5407 packet, reply_data, &reply_ofs,
5408 sizeof(reply_data));
5411 if (lease != NULL) {
5412 iasubopt_dereference(&lease, MDL);
5415 data_string_forget(&iaaddr, MDL);
5416 option_state_dereference(&cli_enc_opt_state, MDL);
5417 data_string_forget(&cli_enc_opt_data, MDL);
5421 * Return our reply to the caller.
5423 reply_ret->len = reply_ofs;
5424 reply_ret->buffer = NULL;
5425 if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
5426 log_fatal("No memory to store reply.");
5428 reply_ret->data = reply_ret->buffer->data;
5429 memcpy(reply_ret->buffer->data, reply, reply_ofs);
5431 exit:
5432 if (lease != NULL) {
5433 iasubopt_dereference(&lease, MDL);
5435 if (host_opt_state != NULL) {
5436 option_state_dereference(&host_opt_state, MDL);
5438 if (fixed_addr.buffer != NULL) {
5439 data_string_forget(&fixed_addr, MDL);
5441 if (iaaddr.buffer != NULL) {
5442 data_string_forget(&iaaddr, MDL);
5444 if (cli_enc_opt_state != NULL) {
5445 option_state_dereference(&cli_enc_opt_state, MDL);
5447 if (cli_enc_opt_data.buffer != NULL) {
5448 data_string_forget(&cli_enc_opt_data, MDL);
5450 if (opt_state != NULL) {
5451 option_state_dereference(&opt_state, MDL);
5456 * Decline means a client has detected that something else is using an
5457 * address we gave it.
5459 * Since we're only dealing with fixed leases for now, there's not
5460 * much we can do, other that log the occurrence.
5462 * When we start issuing addresses from pools, then we will have to
5463 * record our declined addresses and issue another. In general with
5464 * IPv6 there is no worry about DoS by clients exhausting space, but
5465 * we still need to be aware of this possibility.
5468 /* TODO: reject unicast messages, unless we set unicast option */
5469 /* TODO: IA_TA */
5470 static void
5471 dhcpv6_decline(struct data_string *reply, struct packet *packet) {
5472 struct data_string client_id;
5473 struct data_string server_id;
5476 * Validate our input.
5478 if (!valid_client_resp(packet, &client_id, &server_id)) {
5479 return;
5483 * Undefined for IA_PD.
5485 delete_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
5488 * And operate on each IA_NA in this packet.
5490 iterate_over_ia_na(reply, packet, &client_id, &server_id, "Decline",
5491 ia_na_match_decline, ia_na_nomatch_decline);
5493 data_string_forget(&server_id, MDL);
5494 data_string_forget(&client_id, MDL);
5497 static void
5498 ia_na_match_release(const struct data_string *client_id,
5499 const struct data_string *iaaddr,
5500 struct iasubopt *lease)
5502 char tmp_addr[INET6_ADDRSTRLEN];
5504 log_info("Client %s releases address %s",
5505 print_hex_1(client_id->len, client_id->data, 60),
5506 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
5507 if (lease != NULL) {
5508 release_lease6(lease->ipv6_pool, lease);
5509 lease->ia->cltt = cur_time;
5510 write_ia(lease->ia);
5514 static void
5515 ia_na_nomatch_release(const struct data_string *client_id,
5516 const struct data_string *iaaddr,
5517 u_int32_t *ia_na_id,
5518 struct packet *packet,
5519 char *reply_data,
5520 int *reply_ofs,
5521 int reply_len)
5523 char tmp_addr[INET6_ADDRSTRLEN];
5524 struct option_state *host_opt_state;
5525 int len;
5527 log_info("Client %s releases address %s, which is not leased to it.",
5528 print_hex_1(client_id->len, client_id->data, 60),
5529 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
5532 * Create state for this IA_NA.
5534 host_opt_state = NULL;
5535 if (!option_state_allocate(&host_opt_state, MDL)) {
5536 log_error("ia_na_nomatch_release: out of memory "
5537 "allocating option_state.");
5538 goto exit;
5541 if (!set_status_code(STATUS_NoBinding,
5542 "Release for non-leased address.",
5543 host_opt_state)) {
5544 goto exit;
5548 * Insure we have enough space
5550 if (reply_len < (*reply_ofs + 16)) {
5551 log_error("ia_na_nomatch_release: "
5552 "out of space for reply packet.");
5553 goto exit;
5557 * Put our status code into the reply packet.
5559 len = store_options6(reply_data+(*reply_ofs)+16,
5560 reply_len-(*reply_ofs)-16,
5561 host_opt_state, packet,
5562 required_opts_STATUS_CODE, NULL);
5565 * Store the non-encapsulated option data for this
5566 * IA_NA into our reply packet. Defined in RFC 3315,
5567 * section 22.4.
5569 /* option number */
5570 putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
5571 /* option length */
5572 putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5573 /* IA_NA, copied from the client */
5574 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5575 /* t1 and t2, odd that we need them, but here it is */
5576 putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
5577 putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
5580 * Get ready for next IA_NA.
5582 *reply_ofs += (len + 16);
5584 exit:
5585 option_state_dereference(&host_opt_state, MDL);
5588 static void
5589 ia_pd_match_release(const struct data_string *client_id,
5590 const struct data_string *iapref,
5591 struct iasubopt *prefix)
5593 char tmp_addr[INET6_ADDRSTRLEN];
5595 log_info("Client %s releases prefix %s/%u",
5596 print_hex_1(client_id->len, client_id->data, 60),
5597 inet_ntop(AF_INET6, iapref->data + 9,
5598 tmp_addr, sizeof(tmp_addr)),
5599 (unsigned) getUChar(iapref->data + 8));
5600 if (prefix != NULL) {
5601 release_lease6(prefix->ipv6_pool, prefix);
5602 prefix->ia->cltt = cur_time;
5603 write_ia(prefix->ia);
5607 static void
5608 ia_pd_nomatch_release(const struct data_string *client_id,
5609 const struct data_string *iapref,
5610 u_int32_t *ia_pd_id,
5611 struct packet *packet,
5612 char *reply_data,
5613 int *reply_ofs,
5614 int reply_len)
5616 char tmp_addr[INET6_ADDRSTRLEN];
5617 struct option_state *host_opt_state;
5618 int len;
5620 log_info("Client %s releases prefix %s/%u, which is not leased to it.",
5621 print_hex_1(client_id->len, client_id->data, 60),
5622 inet_ntop(AF_INET6, iapref->data + 9,
5623 tmp_addr, sizeof(tmp_addr)),
5624 (unsigned) getUChar(iapref->data + 8));
5627 * Create state for this IA_PD.
5629 host_opt_state = NULL;
5630 if (!option_state_allocate(&host_opt_state, MDL)) {
5631 log_error("ia_pd_nomatch_release: out of memory "
5632 "allocating option_state.");
5633 goto exit;
5636 if (!set_status_code(STATUS_NoBinding,
5637 "Release for non-leased prefix.",
5638 host_opt_state)) {
5639 goto exit;
5643 * Insure we have enough space
5645 if (reply_len < (*reply_ofs + 16)) {
5646 log_error("ia_pd_nomatch_release: "
5647 "out of space for reply packet.");
5648 goto exit;
5652 * Put our status code into the reply packet.
5654 len = store_options6(reply_data+(*reply_ofs)+16,
5655 reply_len-(*reply_ofs)-16,
5656 host_opt_state, packet,
5657 required_opts_STATUS_CODE, NULL);
5660 * Store the non-encapsulated option data for this
5661 * IA_PD into our reply packet. Defined in RFC 3315,
5662 * section 22.4.
5664 /* option number */
5665 putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_PD);
5666 /* option length */
5667 putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5668 /* IA_PD, copied from the client */
5669 memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
5670 /* t1 and t2, odd that we need them, but here it is */
5671 putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
5672 putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
5675 * Get ready for next IA_PD.
5677 *reply_ofs += (len + 16);
5679 exit:
5680 option_state_dereference(&host_opt_state, MDL);
5683 static void
5684 iterate_over_ia_pd(struct data_string *reply_ret,
5685 struct packet *packet,
5686 const struct data_string *client_id,
5687 const struct data_string *server_id,
5688 const char *packet_type,
5689 void (*ia_pd_match)(const struct data_string *,
5690 const struct data_string *,
5691 struct iasubopt *),
5692 void (*ia_pd_nomatch)(const struct data_string *,
5693 const struct data_string *,
5694 u_int32_t *, struct packet *, char *,
5695 int *, int))
5697 struct data_string reply_new;
5698 int reply_len;
5699 struct option_state *opt_state;
5700 struct host_decl *packet_host;
5701 struct option_cache *ia;
5702 struct option_cache *oc;
5703 /* cli_enc_... variables come from the IA_PD options */
5704 struct data_string cli_enc_opt_data;
5705 struct option_state *cli_enc_opt_state;
5706 struct host_decl *host;
5707 struct option_state *host_opt_state;
5708 struct data_string iaprefix;
5709 char reply_data[65536];
5710 int reply_ofs;
5711 struct iasubopt *prefix;
5712 struct ia_xx *existing_ia_pd;
5713 int i;
5714 struct data_string key;
5715 u_int32_t iaid;
5718 * Initialize to empty values, in case we have to exit early.
5720 memset(&reply_new, 0, sizeof(reply_new));
5721 opt_state = NULL;
5722 memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
5723 cli_enc_opt_state = NULL;
5724 memset(&iaprefix, 0, sizeof(iaprefix));
5725 host_opt_state = NULL;
5726 prefix = NULL;
5729 * Compute the available length for the reply.
5731 reply_len = sizeof(reply_data) - reply_ret->len;
5732 reply_ofs = 0;
5735 * Find the host record that matches from the packet, if any.
5737 packet_host = NULL;
5738 if (!find_hosts_by_uid(&packet_host,
5739 client_id->data, client_id->len, MDL)) {
5740 packet_host = NULL;
5742 * Note: In general, we don't expect a client to provide
5743 * enough information to match by option for these
5744 * types of messages, but if we don't have a UID
5745 * match we can check anyway.
5747 if (!find_hosts_by_option(&packet_host,
5748 packet, packet->options, MDL)) {
5749 packet_host = NULL;
5751 if (!find_hosts_by_duid_chaddr(&packet_host,
5752 client_id))
5753 packet_host = NULL;
5758 * Build our option state for reply.
5760 opt_state = NULL;
5761 if (!option_state_allocate(&opt_state, MDL)) {
5762 log_error("iterate_over_ia_pd: no memory for option_state.");
5763 goto exit;
5765 execute_statements_in_scope(NULL, packet, NULL, NULL,
5766 packet->options, opt_state,
5767 &global_scope, root_group, NULL, NULL);
5770 * Loop through the IA_PD reported by the client, and deal with
5771 * prefixes reported as already in use.
5773 for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
5774 ia != NULL; ia = ia->next) {
5776 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5777 &cli_enc_opt_data,
5778 packet, ia, IA_PD_OFFSET)) {
5779 goto exit;
5782 iaid = getULong(cli_enc_opt_data.data);
5784 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
5785 D6O_IAPREFIX);
5786 if (oc == NULL) {
5787 /* no prefix given for this IA_PD, ignore */
5788 option_state_dereference(&cli_enc_opt_state, MDL);
5789 data_string_forget(&cli_enc_opt_data, MDL);
5790 continue;
5793 for (; oc != NULL; oc = oc->next) {
5794 memset(&iaprefix, 0, sizeof(iaprefix));
5795 if (!evaluate_option_cache(&iaprefix, packet, NULL, NULL,
5796 packet->options, NULL,
5797 &global_scope, oc, MDL)) {
5798 log_error("iterate_over_ia_pd: "
5799 "error evaluating IAPREFIX.");
5800 goto exit;
5804 * Now we need to figure out which host record matches
5805 * this IA_PD and IAPREFIX (encapsulated option contents
5806 * matching a host record by option).
5808 * XXX: We don't currently track IA_PD separately, but
5809 * we will need to do this!
5811 host = NULL;
5812 if (!find_hosts_by_option(&host, packet,
5813 cli_enc_opt_state, MDL)) {
5814 if (packet_host != NULL) {
5815 host = packet_host;
5816 } else {
5817 host = NULL;
5820 while (host != NULL) {
5821 if (host->fixed_prefix != NULL) {
5822 struct iaddrcidrnetlist *l;
5823 int plen = (int) getUChar(iaprefix.data + 8);
5825 for (l = host->fixed_prefix; l != NULL;
5826 l = l->next) {
5827 if (plen != l->cidrnet.bits)
5828 continue;
5829 if (memcmp(iaprefix.data + 9,
5830 l->cidrnet.lo_addr.iabuf,
5831 16) == 0)
5832 break;
5834 if ((l != NULL) && (iaprefix.len >= 17))
5835 break;
5837 host = host->n_ipaddr;
5840 if ((host == NULL) && (iaprefix.len >= IAPREFIX_OFFSET)) {
5842 * Find existing IA_PD.
5844 if (ia_make_key(&key, iaid,
5845 (char *)client_id->data,
5846 client_id->len,
5847 MDL) != ISC_R_SUCCESS) {
5848 log_fatal("iterate_over_ia_pd: no memory for "
5849 "key.");
5852 existing_ia_pd = NULL;
5853 if (ia_hash_lookup(&existing_ia_pd, ia_pd_active,
5854 (unsigned char *)key.data,
5855 key.len, MDL)) {
5857 * Make sure this prefix is in the IA_PD.
5859 for (i = 0;
5860 i < existing_ia_pd->num_iasubopt;
5861 i++) {
5862 struct iasubopt *tmp;
5863 u_int8_t plen;
5865 plen = getUChar(iaprefix.data + 8);
5866 tmp = existing_ia_pd->iasubopt[i];
5867 if ((tmp->plen == plen) &&
5868 (memcmp(&tmp->addr,
5869 iaprefix.data + 9,
5870 16) == 0)) {
5871 iasubopt_reference(&prefix,
5872 tmp, MDL);
5873 break;
5878 data_string_forget(&key, MDL);
5881 if ((host != NULL) || (prefix != NULL)) {
5882 ia_pd_match(client_id, &iaprefix, prefix);
5883 } else {
5884 ia_pd_nomatch(client_id, &iaprefix,
5885 (u_int32_t *)cli_enc_opt_data.data,
5886 packet, reply_data, &reply_ofs,
5887 reply_len - reply_ofs);
5890 if (prefix != NULL) {
5891 iasubopt_dereference(&prefix, MDL);
5894 data_string_forget(&iaprefix, MDL);
5897 option_state_dereference(&cli_enc_opt_state, MDL);
5898 data_string_forget(&cli_enc_opt_data, MDL);
5902 * Return our reply to the caller.
5903 * The IA_NA routine has already filled at least the header.
5905 reply_new.len = reply_ret->len + reply_ofs;
5906 if (!buffer_allocate(&reply_new.buffer, reply_new.len, MDL)) {
5907 log_fatal("No memory to store reply.");
5909 reply_new.data = reply_new.buffer->data;
5910 memcpy(reply_new.buffer->data,
5911 reply_ret->buffer->data, reply_ret->len);
5912 memcpy(reply_new.buffer->data + reply_ret->len,
5913 reply_data, reply_ofs);
5914 data_string_forget(reply_ret, MDL);
5915 data_string_copy(reply_ret, &reply_new, MDL);
5916 data_string_forget(&reply_new, MDL);
5918 exit:
5919 if (prefix != NULL) {
5920 iasubopt_dereference(&prefix, MDL);
5922 if (host_opt_state != NULL) {
5923 option_state_dereference(&host_opt_state, MDL);
5925 if (iaprefix.buffer != NULL) {
5926 data_string_forget(&iaprefix, MDL);
5928 if (cli_enc_opt_state != NULL) {
5929 option_state_dereference(&cli_enc_opt_state, MDL);
5931 if (cli_enc_opt_data.buffer != NULL) {
5932 data_string_forget(&cli_enc_opt_data, MDL);
5934 if (opt_state != NULL) {
5935 option_state_dereference(&opt_state, MDL);
5940 * Release means a client is done with the leases.
5943 /* TODO: reject unicast messages, unless we set unicast option */
5944 static void
5945 dhcpv6_release(struct data_string *reply, struct packet *packet) {
5946 struct data_string client_id;
5947 struct data_string server_id;
5950 * Validate our input.
5952 if (!valid_client_resp(packet, &client_id, &server_id)) {
5953 return;
5957 * And operate on each IA_NA in this packet.
5959 iterate_over_ia_na(reply, packet, &client_id, &server_id, "Release",
5960 ia_na_match_release, ia_na_nomatch_release);
5963 * And operate on each IA_PD in this packet.
5965 iterate_over_ia_pd(reply, packet, &client_id, &server_id, "Release",
5966 ia_pd_match_release, ia_pd_nomatch_release);
5968 data_string_forget(&server_id, MDL);
5969 data_string_forget(&client_id, MDL);
5973 * Information-Request is used by clients who have obtained an address
5974 * from other means, but want configuration information from the server.
5977 static void
5978 dhcpv6_information_request(struct data_string *reply, struct packet *packet) {
5979 struct data_string client_id;
5980 struct data_string server_id;
5983 * Validate our input.
5985 if (!valid_client_info_req(packet, &server_id)) {
5986 return;
5990 * Get our client ID, if there is one.
5992 memset(&client_id, 0, sizeof(client_id));
5993 if (get_client_id(packet, &client_id) != ISC_R_SUCCESS) {
5994 data_string_forget(&client_id, MDL);
5998 * Use the lease_to_client() function. This will work fine,
5999 * because the valid_client_info_req() insures that we
6000 * don't have any IA that would cause us to allocate
6001 * resources to the client.
6003 lease_to_client(reply, packet, &client_id,
6004 server_id.data != NULL ? &server_id : NULL);
6007 * Cleanup.
6009 if (client_id.data != NULL) {
6010 data_string_forget(&client_id, MDL);
6012 data_string_forget(&server_id, MDL);
6016 * The Relay-forw message is sent by relays. It typically contains a
6017 * single option, which encapsulates an entire packet.
6019 * We need to build an encapsulated reply.
6022 /* XXX: this is very, very similar to do_packet6(), and should probably
6023 be combined in a clever way */
6024 static void
6025 dhcpv6_relay_forw(struct data_string *reply_ret, struct packet *packet) {
6026 struct option_cache *oc;
6027 struct data_string enc_opt_data;
6028 struct packet *enc_packet;
6029 unsigned char msg_type;
6030 const struct dhcpv6_packet *msg;
6031 const struct dhcpv6_relay_packet *relay;
6032 struct data_string enc_reply;
6033 char link_addr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6034 char peer_addr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6035 struct data_string a_opt, packet_ero;
6036 struct option_state *opt_state;
6037 static char reply_data[65536];
6038 struct dhcpv6_relay_packet *reply;
6039 int reply_ofs;
6042 * Initialize variables for early exit.
6044 opt_state = NULL;
6045 memset(&a_opt, 0, sizeof(a_opt));
6046 memset(&packet_ero, 0, sizeof(packet_ero));
6047 memset(&enc_reply, 0, sizeof(enc_reply));
6048 memset(&enc_opt_data, 0, sizeof(enc_opt_data));
6049 enc_packet = NULL;
6052 * Get our encapsulated relay message.
6054 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_RELAY_MSG);
6055 if (oc == NULL) {
6056 inet_ntop(AF_INET6, &packet->dhcpv6_link_address,
6057 link_addr, sizeof(link_addr));
6058 inet_ntop(AF_INET6, &packet->dhcpv6_peer_address,
6059 peer_addr, sizeof(peer_addr));
6060 log_info("Relay-forward from %s with link address=%s and "
6061 "peer address=%s missing Relay Message option.",
6062 piaddr(packet->client_addr), link_addr, peer_addr);
6063 goto exit;
6066 if (!evaluate_option_cache(&enc_opt_data, NULL, NULL, NULL,
6067 NULL, NULL, &global_scope, oc, MDL)) {
6068 log_error("dhcpv6_forw_relay: error evaluating "
6069 "relayed message.");
6070 goto exit;
6073 if (!packet6_len_okay((char *)enc_opt_data.data, enc_opt_data.len)) {
6074 log_error("dhcpv6_forw_relay: encapsulated packet too short.");
6075 goto exit;
6079 * Build a packet structure from this encapsulated packet.
6081 enc_packet = NULL;
6082 if (!packet_allocate(&enc_packet, MDL)) {
6083 log_error("dhcpv6_forw_relay: "
6084 "no memory for encapsulated packet.");
6085 goto exit;
6088 if (!option_state_allocate(&enc_packet->options, MDL)) {
6089 log_error("dhcpv6_forw_relay: "
6090 "no memory for encapsulated packet's options.");
6091 goto exit;
6094 enc_packet->client_port = packet->client_port;
6095 enc_packet->client_addr = packet->client_addr;
6096 interface_reference(&enc_packet->interface, packet->interface, MDL);
6097 enc_packet->dhcpv6_container_packet = packet;
6099 msg_type = enc_opt_data.data[0];
6100 if ((msg_type == DHCPV6_RELAY_FORW) ||
6101 (msg_type == DHCPV6_RELAY_REPL)) {
6102 int relaylen = (int)(offsetof(struct dhcpv6_relay_packet, options));
6103 relay = (struct dhcpv6_relay_packet *)enc_opt_data.data;
6104 enc_packet->dhcpv6_msg_type = relay->msg_type;
6106 /* relay-specific data */
6107 enc_packet->dhcpv6_hop_count = relay->hop_count;
6108 memcpy(&enc_packet->dhcpv6_link_address,
6109 relay->link_address, sizeof(relay->link_address));
6110 memcpy(&enc_packet->dhcpv6_peer_address,
6111 relay->peer_address, sizeof(relay->peer_address));
6113 if (!parse_option_buffer(enc_packet->options,
6114 relay->options,
6115 enc_opt_data.len - relaylen,
6116 &dhcpv6_universe)) {
6117 /* no logging here, as parse_option_buffer() logs all
6118 cases where it fails */
6119 goto exit;
6121 } else {
6122 int msglen = (int)(offsetof(struct dhcpv6_packet, options));
6123 msg = (struct dhcpv6_packet *)enc_opt_data.data;
6124 enc_packet->dhcpv6_msg_type = msg->msg_type;
6126 /* message-specific data */
6127 memcpy(enc_packet->dhcpv6_transaction_id,
6128 msg->transaction_id,
6129 sizeof(enc_packet->dhcpv6_transaction_id));
6131 if (!parse_option_buffer(enc_packet->options,
6132 msg->options,
6133 enc_opt_data.len - msglen,
6134 &dhcpv6_universe)) {
6135 /* no logging here, as parse_option_buffer() logs all
6136 cases where it fails */
6137 goto exit;
6142 * This is recursive. It is possible to exceed maximum packet size.
6143 * XXX: This will cause the packet send to fail.
6145 build_dhcpv6_reply(&enc_reply, enc_packet);
6148 * If we got no encapsulated data, then it is discarded, and
6149 * our reply-forw is also discarded.
6151 if (enc_reply.data == NULL) {
6152 goto exit;
6156 * Now we can use the reply_data buffer.
6157 * Packet header stuff all comes from the forward message.
6159 reply = (struct dhcpv6_relay_packet *)reply_data;
6160 reply->msg_type = DHCPV6_RELAY_REPL;
6161 reply->hop_count = packet->dhcpv6_hop_count;
6162 memcpy(reply->link_address, &packet->dhcpv6_link_address,
6163 sizeof(reply->link_address));
6164 memcpy(reply->peer_address, &packet->dhcpv6_peer_address,
6165 sizeof(reply->peer_address));
6166 reply_ofs = (int)(offsetof(struct dhcpv6_relay_packet, options));
6169 * Get the reply option state.
6171 opt_state = NULL;
6172 if (!option_state_allocate(&opt_state, MDL)) {
6173 log_error("dhcpv6_relay_forw: no memory for option state.");
6174 goto exit;
6178 * Append the interface-id if present.
6180 oc = lookup_option(&dhcpv6_universe, packet->options,
6181 D6O_INTERFACE_ID);
6182 if (oc != NULL) {
6183 if (!evaluate_option_cache(&a_opt, packet,
6184 NULL, NULL,
6185 packet->options, NULL,
6186 &global_scope, oc, MDL)) {
6187 log_error("dhcpv6_relay_forw: error evaluating "
6188 "Interface ID.");
6189 goto exit;
6191 if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
6192 (unsigned char *)a_opt.data,
6193 a_opt.len,
6194 D6O_INTERFACE_ID, 0)) {
6195 log_error("dhcpv6_relay_forw: error saving "
6196 "Interface ID.");
6197 goto exit;
6199 data_string_forget(&a_opt, MDL);
6203 * Append our encapsulated stuff for caller.
6205 if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
6206 (unsigned char *)enc_reply.data,
6207 enc_reply.len,
6208 D6O_RELAY_MSG, 0)) {
6209 log_error("dhcpv6_relay_forw: error saving Relay MSG.");
6210 goto exit;
6214 * Get the ERO if any.
6216 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ERO);
6217 if (oc != NULL) {
6218 unsigned req;
6219 int i;
6221 if (!evaluate_option_cache(&packet_ero, packet,
6222 NULL, NULL,
6223 packet->options, NULL,
6224 &global_scope, oc, MDL) ||
6225 (packet_ero.len & 1)) {
6226 log_error("dhcpv6_relay_forw: error evaluating ERO.");
6227 goto exit;
6230 /* Decode and apply the ERO. */
6231 for (i = 0; i < packet_ero.len; i += 2) {
6232 req = getUShort(packet_ero.data + i);
6233 /* Already in the reply? */
6234 oc = lookup_option(&dhcpv6_universe, opt_state, req);
6235 if (oc != NULL)
6236 continue;
6237 /* Get it from the packet if present. */
6238 oc = lookup_option(&dhcpv6_universe,
6239 packet->options,
6240 req);
6241 if (oc == NULL)
6242 continue;
6243 if (!evaluate_option_cache(&a_opt, packet,
6244 NULL, NULL,
6245 packet->options, NULL,
6246 &global_scope, oc, MDL)) {
6247 log_error("dhcpv6_relay_forw: error "
6248 "evaluating option %u.", req);
6249 goto exit;
6251 if (!save_option_buffer(&dhcpv6_universe,
6252 opt_state,
6253 NULL,
6254 (unsigned char *)a_opt.data,
6255 a_opt.len,
6256 req,
6257 0)) {
6258 log_error("dhcpv6_relay_forw: error saving "
6259 "option %u.", req);
6260 goto exit;
6262 data_string_forget(&a_opt, MDL);
6266 reply_ofs += store_options6(reply_data + reply_ofs,
6267 sizeof(reply_data) - reply_ofs,
6268 opt_state, packet,
6269 required_opts_agent, &packet_ero);
6272 * Return our reply to the caller.
6274 reply_ret->len = reply_ofs;
6275 reply_ret->buffer = NULL;
6276 if (!buffer_allocate(&reply_ret->buffer, reply_ret->len, MDL)) {
6277 log_fatal("No memory to store reply.");
6279 reply_ret->data = reply_ret->buffer->data;
6280 memcpy(reply_ret->buffer->data, reply_data, reply_ofs);
6282 exit:
6283 if (opt_state != NULL)
6284 option_state_dereference(&opt_state, MDL);
6285 if (a_opt.data != NULL) {
6286 data_string_forget(&a_opt, MDL);
6288 if (packet_ero.data != NULL) {
6289 data_string_forget(&packet_ero, MDL);
6291 if (enc_reply.data != NULL) {
6292 data_string_forget(&enc_reply, MDL);
6294 if (enc_opt_data.data != NULL) {
6295 data_string_forget(&enc_opt_data, MDL);
6297 if (enc_packet != NULL) {
6298 packet_dereference(&enc_packet, MDL);
6302 static void
6303 dhcpv6_discard(struct packet *packet) {
6304 /* INSIST(packet->msg_type > 0); */
6305 /* INSIST(packet->msg_type < dhcpv6_type_name_max); */
6307 log_debug("Discarding %s from %s; message type not handled by server",
6308 dhcpv6_type_names[packet->dhcpv6_msg_type],
6309 piaddr(packet->client_addr));
6312 static void
6313 build_dhcpv6_reply(struct data_string *reply, struct packet *packet) {
6314 memset(reply, 0, sizeof(*reply));
6316 /* I would like to classify the client once here, but
6317 * as I don't want to classify all of the incoming packets
6318 * I need to do it before handling specific types.
6319 * We don't need to classify if we are tossing the packet
6320 * or if it is a relay - the classification step will get
6321 * done when we process the inner client packet.
6324 switch (packet->dhcpv6_msg_type) {
6325 case DHCPV6_SOLICIT:
6326 classify_client(packet);
6327 dhcpv6_solicit(reply, packet);
6328 break;
6329 case DHCPV6_ADVERTISE:
6330 dhcpv6_discard(packet);
6331 break;
6332 case DHCPV6_REQUEST:
6333 classify_client(packet);
6334 dhcpv6_request(reply, packet);
6335 break;
6336 case DHCPV6_CONFIRM:
6337 classify_client(packet);
6338 dhcpv6_confirm(reply, packet);
6339 break;
6340 case DHCPV6_RENEW:
6341 classify_client(packet);
6342 dhcpv6_renew(reply, packet);
6343 break;
6344 case DHCPV6_REBIND:
6345 classify_client(packet);
6346 dhcpv6_rebind(reply, packet);
6347 break;
6348 case DHCPV6_REPLY:
6349 dhcpv6_discard(packet);
6350 break;
6351 case DHCPV6_RELEASE:
6352 classify_client(packet);
6353 dhcpv6_release(reply, packet);
6354 break;
6355 case DHCPV6_DECLINE:
6356 classify_client(packet);
6357 dhcpv6_decline(reply, packet);
6358 break;
6359 case DHCPV6_RECONFIGURE:
6360 dhcpv6_discard(packet);
6361 break;
6362 case DHCPV6_INFORMATION_REQUEST:
6363 classify_client(packet);
6364 dhcpv6_information_request(reply, packet);
6365 break;
6366 case DHCPV6_RELAY_FORW:
6367 dhcpv6_relay_forw(reply, packet);
6368 break;
6369 case DHCPV6_RELAY_REPL:
6370 dhcpv6_discard(packet);
6371 break;
6372 case DHCPV6_LEASEQUERY:
6373 classify_client(packet);
6374 dhcpv6_leasequery(reply, packet);
6375 break;
6376 case DHCPV6_LEASEQUERY_REPLY:
6377 dhcpv6_discard(packet);
6378 break;
6379 default:
6380 /* XXX: would be nice if we had "notice" level,
6381 as syslog, for this */
6382 log_info("Discarding unknown DHCPv6 message type %d "
6383 "from %s", packet->dhcpv6_msg_type,
6384 piaddr(packet->client_addr));
6388 static void
6389 log_packet_in(const struct packet *packet) {
6390 struct data_string s;
6391 u_int32_t tid;
6392 char tmp_addr[INET6_ADDRSTRLEN];
6393 const void *addr;
6395 memset(&s, 0, sizeof(s));
6397 if (packet->dhcpv6_msg_type < dhcpv6_type_name_max) {
6398 data_string_sprintfa(&s, "%s message from %s port %d",
6399 dhcpv6_type_names[packet->dhcpv6_msg_type],
6400 piaddr(packet->client_addr),
6401 ntohs(packet->client_port));
6402 } else {
6403 data_string_sprintfa(&s,
6404 "Unknown message type %d from %s port %d",
6405 packet->dhcpv6_msg_type,
6406 piaddr(packet->client_addr),
6407 ntohs(packet->client_port));
6409 if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) ||
6410 (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
6411 addr = &packet->dhcpv6_link_address;
6412 data_string_sprintfa(&s, ", link address %s",
6413 inet_ntop(AF_INET6, addr,
6414 tmp_addr, sizeof(tmp_addr)));
6415 addr = &packet->dhcpv6_peer_address;
6416 data_string_sprintfa(&s, ", peer address %s",
6417 inet_ntop(AF_INET6, addr,
6418 tmp_addr, sizeof(tmp_addr)));
6419 } else {
6420 tid = 0;
6421 memcpy(((char *)&tid)+1, packet->dhcpv6_transaction_id, 3);
6422 data_string_sprintfa(&s, ", transaction ID 0x%06X", tid);
6425 oc = lookup_option(&dhcpv6_universe, packet->options,
6426 D6O_CLIENTID);
6427 if (oc != NULL) {
6428 memset(&tmp_ds, 0, sizeof(tmp_ds_));
6429 if (!evaluate_option_cache(&tmp_ds, packet, NULL, NULL,
6430 packet->options, NULL,
6431 &global_scope, oc, MDL)) {
6432 log_error("Error evaluating Client Identifier");
6433 } else {
6434 data_strint_sprintf(&s, ", client ID %s",
6436 data_string_forget(&tmp_ds, MDL);
6442 log_info("%s", s.data);
6444 data_string_forget(&s, MDL);
6447 void
6448 dhcpv6(struct packet *packet) {
6449 struct data_string reply;
6450 struct sockaddr_in6 to_addr;
6451 int send_ret;
6454 * Log a message that we received this packet.
6456 log_packet_in(packet);
6459 * Build our reply packet.
6461 build_dhcpv6_reply(&reply, packet);
6463 if (reply.data != NULL) {
6465 * Send our reply, if we have one.
6467 memset(&to_addr, 0, sizeof(to_addr));
6468 to_addr.sin6_family = AF_INET6;
6469 if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) ||
6470 (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
6471 to_addr.sin6_port = local_port;
6472 } else {
6473 to_addr.sin6_port = remote_port;
6476 #if defined (REPLY_TO_SOURCE_PORT)
6478 * This appears to have been included for testing so we would
6479 * not need a root client, but was accidently left in the
6480 * final code. We continue to include it in case
6481 * some users have come to rely upon it, but leave
6482 * it off by default as it's a bad idea.
6484 to_addr.sin6_port = packet->client_port;
6485 #endif
6487 memcpy(&to_addr.sin6_addr, packet->client_addr.iabuf,
6488 sizeof(to_addr.sin6_addr));
6490 log_info("Sending %s to %s port %d",
6491 dhcpv6_type_names[reply.data[0]],
6492 piaddr(packet->client_addr),
6493 ntohs(to_addr.sin6_port));
6495 send_ret = send_packet6(packet->interface,
6496 reply.data, reply.len, &to_addr);
6497 if (send_ret != reply.len) {
6498 log_error("dhcpv6: send_packet6() sent %d of %d bytes",
6499 send_ret, reply.len);
6501 data_string_forget(&reply, MDL);
6505 static void
6506 seek_shared_host(struct host_decl **hp, struct shared_network *shared) {
6507 struct host_decl *nofixed = NULL;
6508 struct host_decl *seek, *hold = NULL;
6511 * Seek forward through fixed addresses for the right link.
6513 * Note: how to do this for fixed prefixes???
6515 host_reference(&hold, *hp, MDL);
6516 host_dereference(hp, MDL);
6517 seek = hold;
6518 while (seek != NULL) {
6519 if (seek->fixed_addr == NULL)
6520 nofixed = seek;
6521 else if (fixed_matches_shared(seek, shared))
6522 break;
6524 seek = seek->n_ipaddr;
6527 if ((seek == NULL) && (nofixed != NULL))
6528 seek = nofixed;
6530 if (seek != NULL)
6531 host_reference(hp, seek, MDL);
6534 static isc_boolean_t
6535 fixed_matches_shared(struct host_decl *host, struct shared_network *shared) {
6536 struct subnet *subnet;
6537 struct data_string addr;
6538 isc_boolean_t matched;
6539 struct iaddr fixed;
6541 if (host->fixed_addr == NULL)
6542 return ISC_FALSE;
6544 memset(&addr, 0, sizeof(addr));
6545 if (!evaluate_option_cache(&addr, NULL, NULL, NULL, NULL, NULL,
6546 &global_scope, host->fixed_addr, MDL))
6547 return ISC_FALSE;
6549 if (addr.len < 16) {
6550 data_string_forget(&addr, MDL);
6551 return ISC_FALSE;
6554 fixed.len = 16;
6555 memcpy(fixed.iabuf, addr.data, 16);
6557 matched = ISC_FALSE;
6558 for (subnet = shared->subnets ; subnet != NULL ;
6559 subnet = subnet->next_sibling) {
6560 if (addr_eq(subnet_number(fixed, subnet->netmask),
6561 subnet->net)) {
6562 matched = ISC_TRUE;
6563 break;
6567 data_string_forget(&addr, MDL);
6568 return matched;
6572 * find_host_by_duid_chaddr() synthesizes a DHCPv4-like 'hardware'
6573 * parameter from a DHCPv6 supplied DUID (client-identifier option),
6574 * and may seek to use client or relay supplied hardware addresses.
6576 static int
6577 find_hosts_by_duid_chaddr(struct host_decl **host,
6578 const struct data_string *client_id) {
6579 static int once_htype;
6580 int htype, hlen;
6581 const unsigned char *chaddr;
6584 * The DUID-LL and DUID-LLT must have a 2-byte DUID type and 2-byte
6585 * htype.
6587 if (client_id->len < 4)
6588 return 0;
6591 * The third and fourth octets of the DUID-LL and DUID-LLT
6592 * is the hardware type, but in 16 bits.
6594 htype = getUShort(client_id->data + 2);
6595 hlen = 0;
6596 chaddr = NULL;
6598 /* The first two octets of the DUID identify the type. */
6599 switch(getUShort(client_id->data)) {
6600 case DUID_LLT:
6601 if (client_id->len > 8) {
6602 hlen = client_id->len - 8;
6603 chaddr = client_id->data + 8;
6605 break;
6607 case DUID_LL:
6609 * Note that client_id->len must be greater than or equal
6610 * to four to get to this point in the function.
6612 hlen = client_id->len - 4;
6613 chaddr = client_id->data + 4;
6614 break;
6616 default:
6617 break;
6620 if ((hlen == 0) || (hlen > HARDWARE_ADDR_LEN))
6621 return 0;
6624 * XXX: DHCPv6 gives a 16-bit field for the htype. DHCPv4 gives an
6625 * 8-bit field. To change the semantics of the generic 'hardware'
6626 * structure, we would have to adjust many DHCPv4 sources (from
6627 * interface to DHCPv4 lease code), and we would have to update the
6628 * 'hardware' config directive (probably being reverse compatible and
6629 * providing a new upgrade/replacement primitive). This is a little
6630 * too much to change for now. Hopefully we will revisit this before
6631 * hardware types exceeding 8 bits are assigned.
6633 if ((htype & 0xFF00) && !once_htype) {
6634 once_htype = 1;
6635 log_error("Attention: At least one client advertises a "
6636 "hardware type of %d, which exceeds the software "
6637 "limitation of 255.", htype);
6640 return find_hosts_by_haddr(host, htype, chaddr, hlen, MDL);
6643 #endif /* DHCPv6 */