]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/dhcpv6.c
[master] Add support for relayed client-linklayer-address option (RFC 6939)
[thirdparty/dhcp.git] / server / dhcpv6.c
CommitLineData
98bd7ca0 1/*
36c4a037 2 * Copyright (C) 2006-2016 by Internet Systems Consortium, Inc. ("ISC")
98bd7ca0
DH
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
01fa619f
SR
17/*! \file server/dhcpv6.c */
18
98bd7ca0
DH
19#include "dhcpd.h"
20
fe5b0fdd
DH
21#ifdef DHCPv6
22
98bd7ca0 23/*
b31fe1d5
TM
24 * We use print_hex_1() to output DUID values. We could actually output
25 * the DUID with more information... MAC address if using type 1 or 3,
26 * and so on. However, RFC 3315 contains Grave Warnings against actually
98bd7ca0
DH
27 * attempting to understand a DUID.
28 */
29
b31fe1d5 30/*
98bd7ca0
DH
31 * TODO: gettext() or other method of localization for the messages
32 * for status codes (and probably for log formats eventually)
33 * TODO: refactoring (simplify, simplify, simplify)
b31fe1d5
TM
34 * TODO: support multiple shared_networks on each interface (this
35 * will allow the server to issue multiple IPv6 addresses to
98bd7ca0
DH
36 * a single interface)
37 */
38
5279b8f3
DH
39/*
40 * DHCPv6 Reply workflow assist. A Reply packet is built by various
41 * different functions; this gives us one location where we keep state
42 * regarding a reply.
43 */
44struct reply_state {
45 /* root level persistent state */
46 struct shared_network *shared;
47 struct host_decl *host;
2267da84 48 struct subnet *subnet; /* Used to match fixed-addrs to subnet scopes. */
5279b8f3
DH
49 struct option_state *opt_state;
50 struct packet *packet;
51 struct data_string client_id;
52
53 /* IA level persistent state */
54 unsigned ia_count;
9322442f 55 unsigned pd_count;
1d9774ab 56 unsigned client_resources;
9322442f 57 isc_boolean_t resources_included;
b024480e 58 isc_boolean_t static_lease;
80c9fdb0 59 unsigned static_prefixes;
9322442f
FD
60 struct ia_xx *ia;
61 struct ia_xx *old_ia;
5279b8f3
DH
62 struct option_state *reply_ia;
63 struct data_string fixed;
d9b5c150 64 struct iaddrcidrnet fixed_pref; /* static prefix for logging */
5279b8f3 65
9322442f 66 /* IAADDR/PREFIX level persistent state */
1d17db44 67 struct iasubopt *lease;
5279b8f3
DH
68
69 /*
70 * "t1", "t2", preferred, and valid lifetimes records for calculating
71 * t1 and t2 (min/max).
72 */
73 u_int32_t renew, rebind, prefer, valid;
74
20ae1aff 75 /* Client-requested valid and preferred lifetimes. */
5279b8f3
DH
76 u_int32_t client_valid, client_prefer;
77
78 /* Chosen values to transmit for valid and preferred lifetimes. */
79 u_int32_t send_valid, send_prefer;
80
80c9fdb0
FD
81 /* Preferred prefix length (-1 is any). */
82 int preflen;
83
20ae1aff 84 /* Index into the data field that has been consumed. */
5279b8f3
DH
85 unsigned cursor;
86
a7341359
SR
87 /* Space for the on commit statements for a fixed host */
88 struct on_star on_star;
89
5279b8f3
DH
90 union reply_buffer {
91 unsigned char data[65536];
92 struct dhcpv6_packet reply;
93 } buf;
94};
95
b31fe1d5 96/*
98bd7ca0
DH
97 * Prototypes local to this file.
98 */
8eab95f2
DH
99static int get_encapsulated_IA_state(struct option_state **enc_opt_state,
100 struct data_string *enc_opt_data,
101 struct packet *packet,
102 struct option_cache *oc,
103 int offset);
98bd7ca0 104static void build_dhcpv6_reply(struct data_string *, struct packet *);
bd72740e
FD
105static isc_result_t shared_network_from_packet6(struct shared_network **shared,
106 struct packet *packet);
5279b8f3
DH
107static void seek_shared_host(struct host_decl **hp,
108 struct shared_network *shared);
109static isc_boolean_t fixed_matches_shared(struct host_decl *host,
110 struct shared_network *shared);
1d9774ab
FD
111static isc_result_t reply_process_ia_na(struct reply_state *reply,
112 struct option_cache *ia);
80c9fdb0
FD
113static isc_result_t reply_process_ia_ta(struct reply_state *reply,
114 struct option_cache *ia);
5279b8f3
DH
115static isc_result_t reply_process_addr(struct reply_state *reply,
116 struct option_cache *addr);
117static isc_boolean_t address_is_owned(struct reply_state *reply,
118 struct iaddr *addr);
783259b1
FD
119static isc_boolean_t temporary_is_available(struct reply_state *reply,
120 struct iaddr *addr);
80c9fdb0 121static isc_result_t find_client_temporaries(struct reply_state *reply);
5279b8f3
DH
122static isc_result_t reply_process_try_addr(struct reply_state *reply,
123 struct iaddr *addr);
124static isc_result_t find_client_address(struct reply_state *reply);
125static isc_result_t reply_process_is_addressed(struct reply_state *reply,
126 struct binding_scope **scope,
127 struct group *group);
128static isc_result_t reply_process_send_addr(struct reply_state *reply,
129 struct iaddr *addr);
1d17db44
FD
130static struct iasubopt *lease_compare(struct iasubopt *alpha,
131 struct iasubopt *beta);
80c9fdb0
FD
132static isc_result_t reply_process_ia_pd(struct reply_state *reply,
133 struct option_cache *ia_pd);
34711bb7 134static struct group *find_group_by_prefix(struct reply_state *reply);
80c9fdb0
FD
135static isc_result_t reply_process_prefix(struct reply_state *reply,
136 struct option_cache *pref);
137static isc_boolean_t prefix_is_owned(struct reply_state *reply,
138 struct iaddrcidrnet *pref);
139static isc_result_t find_client_prefix(struct reply_state *reply);
140static isc_result_t reply_process_try_prefix(struct reply_state *reply,
141 struct iaddrcidrnet *pref);
142static isc_result_t reply_process_is_prefixed(struct reply_state *reply,
80c9fdb0
FD
143 struct binding_scope **scope,
144 struct group *group);
145static isc_result_t reply_process_send_prefix(struct reply_state *reply,
146 struct iaddrcidrnet *pref);
1d17db44
FD
147static struct iasubopt *prefix_compare(struct reply_state *reply,
148 struct iasubopt *alpha,
149 struct iasubopt *beta);
ad80055f
SR
150static void schedule_lease_timeout_reply(struct reply_state *reply);
151
1a006ff6
TM
152static int eval_prefix_mode(int thislen, int preflen, int prefix_mode);
153static isc_result_t pick_v6_prefix_helper(struct reply_state *reply,
154 int prefix_mode);
155
b31fe1d5
TM
156static void unicast_reject(struct data_string *reply_ret, struct packet *packet,
157 const struct data_string *client_id,
158 const struct data_string *server_id);
159
160static isc_boolean_t is_unicast_option_defined(struct packet *packet);
161static isc_result_t shared_network_from_requested_addr (struct shared_network
162 **shared,
163 struct packet* packet);
164static isc_result_t get_first_ia_addr_val (struct packet* packet, int addr_type,
165 struct iaddr* iaddr);
166
ad80055f
SR
167/*
168 * Schedule lease timeouts for all of the iasubopts in the reply.
169 * This is currently used to schedule timeouts for soft leases.
170 */
171
172static void
173schedule_lease_timeout_reply(struct reply_state *reply) {
174 struct iasubopt *tmp;
175 int i;
176
177 /* sanity check the reply */
178 if ((reply == NULL) || (reply->ia == NULL) || (reply->ia->iasubopt == NULL))
179 return;
180
181 /* walk through the list, scheduling as we go */
182 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
183 tmp = reply->ia->iasubopt[i];
184 schedule_lease_timeout(tmp->ipv6_pool);
185 }
186}
187
98bd7ca0
DH
188/*
189 * This function returns the time since DUID time start for the
190 * given time_t value.
191 */
192static u_int32_t
193duid_time(time_t when) {
194 /*
195 * This time is modulo 2^32.
196 */
197 while ((when - DUID_TIME_EPOCH) > 4294967295u) {
198 /* use 2^31 to avoid spurious compiler warnings */
199 when -= 2147483648u;
200 when -= 2147483648u;
201 }
202
203 return when - DUID_TIME_EPOCH;
204}
205
206
b31fe1d5 207/*
98bd7ca0
DH
208 * Server DUID.
209 *
210 * This must remain the same for the lifetime of this server, because
211 * clients return the server DUID that we sent them in Request packets.
212 *
213 * We pick the server DUID like this:
214 *
b31fe1d5 215 * 1. Check dhcpd.conf - any value the administrator has configured
98bd7ca0 216 * overrides any possible values.
b31fe1d5 217 * 2. Check the leases.txt - we want to use the previous value if
98bd7ca0
DH
218 * possible.
219 * 3. Check if dhcpd.conf specifies a type of server DUID to use,
220 * and generate that type.
221 * 4. Generate a type 1 (time + hardware address) DUID.
222 */
223static struct data_string server_duid;
224
225/*
226 * Check if the server_duid has been set.
227 */
783259b1 228isc_boolean_t
98bd7ca0
DH
229server_duid_isset(void) {
230 return (server_duid.data != NULL);
231}
232
233/*
234 * Return the server_duid.
235 */
236void
237copy_server_duid(struct data_string *ds, const char *file, int line) {
238 data_string_copy(ds, &server_duid, file, line);
239}
240
241/*
242 * Set the server DUID to a specified value. This is used when
243 * the server DUID is stored in persistent memory (basically the
244 * leases.txt file).
245 */
246void
247set_server_duid(struct data_string *new_duid) {
248 /* INSIST(new_duid != NULL); */
249 /* INSIST(new_duid->data != NULL); */
250
251 if (server_duid_isset()) {
252 data_string_forget(&server_duid, MDL);
253 }
254 data_string_copy(&server_duid, new_duid, MDL);
255}
256
257
258/*
259 * Set the server DUID based on the D6O_SERVERID option. This handles
b31fe1d5 260 * the case where the administrator explicitly put it in the dhcpd.conf
98bd7ca0
DH
261 * file.
262 */
263isc_result_t
264set_server_duid_from_option(void) {
265 struct option_state *opt_state;
266 struct option_cache *oc;
267 struct data_string option_duid;
268 isc_result_t ret_val;
269
270 opt_state = NULL;
271 if (!option_state_allocate(&opt_state, MDL)) {
272 log_fatal("No memory for server DUID.");
273 }
274
275 execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
a7341359
SR
276 opt_state, &global_scope, root_group,
277 NULL, NULL);
98bd7ca0
DH
278
279 oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
280 if (oc == NULL) {
281 ret_val = ISC_R_NOTFOUND;
282 } else {
283 memset(&option_duid, 0, sizeof(option_duid));
783259b1
FD
284 if (!evaluate_option_cache(&option_duid, NULL, NULL, NULL,
285 opt_state, NULL, &global_scope,
98bd7ca0
DH
286 oc, MDL)) {
287 ret_val = ISC_R_UNEXPECTED;
288 } else {
289 set_server_duid(&option_duid);
290 data_string_forget(&option_duid, MDL);
291 ret_val = ISC_R_SUCCESS;
292 }
293 }
294
295 option_state_dereference(&opt_state, MDL);
296
297 return ret_val;
298}
299
300/*
301 * DUID layout, as defined in RFC 3315, section 9.
b31fe1d5 302 *
98bd7ca0
DH
303 * We support type 1 (hardware address plus time) and type 3 (hardware
304 * address).
305 *
b31fe1d5 306 * We can support type 2 for specific vendors in the future, if they
98bd7ca0
DH
307 * publish the specification. And of course there may be additional
308 * types later.
309 */
310static int server_duid_type = DUID_LLT;
311
b31fe1d5 312/*
98bd7ca0
DH
313 * Set the DUID type.
314 */
315void
316set_server_duid_type(int type) {
317 server_duid_type = type;
318}
319
320/*
b31fe1d5 321 * Generate a new server DUID. This is done if there was no DUID in
98bd7ca0
DH
322 * the leases.txt or in the dhcpd.conf file.
323 */
324isc_result_t
325generate_new_server_duid(void) {
326 struct interface_info *p;
327 u_int32_t time_val;
328 struct data_string generated_duid;
329
330 /*
331 * Verify we have a type that we support.
332 */
333 if ((server_duid_type != DUID_LL) && (server_duid_type != DUID_LLT)) {
334 log_error("Invalid DUID type %d specified, "
335 "only LL and LLT types supported", server_duid_type);
98bf1607 336 return DHCP_R_INVALIDARG;
98bd7ca0
DH
337 }
338
339 /*
340 * Find an interface with a hardware address.
341 * Any will do. :)
342 */
343 for (p = interfaces; p != NULL; p = p->next) {
344 if (p->hw_address.hlen > 0) {
345 break;
346 }
347 }
348 if (p == NULL) {
349 return ISC_R_UNEXPECTED;
350 }
351
352 /*
353 * Build our DUID.
354 */
355 memset(&generated_duid, 0, sizeof(generated_duid));
356 if (server_duid_type == DUID_LLT) {
357 time_val = duid_time(time(NULL));
358 generated_duid.len = 8 + p->hw_address.hlen - 1;
783259b1 359 if (!buffer_allocate(&generated_duid.buffer,
98bd7ca0
DH
360 generated_duid.len, MDL)) {
361 log_fatal("No memory for server DUID.");
362 }
363 generated_duid.data = generated_duid.buffer->data;
364 putUShort(generated_duid.buffer->data, DUID_LLT);
783259b1 365 putUShort(generated_duid.buffer->data + 2,
98bd7ca0
DH
366 p->hw_address.hbuf[0]);
367 putULong(generated_duid.buffer->data + 4, time_val);
783259b1 368 memcpy(generated_duid.buffer->data + 8,
98bd7ca0
DH
369 p->hw_address.hbuf+1, p->hw_address.hlen-1);
370 } else if (server_duid_type == DUID_LL) {
371 generated_duid.len = 4 + p->hw_address.hlen - 1;
783259b1 372 if (!buffer_allocate(&generated_duid.buffer,
98bd7ca0
DH
373 generated_duid.len, MDL)) {
374 log_fatal("No memory for server DUID.");
375 }
376 generated_duid.data = generated_duid.buffer->data;
377 putUShort(generated_duid.buffer->data, DUID_LL);
783259b1 378 putUShort(generated_duid.buffer->data + 2,
98bd7ca0 379 p->hw_address.hbuf[0]);
783259b1 380 memcpy(generated_duid.buffer->data + 4,
98bd7ca0
DH
381 p->hw_address.hbuf+1, p->hw_address.hlen-1);
382 } else {
383 log_fatal("Unsupported server DUID type %d.", server_duid_type);
783259b1 384 }
98bd7ca0
DH
385
386 set_server_duid(&generated_duid);
387 data_string_forget(&generated_duid, MDL);
388
389 return ISC_R_SUCCESS;
390}
391
392/*
393 * Get the client identifier from the packet.
394 */
395isc_result_t
396get_client_id(struct packet *packet, struct data_string *client_id) {
397 struct option_cache *oc;
398
399 /*
400 * Verify our client_id structure is empty.
401 */
402 if ((client_id->data != NULL) || (client_id->len != 0)) {
98bf1607 403 return DHCP_R_INVALIDARG;
98bd7ca0
DH
404 }
405
406 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
407 if (oc == NULL) {
408 return ISC_R_NOTFOUND;
409 }
410
783259b1 411 if (!evaluate_option_cache(client_id, packet, NULL, NULL,
98bd7ca0
DH
412 packet->options, NULL,
413 &global_scope, oc, MDL)) {
414 return ISC_R_FAILURE;
415 }
416
417 return ISC_R_SUCCESS;
418}
419
420/*
421 * Message validation, defined in RFC 3315, sections 15.2, 15.5, 15.7:
422 *
423 * Servers MUST discard any Solicit messages that do not include a
424 * Client Identifier option or that do include a Server Identifier
425 * option.
426 */
427int
428valid_client_msg(struct packet *packet, struct data_string *client_id) {
429 int ret_val;
430 struct option_cache *oc;
431 struct data_string data;
432
433 ret_val = 0;
434 memset(client_id, 0, sizeof(*client_id));
435 memset(&data, 0, sizeof(data));
436
437 switch (get_client_id(packet, client_id)) {
438 case ISC_R_SUCCESS:
439 break;
440 case ISC_R_NOTFOUND:
441 log_debug("Discarding %s from %s; "
783259b1 442 "client identifier missing",
98bd7ca0
DH
443 dhcpv6_type_names[packet->dhcpv6_msg_type],
444 piaddr(packet->client_addr));
445 goto exit;
446 default:
447 log_error("Error processing %s from %s; "
448 "unable to evaluate Client Identifier",
449 dhcpv6_type_names[packet->dhcpv6_msg_type],
450 piaddr(packet->client_addr));
451 goto exit;
452 }
453
454 /*
455 * Required by RFC 3315, section 15.
456 */
457 if (packet->unicast) {
458 log_debug("Discarding %s from %s; packet sent unicast "
783259b1 459 "(CLIENTID %s)",
98bd7ca0
DH
460 dhcpv6_type_names[packet->dhcpv6_msg_type],
461 piaddr(packet->client_addr),
c382bc98 462 print_hex_1(client_id->len, client_id->data, 60));
98bd7ca0
DH
463 goto exit;
464 }
465
466
467 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
468 if (oc != NULL) {
469 if (evaluate_option_cache(&data, packet, NULL, NULL,
783259b1 470 packet->options, NULL,
98bd7ca0 471 &global_scope, oc, MDL)) {
783259b1 472 log_debug("Discarding %s from %s; "
98bd7ca0 473 "server identifier found "
783259b1 474 "(CLIENTID %s, SERVERID %s)",
98bd7ca0
DH
475 dhcpv6_type_names[packet->dhcpv6_msg_type],
476 piaddr(packet->client_addr),
783259b1 477 print_hex_1(client_id->len,
98bd7ca0
DH
478 client_id->data, 60),
479 print_hex_2(data.len,
480 data.data, 60));
481 } else {
783259b1 482 log_debug("Discarding %s from %s; "
98bd7ca0 483 "server identifier found "
783259b1 484 "(CLIENTID %s)",
98bd7ca0 485 dhcpv6_type_names[packet->dhcpv6_msg_type],
783259b1 486 print_hex_1(client_id->len,
98bd7ca0
DH
487 client_id->data, 60),
488 piaddr(packet->client_addr));
489 }
490 goto exit;
491 }
492
493 /* looks good */
494 ret_val = 1;
495
496exit:
497 if (data.len > 0) {
498 data_string_forget(&data, MDL);
499 }
500 if (!ret_val) {
501 if (client_id->len > 0) {
502 data_string_forget(client_id, MDL);
503 }
504 }
505 return ret_val;
506}
507
508/*
b31fe1d5 509 * Response validation, defined in RFC 3315, sections 15.4, 15.6, 15.8,
98bd7ca0
DH
510 * 15.9 (slightly different wording, but same meaning):
511 *
512 * Servers MUST discard any received Request message that meet any of
513 * the following conditions:
514 *
515 * - the message does not include a Server Identifier option.
516 * - the contents of the Server Identifier option do not match the
517 * server's DUID.
518 * - the message does not include a Client Identifier option.
519 */
520int
521valid_client_resp(struct packet *packet,
522 struct data_string *client_id,
c382bc98
SK
523 struct data_string *server_id)
524{
98bd7ca0
DH
525 int ret_val;
526 struct option_cache *oc;
527
528 /* INSIST((duid.data != NULL) && (duid.len > 0)); */
529
530 ret_val = 0;
531 memset(client_id, 0, sizeof(*client_id));
532 memset(server_id, 0, sizeof(*server_id));
533
534 switch (get_client_id(packet, client_id)) {
535 case ISC_R_SUCCESS:
536 break;
537 case ISC_R_NOTFOUND:
538 log_debug("Discarding %s from %s; "
783259b1 539 "client identifier missing",
98bd7ca0
DH
540 dhcpv6_type_names[packet->dhcpv6_msg_type],
541 piaddr(packet->client_addr));
542 goto exit;
543 default:
544 log_error("Error processing %s from %s; "
545 "unable to evaluate Client Identifier",
546 dhcpv6_type_names[packet->dhcpv6_msg_type],
547 piaddr(packet->client_addr));
548 goto exit;
549 }
550
551 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
552 if (oc == NULL) {
553 log_debug("Discarding %s from %s: "
783259b1 554 "server identifier missing (CLIENTID %s)",
98bd7ca0
DH
555 dhcpv6_type_names[packet->dhcpv6_msg_type],
556 piaddr(packet->client_addr),
557 print_hex_1(client_id->len, client_id->data, 60));
558 goto exit;
559 }
783259b1 560 if (!evaluate_option_cache(server_id, packet, NULL, NULL,
98bd7ca0
DH
561 packet->options, NULL,
562 &global_scope, oc, MDL)) {
563 log_error("Error processing %s from %s; "
564 "unable to evaluate Server Identifier (CLIENTID %s)",
565 dhcpv6_type_names[packet->dhcpv6_msg_type],
566 piaddr(packet->client_addr),
567 print_hex_1(client_id->len, client_id->data, 60));
568 goto exit;
569 }
783259b1 570 if ((server_duid.len != server_id->len) ||
98bd7ca0 571 (memcmp(server_duid.data, server_id->data, server_duid.len) != 0)) {
783259b1 572 log_debug("Discarding %s from %s; "
98bd7ca0 573 "not our server identifier "
783259b1 574 "(CLIENTID %s, SERVERID %s, server DUID %s)",
98bd7ca0
DH
575 dhcpv6_type_names[packet->dhcpv6_msg_type],
576 piaddr(packet->client_addr),
577 print_hex_1(client_id->len, client_id->data, 60),
578 print_hex_2(server_id->len, server_id->data, 60),
579 print_hex_3(server_duid.len, server_duid.data, 60));
580 goto exit;
581 }
582
583 /* looks good */
584 ret_val = 1;
585
586exit:
587 if (!ret_val) {
588 if (server_id->len > 0) {
589 data_string_forget(server_id, MDL);
590 }
591 if (client_id->len > 0) {
592 data_string_forget(client_id, MDL);
593 }
594 }
595 return ret_val;
596}
597
598/*
599 * Information request validation, defined in RFC 3315, section 15.12:
600 *
601 * Servers MUST discard any received Information-request message that
602 * meets any of the following conditions:
603 *
604 * - The message includes a Server Identifier option and the DUID in
605 * the option does not match the server's DUID.
606 *
607 * - The message includes an IA option.
608 */
609int
610valid_client_info_req(struct packet *packet, struct data_string *server_id) {
611 int ret_val;
612 struct option_cache *oc;
c382bc98
SK
613 struct data_string client_id;
614 char client_id_str[80]; /* print_hex_1() uses maximum 60 characters,
615 plus a few more for extra information */
98bd7ca0
DH
616
617 ret_val = 0;
618 memset(server_id, 0, sizeof(*server_id));
0f750c4f 619 memset(&client_id, 0, sizeof(client_id));
98bd7ca0 620
c382bc98 621 /*
b31fe1d5 622 * Make a string that we can print out to give more
c382bc98
SK
623 * information about the client if we need to.
624 *
b31fe1d5
TM
625 * By RFC 3315, Section 18.1.5 clients SHOULD have a
626 * client-id on an Information-request packet, but it
c382bc98
SK
627 * is not strictly necessary.
628 */
629 if (get_client_id(packet, &client_id) == ISC_R_SUCCESS) {
630 snprintf(client_id_str, sizeof(client_id_str), " (CLIENTID %s)",
631 print_hex_1(client_id.len, client_id.data, 60));
632 data_string_forget(&client_id, MDL);
633 } else {
634 client_id_str[0] = '\0';
635 }
636
98bd7ca0
DH
637 /*
638 * Required by RFC 3315, section 15.
639 */
640 if (packet->unicast) {
c382bc98 641 log_debug("Discarding %s from %s; packet sent unicast%s",
98bd7ca0 642 dhcpv6_type_names[packet->dhcpv6_msg_type],
c382bc98 643 piaddr(packet->client_addr), client_id_str);
98bd7ca0
DH
644 goto exit;
645 }
646
647 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
648 if (oc != NULL) {
649 log_debug("Discarding %s from %s; "
783259b1 650 "IA_NA option present%s",
98bd7ca0 651 dhcpv6_type_names[packet->dhcpv6_msg_type],
c382bc98 652 piaddr(packet->client_addr), client_id_str);
98bd7ca0
DH
653 goto exit;
654 }
655 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
656 if (oc != NULL) {
657 log_debug("Discarding %s from %s; "
783259b1 658 "IA_TA option present%s",
98bd7ca0 659 dhcpv6_type_names[packet->dhcpv6_msg_type],
c382bc98 660 piaddr(packet->client_addr), client_id_str);
98bd7ca0
DH
661 goto exit;
662 }
1d9774ab
FD
663 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
664 if (oc != NULL) {
665 log_debug("Discarding %s from %s; "
783259b1 666 "IA_PD option present%s",
1d9774ab
FD
667 dhcpv6_type_names[packet->dhcpv6_msg_type],
668 piaddr(packet->client_addr), client_id_str);
669 goto exit;
670 }
98bd7ca0
DH
671
672 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
673 if (oc != NULL) {
783259b1 674 if (!evaluate_option_cache(server_id, packet, NULL, NULL,
98bd7ca0
DH
675 packet->options, NULL,
676 &global_scope, oc, MDL)) {
677 log_error("Error processing %s from %s; "
c382bc98 678 "unable to evaluate Server Identifier%s",
98bd7ca0 679 dhcpv6_type_names[packet->dhcpv6_msg_type],
c382bc98 680 piaddr(packet->client_addr), client_id_str);
98bd7ca0
DH
681 goto exit;
682 }
783259b1
FD
683 if ((server_duid.len != server_id->len) ||
684 (memcmp(server_duid.data, server_id->data,
98bd7ca0 685 server_duid.len) != 0)) {
783259b1 686 log_debug("Discarding %s from %s; "
98bd7ca0 687 "not our server identifier "
783259b1 688 "(SERVERID %s, server DUID %s)%s",
98bd7ca0
DH
689 dhcpv6_type_names[packet->dhcpv6_msg_type],
690 piaddr(packet->client_addr),
783259b1 691 print_hex_1(server_id->len,
98bd7ca0 692 server_id->data, 60),
783259b1 693 print_hex_2(server_duid.len,
c382bc98
SK
694 server_duid.data, 60),
695 client_id_str);
98bd7ca0
DH
696 goto exit;
697 }
698 }
699
700 /* looks good */
701 ret_val = 1;
702
703exit:
704 if (!ret_val) {
705 if (server_id->len > 0) {
706 data_string_forget(server_id, MDL);
707 }
708 }
709 return ret_val;
710}
711
b31fe1d5 712/*
98bd7ca0
DH
713 * Options that we want to send, in addition to what was requested
714 * via the ORO.
715 */
716static const int required_opts[] = {
717 D6O_CLIENTID,
718 D6O_SERVERID,
719 D6O_STATUS_CODE,
76db44f9 720 D6O_PREFERENCE,
98bd7ca0
DH
721 0
722};
723static const int required_opts_solicit[] = {
724 D6O_CLIENTID,
725 D6O_SERVERID,
726 D6O_IA_NA,
727 D6O_IA_TA,
1d9774ab 728 D6O_IA_PD,
98bd7ca0
DH
729 D6O_RAPID_COMMIT,
730 D6O_STATUS_CODE,
98bd7ca0 731 D6O_RECONF_ACCEPT,
76db44f9 732 D6O_PREFERENCE,
98bd7ca0
DH
733 0
734};
2b964ac0
FD
735static const int required_opts_agent[] = {
736 D6O_INTERFACE_ID,
737 D6O_RELAY_MSG,
738 0
739};
80c9fdb0 740static const int required_opts_IA[] = {
1d9774ab
FD
741 D6O_IAADDR,
742 D6O_STATUS_CODE,
1d9774ab
FD
743 0
744};
745static const int required_opts_IA_PD[] = {
746 D6O_IAPREFIX,
747 D6O_STATUS_CODE,
1d9774ab
FD
748 0
749};
98bd7ca0
DH
750static const int required_opts_STATUS_CODE[] = {
751 D6O_STATUS_CODE,
752 0
753};
754
b31fe1d5
TM
755static const int unicast_reject_opts[] = {
756 D6O_CLIENTID,
757 D6O_SERVERID,
758 D6O_STATUS_CODE,
759 0
760};
761
762
98bd7ca0 763/*
8eab95f2
DH
764 * Extracts from packet contents an IA_* option, storing the IA structure
765 * in its entirety in enc_opt_data, and storing any decoded DHCPv6 options
766 * in enc_opt_state for later lookup and evaluation. The 'offset' indicates
767 * where in the IA_* the DHCPv6 options commence.
98bd7ca0
DH
768 */
769static int
783259b1 770get_encapsulated_IA_state(struct option_state **enc_opt_state,
98bd7ca0
DH
771 struct data_string *enc_opt_data,
772 struct packet *packet,
8eab95f2
DH
773 struct option_cache *oc,
774 int offset)
c382bc98 775{
b31fe1d5 776 /*
98bd7ca0
DH
777 * Get the raw data for the encapsulated options.
778 */
779 memset(enc_opt_data, 0, sizeof(*enc_opt_data));
780 if (!evaluate_option_cache(enc_opt_data, packet,
781 NULL, NULL, packet->options, NULL,
782 &global_scope, oc, MDL)) {
783 log_error("get_encapsulated_IA_state: "
784 "error evaluating raw option.");
785 return 0;
786 }
8eab95f2 787 if (enc_opt_data->len < offset) {
98bd7ca0
DH
788 log_error("get_encapsulated_IA_state: raw option too small.");
789 data_string_forget(enc_opt_data, MDL);
790 return 0;
791 }
792
793 /*
b31fe1d5 794 * Now create the option state structure, and pass it to the
98bd7ca0
DH
795 * function that parses options.
796 */
797 *enc_opt_state = NULL;
798 if (!option_state_allocate(enc_opt_state, MDL)) {
799 log_error("get_encapsulated_IA_state: no memory for options.");
800 data_string_forget(enc_opt_data, MDL);
801 return 0;
802 }
783259b1 803 if (!parse_option_buffer(*enc_opt_state,
b31fe1d5 804 enc_opt_data->data + offset,
8eab95f2 805 enc_opt_data->len - offset,
98bd7ca0
DH
806 &dhcpv6_universe)) {
807 log_error("get_encapsulated_IA_state: error parsing options.");
808 option_state_dereference(enc_opt_state, MDL);
809 data_string_forget(enc_opt_data, MDL);
810 return 0;
811 }
812
813 return 1;
814}
815
816static int
817set_status_code(u_int16_t status_code, const char *status_message,
c382bc98
SK
818 struct option_state *opt_state)
819{
98bd7ca0
DH
820 struct data_string d;
821 int ret_val;
822
823 memset(&d, 0, sizeof(d));
824 d.len = sizeof(status_code) + strlen(status_message);
825 if (!buffer_allocate(&d.buffer, d.len, MDL)) {
826 log_fatal("set_status_code: no memory for status code.");
827 }
828 d.data = d.buffer->data;
829 putUShort(d.buffer->data, status_code);
b31fe1d5 830 memcpy(d.buffer->data + sizeof(status_code),
98bd7ca0 831 status_message, d.len - sizeof(status_code));
b31fe1d5
TM
832 if (!save_option_buffer(&dhcpv6_universe, opt_state,
833 d.buffer, (unsigned char *)d.data, d.len,
98bd7ca0
DH
834 D6O_STATUS_CODE, 0)) {
835 log_error("set_status_code: error saving status code.");
836 ret_val = 0;
837 } else {
838 ret_val = 1;
839 }
840 data_string_forget(&d, MDL);
841 return ret_val;
842}
843
250f7134
SR
844void check_pool6_threshold(struct reply_state *reply,
845 struct iasubopt *lease)
846{
847 struct ipv6_pond *pond;
fb98e02e
TM
848 isc_uint64_t used, count, high_threshold;
849 int poolhigh = 0, poollow = 0;
250f7134
SR
850 char *shared_name = "no name";
851 char tmp_addr[INET6_ADDRSTRLEN];
852
853 if ((lease->ipv6_pool == NULL) || (lease->ipv6_pool->ipv6_pond == NULL))
854 return;
855 pond = lease->ipv6_pool->ipv6_pond;
856
fb98e02e
TM
857 /* If the address range is too large to track, just skip all this. */
858 if (pond->jumbo_range == 1) {
859 return;
860 }
861
250f7134
SR
862 count = pond->num_total;
863 used = pond->num_active;
864
fb98e02e
TM
865 /* get network name for logging */
866 if ((pond->shared_network != NULL) &&
867 (pond->shared_network->name != NULL)) {
868 shared_name = pond->shared_network->name;
869 }
870
250f7134
SR
871 /* The logged flag indicates if we have already crossed the high
872 * threshold and emitted a log message. If it is set we check to
873 * see if we have re-crossed the low threshold and need to reset
874 * things. When we cross the high threshold we determine what
875 * the low threshold is and save it into the low_threshold value.
876 * When we cross that threshold we reset the logged flag and
877 * the low_threshold to 0 which allows the high threshold message
878 * to be emitted once again.
879 * if we haven't recrossed the boundry we don't need to do anything.
880 */
881 if (pond->logged !=0) {
882 if (used <= pond->low_threshold) {
883 pond->low_threshold = 0;
884 pond->logged = 0;
885 log_error("Pool threshold reset - shared subnet: %s; "
fb98e02e 886 "address: %s; low threshold %llu/%llu.",
250f7134
SR
887 shared_name,
888 inet_ntop(AF_INET6, &lease->addr,
889 tmp_addr, sizeof(tmp_addr)),
890 used, count);
891 }
892 return;
893 }
894
895 /* find the high threshold */
896 if (get_option_int(&poolhigh, &server_universe, reply->packet, NULL,
897 NULL, reply->packet->options, reply->opt_state,
898 reply->opt_state, &lease->scope,
899 SV_LOG_THRESHOLD_HIGH, MDL) == 0) {
900 /* no threshold bail out */
901 return;
902 }
903
904 /* We do have a threshold for this pool, see if its valid */
905 if ((poolhigh <= 0) || (poolhigh > 100)) {
906 /* not valid */
907 return;
908 }
909
910 /* we have a valid value, have we exceeded it */
fb98e02e 911 high_threshold = FIND_POND6_PERCENT(count, poolhigh);
250f7134
SR
912 if (used < high_threshold) {
913 /* nope, no more to do */
914 return;
915 }
916
917 /* we've exceeded it, output a message */
250f7134 918 log_error("Pool threshold exceeded - shared subnet: %s; "
fb98e02e 919 "address: %s; high threshold %d%% %llu/%llu.",
250f7134
SR
920 shared_name,
921 inet_ntop(AF_INET6, &lease->addr, tmp_addr, sizeof(tmp_addr)),
922 poolhigh, used, count);
923
924 /* handle the low threshold now, if we don't
925 * have one we default to 0. */
926 if ((get_option_int(&poollow, &server_universe, reply->packet, NULL,
927 NULL, reply->packet->options, reply->opt_state,
928 reply->opt_state, &lease->scope,
929 SV_LOG_THRESHOLD_LOW, MDL) == 0) ||
930 (poollow > 100)) {
931 poollow = 0;
932 }
933
934 /*
935 * If the low theshold is higher than the high threshold we continue to log
936 * If it isn't then we set the flag saying we already logged and determine
937 * what the reset threshold is.
938 */
939 if (poollow < poolhigh) {
940 pond->logged = 1;
fb98e02e 941 pond->low_threshold = FIND_POND6_PERCENT(count, poollow);
250f7134
SR
942 }
943}
944
98bd7ca0
DH
945/*
946 * We have a set of operations we do to set up the reply packet, which
947 * is the same for many message types.
948 */
949static int
950start_reply(struct packet *packet,
b31fe1d5 951 const struct data_string *client_id,
98bd7ca0
DH
952 const struct data_string *server_id,
953 struct option_state **opt_state,
c382bc98
SK
954 struct dhcpv6_packet *reply)
955{
98bd7ca0 956 struct option_cache *oc;
28868515 957 const unsigned char *server_id_data;
98bd7ca0
DH
958 int server_id_len;
959
98bd7ca0
DH
960 /*
961 * Build our option state for reply.
962 */
963 *opt_state = NULL;
964 if (!option_state_allocate(opt_state, MDL)) {
965 log_error("start_reply: no memory for option_state.");
966 return 0;
967 }
5279b8f3
DH
968 execute_statements_in_scope(NULL, packet, NULL, NULL,
969 packet->options, *opt_state,
a7341359 970 &global_scope, root_group, NULL, NULL);
98bd7ca0 971
5279b8f3
DH
972 /*
973 * A small bit of special handling for Solicit messages.
974 *
975 * We could move the logic into a flag, but for now just check
976 * explicitly.
977 */
978 if (packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
979 reply->msg_type = DHCPV6_ADVERTISE;
980
981 /*
982 * If:
983 * - this message type supports rapid commit (Solicit), and
984 * - the server is configured to supply a rapid commit, and
985 * - the client requests a rapid commit,
986 * Then we add a rapid commit option, and send Reply (instead
987 * of an Advertise).
988 */
989 oc = lookup_option(&dhcpv6_universe,
990 *opt_state, D6O_RAPID_COMMIT);
991 if (oc != NULL) {
992 oc = lookup_option(&dhcpv6_universe,
993 packet->options, D6O_RAPID_COMMIT);
994 if (oc != NULL) {
a8ac02a4 995 /* Rapid-commit in action. */
5279b8f3 996 reply->msg_type = DHCPV6_REPLY;
a8ac02a4
FD
997 } else {
998 /* Don't want a rapid-commit in advertise. */
999 delete_option(&dhcpv6_universe,
1000 *opt_state, D6O_RAPID_COMMIT);
5279b8f3
DH
1001 }
1002 }
a8ac02a4 1003 } else {
5279b8f3 1004 reply->msg_type = DHCPV6_REPLY;
a8ac02a4
FD
1005 /* Delete the rapid-commit from the sent options. */
1006 oc = lookup_option(&dhcpv6_universe,
1007 *opt_state, D6O_RAPID_COMMIT);
1008 if (oc != NULL) {
1009 delete_option(&dhcpv6_universe,
1010 *opt_state, D6O_RAPID_COMMIT);
1011 }
1012 }
5279b8f3 1013
b31fe1d5 1014 /*
5279b8f3
DH
1015 * Use the client's transaction identifier for the reply.
1016 */
b31fe1d5 1017 memcpy(reply->transaction_id, packet->dhcpv6_transaction_id,
5279b8f3
DH
1018 sizeof(reply->transaction_id));
1019
b31fe1d5 1020 /*
98bd7ca0
DH
1021 * RFC 3315, section 18.2 says we need server identifier and
1022 * client identifier.
1023 *
1024 * If the server ID is defined via the configuration file, then
b31fe1d5 1025 * it will already be present in the option state at this point,
98bd7ca0
DH
1026 * so we don't need to set it.
1027 *
b31fe1d5 1028 * If we have a server ID passed in from the caller,
98bd7ca0
DH
1029 * use that, otherwise use the global DUID.
1030 */
1031 oc = lookup_option(&dhcpv6_universe, *opt_state, D6O_SERVERID);
1032 if (oc == NULL) {
1033 if (server_id == NULL) {
28868515 1034 server_id_data = server_duid.data;
98bd7ca0
DH
1035 server_id_len = server_duid.len;
1036 } else {
28868515 1037 server_id_data = server_id->data;
98bd7ca0
DH
1038 server_id_len = server_id->len;
1039 }
b31fe1d5 1040 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
28868515
SK
1041 NULL, (unsigned char *)server_id_data,
1042 server_id_len, D6O_SERVERID, 0)) {
98bd7ca0
DH
1043 log_error("start_reply: "
1044 "error saving server identifier.");
1045 return 0;
1046 }
1047 }
1048
1049 if (client_id->buffer != NULL) {
b31fe1d5
TM
1050 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
1051 client_id->buffer,
1052 (unsigned char *)client_id->data,
1053 client_id->len,
98bd7ca0
DH
1054 D6O_CLIENTID, 0)) {
1055 log_error("start_reply: error saving "
1056 "client identifier.");
1057 return 0;
1058 }
1059 }
1060
1061 /*
1062 * If the client accepts reconfiguration, let it know that we
1063 * will send them.
1064 *
1065 * Note: we don't actually do this yet, but DOCSIS requires we
1066 * claim to.
1067 */
1068 oc = lookup_option(&dhcpv6_universe, packet->options,
1069 D6O_RECONF_ACCEPT);
1070 if (oc != NULL) {
1071 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
b31fe1d5 1072 NULL, (unsigned char *)"", 0,
28868515 1073 D6O_RECONF_ACCEPT, 0)) {
98bd7ca0
DH
1074 log_error("start_reply: "
1075 "error saving RECONF_ACCEPT option.");
1076 option_state_dereference(opt_state, MDL);
1077 return 0;
1078 }
1079 }
1080
98bd7ca0
DH
1081 return 1;
1082}
1083
1084/*
5279b8f3 1085 * Try to get the IPv6 address the client asked for from the
98bd7ca0
DH
1086 * pool.
1087 *
1088 * addr is the result (should be a pointer to NULL on entry)
1089 * pool is the pool to search in
1090 * requested_addr is the address the client wants
1091 */
1092static isc_result_t
1d17db44 1093try_client_v6_address(struct iasubopt **addr,
98bd7ca0 1094 struct ipv6_pool *pool,
c382bc98
SK
1095 const struct data_string *requested_addr)
1096{
98bd7ca0
DH
1097 struct in6_addr tmp_addr;
1098 isc_result_t result;
98bd7ca0
DH
1099
1100 if (requested_addr->len < sizeof(tmp_addr)) {
98bf1607 1101 return DHCP_R_INVALIDARG;
98bd7ca0
DH
1102 }
1103 memcpy(&tmp_addr, requested_addr->data, sizeof(tmp_addr));
1104 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
1105 return ISC_R_FAILURE;
1106 }
1107
1aa0fe5e
DH
1108 /*
1109 * The address is not covered by this (or possibly any) dynamic
1110 * range.
1111 */
9322442f 1112 if (!ipv6_in_pool(&tmp_addr, pool)) {
1aa0fe5e 1113 return ISC_R_ADDRNOTAVAIL;
98bd7ca0
DH
1114 }
1115
1116 if (lease6_exists(pool, &tmp_addr)) {
1117 return ISC_R_ADDRINUSE;
1118 }
1119
1d17db44 1120 result = iasubopt_allocate(addr, MDL);
98bd7ca0
DH
1121 if (result != ISC_R_SUCCESS) {
1122 return result;
1123 }
1124 (*addr)->addr = tmp_addr;
9322442f 1125 (*addr)->plen = 0;
98bd7ca0 1126
5d89d60f
FD
1127 /* Default is soft binding for 2 minutes. */
1128 result = add_lease6(pool, *addr, cur_time + 120);
98bd7ca0 1129 if (result != ISC_R_SUCCESS) {
1d17db44 1130 iasubopt_dereference(addr, MDL);
98bd7ca0
DH
1131 }
1132 return result;
1133}
1134
01fa619f
SR
1135
1136/*!
98bd7ca0 1137 *
01fa619f
SR
1138 * \brief Get an IPv6 address for the client.
1139 *
1140 * Attempt to find a usable address for the client. We walk through
1141 * the ponds checking for permit and deny then through the pools
1142 * seeing if they have an available address.
1143 *
1144 * \param reply = the state structure for the current work on this request
1145 * if we create a lease we return it using reply->lease
1146 *
1147 * \return
1148 * ISC_R_SUCCESS = we were able to find an address and are returning a
1149 * pointer to the lease
1150 * ISC_R_NORESOURCES = there don't appear to be any free addresses. This
1151 * is probabalistic. We don't exhaustively try the
1152 * address range, instead we hash the duid and if
1153 * the address derived from the hash is in use we
1154 * hash the address. After a number of failures we
1155 * conclude the pool is basically full.
98bd7ca0 1156 */
b31fe1d5 1157static isc_result_t
01fa619f 1158pick_v6_address(struct reply_state *reply)
c382bc98 1159{
01fa619f
SR
1160 struct ipv6_pool *p = NULL;
1161 struct ipv6_pond *pond;
98bd7ca0
DH
1162 int i;
1163 int start_pool;
28868515 1164 unsigned int attempts;
1b5053b5 1165 char tmp_buf[INET6_ADDRSTRLEN];
01fa619f 1166 struct iasubopt **addr = &reply->lease;
fb98e02e
TM
1167 isc_uint64_t total = 0;
1168 isc_uint64_t active = 0;
1169 isc_uint64_t abandoned = 0;
1170 int jumbo_range = 0;
1171 char *shared_name = (reply->shared->name ?
1172 reply->shared->name : "(no name)");
98bd7ca0 1173
98bd7ca0 1174 /*
01fa619f
SR
1175 * Do a quick walk through of the ponds and pools
1176 * to see if we have any NA address pools
98bd7ca0 1177 */
01fa619f
SR
1178 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
1179 if (pond->ipv6_pools == NULL)
1180 continue;
1181
1182 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
1183 if (p->pool_type == D6O_IA_NA)
1184 break;
80c9fdb0 1185 }
01fa619f 1186 if (p != NULL)
80c9fdb0 1187 break;
80c9fdb0 1188 }
98bd7ca0 1189
01fa619f
SR
1190 /* If we get here and p is NULL we have no useful pools */
1191 if (p == NULL) {
1192 log_debug("Unable to pick client address: "
1193 "no IPv6 pools on this shared network");
1194 return ISC_R_NORESOURCES;
1195 }
b31fe1d5 1196
98bd7ca0 1197 /*
01fa619f
SR
1198 * We have at least one pool that could provide an address
1199 * Now we walk through the ponds and pools again and check
1200 * to see if the client is permitted and if an address is
1201 * available
b31fe1d5 1202 *
01fa619f
SR
1203 * Within a given pond we start looking at the last pool we
1204 * allocated from, unless it had a collision trying to allocate
1205 * an address. This will tend to move us into less-filled pools.
1206 */
1207
1208 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
f48dfdf1 1209 isc_result_t result = ISC_R_FAILURE;
fb98e02e 1210
01fa619f
SR
1211 if (((pond->prohibit_list != NULL) &&
1212 (permitted(reply->packet, pond->prohibit_list))) ||
1213 ((pond->permit_list != NULL) &&
1214 (!permitted(reply->packet, pond->permit_list))))
1215 continue;
1216
1217 start_pool = pond->last_ipv6_pool;
1218 i = start_pool;
1219 do {
1220 p = pond->ipv6_pools[i];
fb98e02e
TM
1221 if (p->pool_type == D6O_IA_NA) {
1222 result = create_lease6(p, addr, &attempts,
1223 &reply->ia->iaid_duid,
1224 cur_time + 120);
1225 if (result == ISC_R_SUCCESS) {
1226 /*
1227 * Record the pool used (or next one if
1228 * there was a collision).
1229 */
1230 if (attempts > 1) {
1231 i++;
1232 if (pond->ipv6_pools[i]
1233 == NULL) {
1234 i = 0;
1235 }
01fa619f 1236 }
98bd7ca0 1237
fb98e02e
TM
1238 pond->last_ipv6_pool = i;
1239
1240 log_debug("Picking pool address %s",
1241 inet_ntop(AF_INET6,
1242 &((*addr)->addr),
1243 tmp_buf, sizeof(tmp_buf)));
1244 return (ISC_R_SUCCESS);
1245 }
01fa619f 1246 }
98bd7ca0 1247
01fa619f
SR
1248 i++;
1249 if (pond->ipv6_pools[i] == NULL) {
1250 i = 0;
1251 }
1252 } while (i != start_pool);
fb98e02e
TM
1253
1254 if (result == ISC_R_NORESOURCES) {
1255 jumbo_range += pond->jumbo_range;
1256 total += pond->num_total;
1257 active += pond->num_active;
1258 abandoned += pond->num_abandoned;
1259 }
01fa619f 1260 }
98bd7ca0
DH
1261
1262 /*
1263 * If we failed to pick an IPv6 address from any of the subnets.
1264 * Presumably that means we have no addresses for the client.
1265 */
fb98e02e
TM
1266 if (jumbo_range != 0) {
1267 log_debug("Unable to pick client address: "
1268 "no addresses available - shared network %s: "
1269 " 2^64-1 < total, %llu active, %llu abandoned",
1270 shared_name, active - abandoned, abandoned);
1271 } else {
1272 log_debug("Unable to pick client address: "
1273 "no addresses available - shared network %s: "
1274 "%llu total, %llu active, %llu abandoned",
1275 shared_name, total, active - abandoned, abandoned);
1276 }
1277
98bd7ca0
DH
1278 return ISC_R_NORESOURCES;
1279}
1280
80c9fdb0
FD
1281/*
1282 * Try to get the IPv6 prefix the client asked for from the
1283 * prefix pool.
1284 *
1285 * pref is the result (should be a pointer to NULL on entry)
9322442f 1286 * pool is the prefix pool to search in
80c9fdb0
FD
1287 * requested_pref is the address the client wants
1288 */
1289static isc_result_t
1d17db44 1290try_client_v6_prefix(struct iasubopt **pref,
9322442f 1291 struct ipv6_pool *pool,
80c9fdb0
FD
1292 const struct data_string *requested_pref)
1293{
1294 u_int8_t tmp_plen;
1295 struct in6_addr tmp_pref;
1296 struct iaddr ia;
1297 isc_result_t result;
1298
1299 if (requested_pref->len < sizeof(tmp_plen) + sizeof(tmp_pref)) {
98bf1607 1300 return DHCP_R_INVALIDARG;
80c9fdb0
FD
1301 }
1302 tmp_plen = (int) requested_pref->data[0];
d19fa5a1
SR
1303 if ((tmp_plen < 3) || (tmp_plen > 128) ||
1304 ((int)tmp_plen != pool->units)) {
80c9fdb0
FD
1305 return ISC_R_FAILURE;
1306 }
1307 memcpy(&tmp_pref, requested_pref->data + 1, sizeof(tmp_pref));
1308 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
1309 return ISC_R_FAILURE;
1310 }
1311 ia.len = 16;
1312 memcpy(&ia.iabuf, &tmp_pref, 16);
1313 if (!is_cidr_mask_valid(&ia, (int) tmp_plen)) {
1314 return ISC_R_FAILURE;
1315 }
1316
d19fa5a1
SR
1317 if (!ipv6_in_pool(&tmp_pref, pool)) {
1318 return ISC_R_ADDRNOTAVAIL;
80c9fdb0
FD
1319 }
1320
9322442f 1321 if (prefix6_exists(pool, &tmp_pref, tmp_plen)) {
80c9fdb0
FD
1322 return ISC_R_ADDRINUSE;
1323 }
1324
1d17db44 1325 result = iasubopt_allocate(pref, MDL);
80c9fdb0
FD
1326 if (result != ISC_R_SUCCESS) {
1327 return result;
1328 }
9322442f 1329 (*pref)->addr = tmp_pref;
80c9fdb0
FD
1330 (*pref)->plen = tmp_plen;
1331
5d89d60f 1332 /* Default is soft binding for 2 minutes. */
9322442f 1333 result = add_lease6(pool, *pref, cur_time + 120);
80c9fdb0 1334 if (result != ISC_R_SUCCESS) {
1d17db44 1335 iasubopt_dereference(pref, MDL);
80c9fdb0
FD
1336 }
1337 return result;
1338}
1339
01fa619f 1340/*!
80c9fdb0 1341 *
01fa619f
SR
1342 * \brief Get an IPv6 prefix for the client.
1343 *
1a006ff6
TM
1344 * Attempt to find a usable prefix for the client. Based upon the prefix
1345 * length mode and the plen supplied by the client (if one), we make one
1346 * or more calls to pick_v6_prefix_helper() to find a prefix as follows:
1347 *
1348 * PLM_IGNORE or client specifies a plen of zero, use the first available
1349 * prefix regardless of it's length.
1350 *
1351 * PLM_PREFER – look for an exact match to client's plen first, if none
1352 * found, use the first available prefix of any length
1353 *
1354 * PLM_EXACT – look for an exact match first, if none found then fail. This
1355 * is the default behavior.
1356 *
1357 * PLM_MAXIMUM - look for an exact match first, then the first available whose
1358 * prefix length is less than client's plen, otherwise fail.
1359 *
1360 * PLM_MINIMUM - look for an exact match first, then the first available whose
1361 * prefix length is greater than client's plen, otherwise fail.
1362 *
1363 * Note that the selection mode is configurable at the global scope only via
1364 * prefix-len-mode.
01fa619f
SR
1365 *
1366 * \param reply = the state structure for the current work on this request
1367 * if we create a lease we return it using reply->lease
1368 *
1369 * \return
1370 * ISC_R_SUCCESS = we were able to find an prefix and are returning a
1371 * pointer to the lease
1372 * ISC_R_NORESOURCES = there don't appear to be any free addresses. This
1373 * is probabalistic. We don't exhaustively try the
1374 * address range, instead we hash the duid and if
1375 * the address derived from the hash is in use we
1376 * hash the address. After a number of failures we
1377 * conclude the pool is basically full.
80c9fdb0
FD
1378 */
1379static isc_result_t
1a006ff6
TM
1380pick_v6_prefix(struct reply_state *reply) {
1381 struct ipv6_pool *p = NULL;
1382 struct ipv6_pond *pond;
1383 int i;
1384 isc_result_t result;
80c9fdb0
FD
1385
1386 /*
01fa619f
SR
1387 * Do a quick walk through of the ponds and pools
1388 * to see if we have any prefix pools
1a006ff6 1389 */
01fa619f
SR
1390 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
1391 if (pond->ipv6_pools == NULL)
1392 continue;
1393
1394 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
1395 if (p->pool_type == D6O_IA_PD)
1396 break;
1397 }
1398 if (p != NULL)
1399 break;
1400 }
1401
1402 /* If we get here and p is NULL we have no useful pools */
1403 if (p == NULL) {
80c9fdb0 1404 log_debug("Unable to pick client prefix: "
9322442f 1405 "no IPv6 pools on this shared network");
80c9fdb0
FD
1406 return ISC_R_NORESOURCES;
1407 }
1408
1a006ff6
TM
1409 if (reply->preflen <= 0) {
1410 /* If we didn't get a plen (-1) or client plen is 0, then just
1411 * select first available (same as PLM_INGORE) */
1412 result = pick_v6_prefix_helper(reply, PLM_IGNORE);
1413 } else {
1414 switch (prefix_length_mode) {
1415 case PLM_PREFER:
1416 /* First we look for an exact match, if not found
1417 * then first available */
1418 result = pick_v6_prefix_helper(reply, PLM_EXACT);
1419 if (result != ISC_R_SUCCESS) {
1420 result = pick_v6_prefix_helper(reply,
1421 PLM_IGNORE);
1422 }
1423 break;
1424
1425 case PLM_EXACT:
1426 /* Match exactly or fail */
1427 result = pick_v6_prefix_helper(reply, PLM_EXACT);
1428 break;
1429
1430 case PLM_MINIMUM:
1431 case PLM_MAXIMUM:
1432 /* First we look for an exact match, if not found
1433 * then first available by mode */
1434 result = pick_v6_prefix_helper(reply, PLM_EXACT);
1435 if (result != ISC_R_SUCCESS) {
1436 result = pick_v6_prefix_helper(reply,
1437 prefix_length_mode);
1438 }
1439 break;
1440
1441 default:
1442 /* First available */
1443 result = pick_v6_prefix_helper(reply, PLM_IGNORE);
1444 break;
1445 }
1446 }
1447
1448 if (result == ISC_R_SUCCESS) {
1449 char tmp_buf[INET6_ADDRSTRLEN];
1450
1451 log_debug("Picking pool prefix %s/%u",
1452 inet_ntop(AF_INET6, &(reply->lease->addr),
1453 tmp_buf, sizeof(tmp_buf)),
1454 (unsigned)(reply->lease->plen));
1455 return (ISC_R_SUCCESS);
1456 }
1457
80c9fdb0 1458 /*
1a006ff6
TM
1459 * If we failed to pick an IPv6 prefix
1460 * Presumably that means we have no prefixes for the client.
1461 */
1462 log_debug("Unable to pick client prefix: no prefixes available");
1463 return ISC_R_NORESOURCES;
1464}
1465
1466/*!
1467 *
1468 * \brief Get an IPv6 prefix for the client based upon selection mode.
1469 *
1470 * We walk through the ponds checking for permit and deny. If a pond is
1471 * permissable to use, loop through its PD pools checking prefix lengths
1472 * against the client plen based on the prefix length mode, looking for
1473 * available prefixes.
1474 *
1475 * \param reply = the state structure for the current work on this request
1476 * if we create a lease we return it using reply->lease
1477 * \prefix_mode = selection mode to use
1478 *
1479 * \return
1480 * ISC_R_SUCCESS = we were able to find a prefix and are returning a
1481 * pointer to the lease
1482 * ISC_R_NORESOURCES = there don't appear to be any free addresses. This
1483 * is probabalistic. We don't exhaustively try the
1484 * address range, instead we hash the duid and if
1485 * the address derived from the hash is in use we
1486 * hash the address. After a number of failures we
1487 * conclude the pool is basically full.
1488 */
1489isc_result_t
1490pick_v6_prefix_helper(struct reply_state *reply, int prefix_mode) {
1491 struct ipv6_pool *p = NULL;
1492 struct ipv6_pond *pond;
1493 int i;
1494 unsigned int attempts;
1495 struct iasubopt **pref = &reply->lease;
01fa619f
SR
1496
1497 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
1498 if (((pond->prohibit_list != NULL) &&
1499 (permitted(reply->packet, pond->prohibit_list))) ||
1500 ((pond->permit_list != NULL) &&
1501 (!permitted(reply->packet, pond->permit_list))))
9322442f 1502 continue;
80c9fdb0 1503
01fa619f 1504 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
1a006ff6
TM
1505 if ((p->pool_type == D6O_IA_PD) &&
1506 (eval_prefix_mode(p->units, reply->preflen,
1507 prefix_mode) == 1) &&
1508 (create_prefix6(p, pref, &attempts,
1509 &reply->ia->iaid_duid,
1510 cur_time + 120) == ISC_R_SUCCESS)) {
01fa619f
SR
1511 return (ISC_R_SUCCESS);
1512 }
80c9fdb0
FD
1513 }
1514 }
1515
80c9fdb0
FD
1516 return ISC_R_NORESOURCES;
1517}
1518
1a006ff6
TM
1519/*!
1520 *
1521 * \brief Test a prefix length against another based on prefix length mode
1522 *
1523 * \param len - prefix length to test
1524 * \param preflen - preferred prefix length against which to test
1525 * \param prefix_mode - prefix selection mode with which to test
1526 *
1527 * Note that the case of preferred length of 0 is not short-cut here as it
1528 * is assumed to be done at a higher level.
1529 *
1530 * \return 1 if the given length is usable based upon mode and a preferred
1531 * length, 0 if not.
1532 */
1533int
1534eval_prefix_mode(int len, int preflen, int prefix_mode) {
1535 int use_it = 1;
1536 switch (prefix_mode) {
1537 case PLM_EXACT:
1538 use_it = (len == preflen);
1539 break;
1540 case PLM_MINIMUM:
1541 /* they asked for a prefix length no "shorter" than preflen */
1542 use_it = (len >= preflen);
1543 break;
1544 case PLM_MAXIMUM:
1545 /* they asked for a prefix length no "longer" than preflen */
1546 use_it = (len <= preflen);
1547 break;
1548 default:
1549 /* otherwise use it */
1550 break;
1551 }
1552
1553#if defined (DEBUG)
1554 log_debug("eval_prefix_mode: "
1555 "len %d, preflen %d, mode %s, use_it %d",
1556 len, preflen,
1557 prefix_length_modes.values[prefix_mode].name, use_it);
1558#endif
1559
1560 return (use_it);
1561}
1562
5279b8f3 1563/*
cbbd2714
SR
1564 *! \file server/dhcpv6.c
1565 *
1566 * \brief construct a reply containing information about a client's lease
1567 *
5279b8f3
DH
1568 * lease_to_client() is called from several messages to construct a
1569 * reply that contains all that we know about the client's correct lease
1570 * (or projected lease).
1571 *
20ae1aff 1572 * Solicit - "Soft" binding, ignore unknown addresses or bindings, just
5279b8f3
DH
1573 * send what we "may" give them on a request.
1574 *
1575 * Request - "Hard" binding, but ignore supplied addresses (just provide what
1576 * the client should really use).
1577 *
1578 * Renew - "Hard" binding, but client-supplied addresses are 'real'. Error
1579 * Rebind out any "wrong" addresses the client sends. This means we send
1580 * an empty IA_NA with a status code of NoBinding or NotOnLink or
1581 * possibly send the address with zeroed lifetimes.
1582 *
4f963ddc
FD
1583 * Information-Request - No binding.
1584 *
5279b8f3
DH
1585 * The basic structure is to traverse the client-supplied data first, and
1586 * validate and echo back any contents that can be. If the client-supplied
1587 * data does not error out (on renew/rebind as above), but we did not send
1588 * any addresses, attempt to allocate one.
cbbd2714
SR
1589 *
1590 * At the end of the this function we call commit_leases_timed() to
1591 * fsync and rotate the file as necessary. commit_leases_timed() will
1592 * check that we have written at least one lease to the file and that
1593 * some time has passed before doing any fsync or file rewrite so we
1594 * don't bother tracking if we did a write_ia during this function.
5279b8f3 1595 */
98bd7ca0 1596/* TODO: look at client hints for lease times */
cbbd2714 1597
98bd7ca0
DH
1598static void
1599lease_to_client(struct data_string *reply_ret,
b31fe1d5 1600 struct packet *packet,
98bd7ca0 1601 const struct data_string *client_id,
c382bc98
SK
1602 const struct data_string *server_id)
1603{
5279b8f3 1604 static struct reply_state reply;
98bd7ca0
DH
1605 struct option_cache *oc;
1606 struct data_string packet_oro;
01fa619f 1607 int i;
98bd7ca0 1608
355db4b6
SR
1609 memset(&packet_oro, 0, sizeof(packet_oro));
1610
5279b8f3 1611 /* Locate the client. */
bd72740e
FD
1612 if (shared_network_from_packet6(&reply.shared,
1613 packet) != ISC_R_SUCCESS)
1614 goto exit;
06eb8bab 1615
b31fe1d5 1616 /*
5279b8f3 1617 * Initialize the reply.
98bd7ca0 1618 */
5279b8f3
DH
1619 packet_reference(&reply.packet, packet, MDL);
1620 data_string_copy(&reply.client_id, client_id, MDL);
1621
1622 if (!start_reply(packet, client_id, server_id, &reply.opt_state,
1623 &reply.buf.reply))
98bd7ca0 1624 goto exit;
5279b8f3
DH
1625
1626 /* Set the write cursor to just past the reply header. */
1627 reply.cursor = REPLY_OPTIONS_INDEX;
98bd7ca0
DH
1628
1629 /*
1630 * Get the ORO from the packet, if any.
1631 */
1632 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ORO);
1633 if (oc != NULL) {
b31fe1d5
TM
1634 if (!evaluate_option_cache(&packet_oro, packet,
1635 NULL, NULL,
98bd7ca0
DH
1636 packet->options, NULL,
1637 &global_scope, oc, MDL)) {
1638 log_error("lease_to_client: error evaluating ORO.");
1639 goto exit;
1640 }
1641 }
1642
b31fe1d5 1643 /*
62a9eb91 1644 * Find a host record that matches the packet, if any, and is
5279b8f3 1645 * valid for the shared network the client is on.
98bd7ca0 1646 */
62a9eb91 1647 if (find_hosts6(&reply.host, packet, client_id, MDL)) {
01fa619f 1648 packet->known = 1;
bd72740e 1649 seek_shared_host(&reply.host, reply.shared);
01fa619f 1650 }
98bd7ca0 1651
80c9fdb0 1652 /* Process the client supplied IA's onto the reply buffer. */
5279b8f3
DH
1653 reply.ia_count = 0;
1654 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
d19fa5a1 1655
5279b8f3 1656 for (; oc != NULL ; oc = oc->next) {
9f1d5a2f
DH
1657 isc_result_t status;
1658
1d9774ab
FD
1659 /* Start counting resources (addresses) offered. */
1660 reply.client_resources = 0;
9322442f 1661 reply.resources_included = ISC_FALSE;
9f1d5a2f 1662
1d9774ab 1663 status = reply_process_ia_na(&reply, oc);
9f1d5a2f
DH
1664
1665 /*
1666 * We continue to try other IA's whether we can address
1667 * this one or not. Any other result is an immediate fail.
1668 */
1669 if ((status != ISC_R_SUCCESS) &&
1670 (status != ISC_R_NORESOURCES))
5279b8f3 1671 goto exit;
80c9fdb0
FD
1672 }
1673 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
1674 for (; oc != NULL ; oc = oc->next) {
1675 isc_result_t status;
1676
80c9fdb0
FD
1677 /* Start counting resources (addresses) offered. */
1678 reply.client_resources = 0;
9322442f 1679 reply.resources_included = ISC_FALSE;
80c9fdb0
FD
1680
1681 status = reply_process_ia_ta(&reply, oc);
1682
1683 /*
1684 * We continue to try other IA's whether we can address
1685 * this one or not. Any other result is an immediate fail.
1686 */
1687 if ((status != ISC_R_SUCCESS) &&
1688 (status != ISC_R_NORESOURCES))
1689 goto exit;
5279b8f3
DH
1690 }
1691
80c9fdb0 1692 /* Same for IA_PD's. */
9322442f 1693 reply.pd_count = 0;
80c9fdb0
FD
1694 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
1695 for (; oc != NULL ; oc = oc->next) {
1696 isc_result_t status;
1697
1698 /* Start counting resources (prefixes) offered. */
1699 reply.client_resources = 0;
9322442f 1700 reply.resources_included = ISC_FALSE;
80c9fdb0
FD
1701
1702 status = reply_process_ia_pd(&reply, oc);
1703
1704 /*
1705 * We continue to try other IA_PD's whether we can address
1706 * this one or not. Any other result is an immediate fail.
1707 */
1708 if ((status != ISC_R_SUCCESS) &&
1709 (status != ISC_R_NORESOURCES))
1710 goto exit;
80c9fdb0 1711 }
1d9774ab 1712
5279b8f3 1713 /*
4f963ddc
FD
1714 * Make no reply if we gave no resources and is not
1715 * for Information-Request.
5279b8f3 1716 */
7d6180be
DH
1717 if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
1718 if (reply.packet->dhcpv6_msg_type !=
1719 DHCPV6_INFORMATION_REQUEST)
1720 goto exit;
1721
1722 /*
1723 * Because we only execute statements on a per-IA basis,
1724 * we need to execute statements in any non-IA reply to
1725 * source configuration.
1726 */
1727 execute_statements_in_scope(NULL, reply.packet, NULL, NULL,
1728 reply.packet->options,
1729 reply.opt_state, &global_scope,
a7341359
SR
1730 reply.shared->group, root_group,
1731 NULL);
2267da84 1732
01fa619f
SR
1733 /* Execute statements from class scopes. */
1734 for (i = reply.packet->class_count; i > 0; i--) {
1735 execute_statements_in_scope(NULL, reply.packet,
1736 NULL, NULL,
1737 reply.packet->options,
1738 reply.opt_state,
1739 &global_scope,
1740 reply.packet->classes[i - 1]->group,
1741 reply.shared->group, NULL);
1742 }
1743
2267da84
DH
1744 /* Bring in any configuration from a host record. */
1745 if (reply.host != NULL)
a7341359
SR
1746 execute_statements_in_scope(NULL, reply.packet,
1747 NULL, NULL,
1748 reply.packet->options,
2267da84
DH
1749 reply.opt_state,
1750 &global_scope,
1751 reply.host->group,
a7341359 1752 reply.shared->group, NULL);
7d6180be 1753 }
98bd7ca0 1754
5279b8f3 1755 /*
9f1d5a2f
DH
1756 * RFC3315 section 17.2.2 (Solicit):
1757 *
1758 * If the server will not assign any addresses to any IAs in a
1759 * subsequent Request from the client, the server MUST send an
1760 * Advertise message to the client that includes only a Status
1761 * Code option with code NoAddrsAvail and a status message for
1762 * the user, a Server Identifier option with the server's DUID,
1763 * and a Client Identifier option with the client's DUID.
1764 *
388cba45
SR
1765 * This has been updated by an errata such that the server
1766 * can always send an IA.
1767 *
9f1d5a2f
DH
1768 * Section 18.2.1 (Request):
1769 *
1770 * If the server cannot assign any addresses to an IA in the
1771 * message from the client, the server MUST include the IA in
1772 * the Reply message with no addresses in the IA and a Status
1773 * Code option in the IA containing status code NoAddrsAvail.
1774 *
892379ec 1775 * Section 18.1.8 (Client Behavior):
9f1d5a2f 1776 *
892379ec
FD
1777 * Leave unchanged any information about addresses the client has
1778 * recorded in the IA but that were not included in the IA from
1779 * the server.
1780 * Sends a Renew/Rebind if the IA is not in the Reply message.
5279b8f3 1781 */
9f1d5a2f 1782
d19fa5a1
SR
1783 /*
1784 * Having stored the client's IA's, store any options that
1785 * will fit in the remaining space.
1786 */
1787 reply.cursor += store_options6((char *)reply.buf.data + reply.cursor,
1788 sizeof(reply.buf) - reply.cursor,
1789 reply.opt_state, reply.packet,
1790 required_opts_solicit,
1791 &packet_oro);
5279b8f3
DH
1792
1793 /* Return our reply to the caller. */
1794 reply_ret->len = reply.cursor;
1795 reply_ret->buffer = NULL;
1796 if (!buffer_allocate(&reply_ret->buffer, reply.cursor, MDL)) {
1797 log_fatal("No memory to store Reply.");
98bd7ca0 1798 }
5279b8f3
DH
1799 memcpy(reply_ret->buffer->data, reply.buf.data, reply.cursor);
1800 reply_ret->data = reply_ret->buffer->data;
1801
cbbd2714
SR
1802 /* If appropriate commit and rotate the lease file */
1803 (void) commit_leases_timed();
1804
5279b8f3
DH
1805 exit:
1806 /* Cleanup. */
1807 if (reply.shared != NULL)
1808 shared_network_dereference(&reply.shared, MDL);
1809 if (reply.host != NULL)
1810 host_dereference(&reply.host, MDL);
1811 if (reply.opt_state != NULL)
1812 option_state_dereference(&reply.opt_state, MDL);
1813 if (reply.packet != NULL)
1814 packet_dereference(&reply.packet, MDL);
1815 if (reply.client_id.data != NULL)
1816 data_string_forget(&reply.client_id, MDL);
3bedb117
SR
1817 if (packet_oro.buffer != NULL)
1818 data_string_forget(&packet_oro, MDL);
5279b8f3
DH
1819 reply.renew = reply.rebind = reply.prefer = reply.valid = 0;
1820 reply.cursor = 0;
1821}
98bd7ca0 1822
b9137d42 1823/* Process a client-supplied IA_NA. This may append options to the tail of
5279b8f3
DH
1824 * the reply packet being built in the reply_state structure.
1825 */
1826static isc_result_t
1d9774ab 1827reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
5279b8f3
DH
1828 isc_result_t status = ISC_R_SUCCESS;
1829 u_int32_t iaid;
1830 unsigned ia_cursor;
1831 struct option_state *packet_ia;
1832 struct option_cache *oc;
1833 struct data_string ia_data, data;
98bd7ca0 1834
5279b8f3
DH
1835 /* Initialize values that will get cleaned up on return. */
1836 packet_ia = NULL;
1837 memset(&ia_data, 0, sizeof(ia_data));
1838 memset(&data, 0, sizeof(data));
b31fe1d5
TM
1839 /*
1840 * Note that find_client_address() may set reply->lease.
b9137d42 1841 */
98bd7ca0 1842
5279b8f3
DH
1843 /* Make sure there is at least room for the header. */
1844 if ((reply->cursor + IA_NA_OFFSET + 4) > sizeof(reply->buf)) {
1d9774ab 1845 log_error("reply_process_ia_na: Reply too long for IA.");
5279b8f3 1846 return ISC_R_NOSPACE;
98bd7ca0 1847 }
98bd7ca0 1848
98bd7ca0 1849
5279b8f3
DH
1850 /* Fetch the IA_NA contents. */
1851 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
1852 ia, IA_NA_OFFSET)) {
9322442f 1853 log_error("reply_process_ia_na: error evaluating ia");
5279b8f3
DH
1854 status = ISC_R_FAILURE;
1855 goto cleanup;
1856 }
98bd7ca0 1857
5279b8f3
DH
1858 /* Extract IA_NA header contents. */
1859 iaid = getULong(ia_data.data);
1860 reply->renew = getULong(ia_data.data + 4);
1861 reply->rebind = getULong(ia_data.data + 8);
1862
1863 /* Create an IA_NA structure. */
b31fe1d5 1864 if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
9322442f
FD
1865 reply->client_id.len, MDL) != ISC_R_SUCCESS) {
1866 log_error("reply_process_ia_na: no memory for ia.");
5279b8f3
DH
1867 status = ISC_R_NOMEMORY;
1868 goto cleanup;
1869 }
9322442f 1870 reply->ia->ia_type = D6O_IA_NA;
5279b8f3
DH
1871
1872 /* Cache pre-existing IA, if any. */
9322442f
FD
1873 ia_hash_lookup(&reply->old_ia, ia_na_active,
1874 (unsigned char *)reply->ia->iaid_duid.data,
1875 reply->ia->iaid_duid.len, MDL);
5279b8f3
DH
1876
1877 /*
1878 * Create an option cache to carry the IA_NA option contents, and
1879 * execute any user-supplied values into it.
1880 */
1881 if (!option_state_allocate(&reply->reply_ia, MDL)) {
1882 status = ISC_R_NOMEMORY;
1883 goto cleanup;
1884 }
1885
1886 /* Check & cache the fixed host record. */
1887 if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
2267da84
DH
1888 struct iaddr tmp_addr;
1889
5279b8f3
DH
1890 if (!evaluate_option_cache(&reply->fixed, NULL, NULL, NULL,
1891 NULL, NULL, &global_scope,
1892 reply->host->fixed_addr, MDL)) {
1d9774ab 1893 log_error("reply_process_ia_na: unable to evaluate "
5279b8f3
DH
1894 "fixed address.");
1895 status = ISC_R_FAILURE;
1896 goto cleanup;
98bd7ca0
DH
1897 }
1898
5279b8f3 1899 if (reply->fixed.len < 16) {
1d9774ab 1900 log_error("reply_process_ia_na: invalid fixed address.");
98bf1607 1901 status = DHCP_R_INVALIDARG;
5279b8f3 1902 goto cleanup;
98bd7ca0
DH
1903 }
1904
2267da84
DH
1905 /* Find the static lease's subnet. */
1906 tmp_addr.len = 16;
1907 memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
1908
1909 if (find_grouped_subnet(&reply->subnet, reply->shared,
1910 tmp_addr, MDL) == 0)
1911 log_fatal("Impossible condition at %s:%d.", MDL);
1912
5279b8f3
DH
1913 reply->static_lease = ISC_TRUE;
1914 } else
1915 reply->static_lease = ISC_FALSE;
1916
1917 /*
1918 * Save the cursor position at the start of the IA, so we can
1919 * set length and adjust t1/t2 values later. We write a temporary
1920 * header out now just in case we decide to adjust the packet
1921 * within sub-process functions.
1922 */
1923 ia_cursor = reply->cursor;
1924
1925 /* Initialize the IA_NA header. First the code. */
1926 putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_NA);
1927 reply->cursor += 2;
1928
1929 /* Then option length. */
1930 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
1931 reply->cursor += 2;
1932
1933 /* Then IA_NA header contents; IAID. */
1934 putULong(reply->buf.data + reply->cursor, iaid);
1935 reply->cursor += 4;
1936
1937 /* We store the client's t1 for now, and may over-ride it later. */
1938 putULong(reply->buf.data + reply->cursor, reply->renew);
1939 reply->cursor += 4;
1940
1941 /* We store the client's t2 for now, and may over-ride it later. */
1942 putULong(reply->buf.data + reply->cursor, reply->rebind);
1943 reply->cursor += 4;
1944
b31fe1d5 1945 /*
892379ec
FD
1946 * For each address in this IA_NA, decide what to do about it.
1947 *
1948 * Guidelines:
1949 *
7c7515b9 1950 * The client leaves unchanged any information about addresses
892379ec
FD
1951 * it has recorded but are not included ("cancel/break" below).
1952 * A not included IA ("cleanup" below) could give a Renew/Rebind.
5279b8f3
DH
1953 */
1954 oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
1955 reply->valid = reply->prefer = 0xffffffff;
1956 reply->client_valid = reply->client_prefer = 0;
5279b8f3
DH
1957 for (; oc != NULL ; oc = oc->next) {
1958 status = reply_process_addr(reply, oc);
1959
98bd7ca0 1960 /*
5279b8f3
DH
1961 * Canceled means we did not allocate addresses to the
1962 * client, but we're "done" with this IA - we set a status
1963 * code. So transmit this reply, e.g., move on to the next
1964 * IA.
98bd7ca0 1965 */
5279b8f3
DH
1966 if (status == ISC_R_CANCELED)
1967 break;
98bd7ca0 1968
1aa0fe5e
DH
1969 if ((status != ISC_R_SUCCESS) &&
1970 (status != ISC_R_ADDRINUSE) &&
1971 (status != ISC_R_ADDRNOTAVAIL))
5279b8f3
DH
1972 goto cleanup;
1973 }
1974
1975 reply->ia_count++;
1976
1977 /*
1978 * If we fell through the above and never gave the client
1979 * an address, give it one now.
1980 */
1d9774ab 1981 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
5279b8f3
DH
1982 status = find_client_address(reply);
1983
9f1d5a2f
DH
1984 if (status == ISC_R_NORESOURCES) {
1985 switch (reply->packet->dhcpv6_msg_type) {
1986 case DHCPV6_SOLICIT:
1987 /*
80c9fdb0 1988 * No address for any IA is handled
892379ec 1989 * by the caller.
9f1d5a2f 1990 */
80c9fdb0 1991 /* FALL THROUGH */
9f1d5a2f
DH
1992
1993 case DHCPV6_REQUEST:
1994 /* Section 18.2.1 (Request):
1995 *
1996 * If the server cannot assign any addresses to
1997 * an IA in the message from the client, the
1998 * server MUST include the IA in the Reply
1999 * message with no addresses in the IA and a
2000 * Status Code option in the IA containing
2001 * status code NoAddrsAvail.
2002 */
5279b8f3
DH
2003 option_state_dereference(&reply->reply_ia, MDL);
2004 if (!option_state_allocate(&reply->reply_ia,
9f1d5a2f
DH
2005 MDL))
2006 {
1d9774ab 2007 log_error("reply_process_ia_na: No "
9f1d5a2f
DH
2008 "memory for option state "
2009 "wipe.");
5279b8f3
DH
2010 status = ISC_R_NOMEMORY;
2011 goto cleanup;
2012 }
5279b8f3 2013
9f1d5a2f
DH
2014 if (!set_status_code(STATUS_NoAddrsAvail,
2015 "No addresses available "
2016 "for this interface.",
2017 reply->reply_ia)) {
1d9774ab 2018 log_error("reply_process_ia_na: Unable "
9f1d5a2f
DH
2019 "to set NoAddrsAvail status "
2020 "code.");
2021 status = ISC_R_FAILURE;
2022 goto cleanup;
2023 }
5279b8f3 2024
9f1d5a2f
DH
2025 status = ISC_R_SUCCESS;
2026 break;
2027
2028 default:
2029 /*
2030 * RFC 3315 does not tell us to emit a status
2031 * code in this condition, or anything else.
2032 *
2033 * If we included non-allocated addresses
2034 * (zeroed lifetimes) in an IA, then the client
2035 * will deconfigure them.
2036 *
2037 * So we want to include the IA even if we
2038 * can't give it a new address if it includes
2039 * zeroed lifetime addresses.
2040 *
2041 * We don't want to include the IA if we
2042 * provide zero addresses including zeroed
892379ec 2043 * lifetimes.
9f1d5a2f 2044 */
9322442f 2045 if (reply->resources_included)
9f1d5a2f
DH
2046 status = ISC_R_SUCCESS;
2047 else
2048 goto cleanup;
2049 break;
2050 }
98bd7ca0
DH
2051 }
2052
5279b8f3
DH
2053 if (status != ISC_R_SUCCESS)
2054 goto cleanup;
2055 }
2056
2057 reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
2058 sizeof(reply->buf) - reply->cursor,
2059 reply->reply_ia, reply->packet,
80c9fdb0 2060 required_opts_IA, NULL);
5279b8f3
DH
2061
2062 /* Reset the length of this IA to match what was just written. */
2063 putUShort(reply->buf.data + ia_cursor + 2,
2064 reply->cursor - (ia_cursor + 4));
2065
2066 /*
2067 * T1/T2 time selection is kind of weird. We actually use DHCP
2068 * (v4) scoped options as handy existing places where these might
2069 * be configured by an administrator. A value of zero tells the
2070 * client it may choose its own renewal time.
2071 */
2072 reply->renew = 0;
2073 oc = lookup_option(&dhcp_universe, reply->opt_state,
2074 DHO_DHCP_RENEWAL_TIME);
2075 if (oc != NULL) {
2076 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
2077 reply->packet->options,
2078 reply->opt_state, &global_scope,
2079 oc, MDL) ||
2080 (data.len != 4)) {
2081 log_error("Invalid renewal time.");
2082 } else {
2083 reply->renew = getULong(data.data);
98bd7ca0
DH
2084 }
2085
5279b8f3
DH
2086 if (data.data != NULL)
2087 data_string_forget(&data, MDL);
2088 }
2089 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
2090
2091 /* Now T2. */
2092 reply->rebind = 0;
2093 oc = lookup_option(&dhcp_universe, reply->opt_state,
2094 DHO_DHCP_REBINDING_TIME);
2095 if (oc != NULL) {
2096 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
2097 reply->packet->options,
2098 reply->opt_state, &global_scope,
2099 oc, MDL) ||
2100 (data.len != 4)) {
2101 log_error("Invalid rebinding time.");
98bd7ca0 2102 } else {
5279b8f3 2103 reply->rebind = getULong(data.data);
98bd7ca0
DH
2104 }
2105
5279b8f3
DH
2106 if (data.data != NULL)
2107 data_string_forget(&data, MDL);
2108 }
2109 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
98bd7ca0 2110
d9b5c150
SR
2111 /*
2112 * yes, goto's aren't the best but we also want to avoid extra
2113 * indents
2114 */
2115 if (status == ISC_R_CANCELED)
2116 goto cleanup;
2117
2118 /*
2119 * Handle static leases, we always log stuff and if it's
2120 * a hard binding we run any commit statements that we have
2121 */
2122 if (reply->static_lease) {
2123 char tmp_addr[INET6_ADDRSTRLEN];
2124 log_info("%s NA: address %s to client with duid %s iaid = %d "
2125 "static",
2126 dhcpv6_type_names[reply->buf.reply.msg_type],
2127 inet_ntop(AF_INET6, reply->fixed.data, tmp_addr,
2128 sizeof(tmp_addr)),
2129 print_hex_1(reply->client_id.len,
2130 reply->client_id.data, 60),
2131 iaid);
2132
2133 if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
2134 (reply->on_star.on_commit != NULL)) {
b31fe1d5 2135 execute_statements(NULL, reply->packet, NULL, NULL,
d9b5c150
SR
2136 reply->packet->options,
2137 reply->opt_state, NULL,
2138 reply->on_star.on_commit, NULL);
2139 executable_statement_dereference
2140 (&reply->on_star.on_commit, MDL);
2141 }
2142 goto cleanup;
2143 }
2144
2145 /*
2146 * If we have any addresses log what we are doing.
2147 */
2148 if (reply->ia->num_iasubopt != 0) {
2149 struct iasubopt *tmp;
2150 int i;
2151 char tmp_addr[INET6_ADDRSTRLEN];
2152
2153 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2154 tmp = reply->ia->iasubopt[i];
2155
2156 log_info("%s NA: address %s to client with duid %s "
36c4a037 2157 "iaid = %d valid for %u seconds",
d9b5c150
SR
2158 dhcpv6_type_names[reply->buf.reply.msg_type],
2159 inet_ntop(AF_INET6, &tmp->addr,
2160 tmp_addr, sizeof(tmp_addr)),
2161 print_hex_1(reply->client_id.len,
2162 reply->client_id.data, 60),
2163 iaid, tmp->valid);
2164 }
2165 }
2166
5279b8f3
DH
2167 /*
2168 * If this is not a 'soft' binding, consume the new changes into
2169 * the database (if any have been attached to the ia_na).
2170 *
2171 * Loop through the assigned dynamic addresses, referencing the
2172 * leases onto this IA_NA rather than any old ones, and updating
2173 * pool timers for each (if any).
2174 */
d9b5c150
SR
2175
2176 if ((reply->ia->num_iasubopt != 0) &&
2177 (reply->buf.reply.msg_type == DHCPV6_REPLY)) {
1d17db44 2178 struct iasubopt *tmp;
5279b8f3
DH
2179 struct data_string *ia_id;
2180 int i;
98bd7ca0 2181
1d17db44
FD
2182 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2183 tmp = reply->ia->iasubopt[i];
98bd7ca0 2184
9322442f
FD
2185 if (tmp->ia != NULL)
2186 ia_dereference(&tmp->ia, MDL);
2187 ia_reference(&tmp->ia, reply->ia, MDL);
98bd7ca0 2188
5d89d60f 2189 /* Commit 'hard' bindings. */
5d89d60f 2190 renew_lease6(tmp->ipv6_pool, tmp);
5279b8f3 2191 schedule_lease_timeout(tmp->ipv6_pool);
98bd7ca0 2192
a7341359
SR
2193 /* If we have anything to do on commit do it now */
2194 if (tmp->on_star.on_commit != NULL) {
2195 execute_statements(NULL, reply->packet,
b31fe1d5 2196 NULL, NULL,
a7341359
SR
2197 reply->packet->options,
2198 reply->opt_state,
58cb5d86 2199 &tmp->scope,
a7341359
SR
2200 tmp->on_star.on_commit,
2201 &tmp->on_star);
2202 executable_statement_dereference
2203 (&tmp->on_star.on_commit, MDL);
2204 }
2205
98bf1607 2206#if defined (NSUPDATE)
98bd7ca0 2207 /*
5d89d60f 2208 * Perform ddns updates.
98bd7ca0 2209 */
5279b8f3
DH
2210 oc = lookup_option(&server_universe, reply->opt_state,
2211 SV_DDNS_UPDATES);
2212 if ((oc == NULL) ||
2213 evaluate_boolean_option_cache(NULL, reply->packet,
2214 NULL, NULL,
2215 reply->packet->options,
2216 reply->opt_state,
bead14ea 2217 &tmp->scope,
5279b8f3
DH
2218 oc, MDL)) {
2219 ddns_updates(reply->packet, NULL, NULL,
bead14ea 2220 tmp, NULL, reply->opt_state);
98bd7ca0 2221 }
98bf1607 2222#endif
250f7134
SR
2223 /* Do our threshold check. */
2224 check_pool6_threshold(reply, tmp);
5279b8f3 2225 }
98bd7ca0 2226
9322442f 2227 /* Remove any old ia from the hash. */
80c9fdb0
FD
2228 if (reply->old_ia != NULL) {
2229 ia_id = &reply->old_ia->iaid_duid;
9322442f
FD
2230 ia_hash_delete(ia_na_active,
2231 (unsigned char *)ia_id->data,
2232 ia_id->len, MDL);
2233 ia_dereference(&reply->old_ia, MDL);
98bd7ca0
DH
2234 }
2235
9322442f 2236 /* Put new ia into the hash. */
1acab09f 2237 reply->ia->cltt = cur_time;
9322442f
FD
2238 ia_id = &reply->ia->iaid_duid;
2239 ia_hash_add(ia_na_active, (unsigned char *)ia_id->data,
2240 ia_id->len, reply->ia, MDL);
98bd7ca0 2241
9322442f 2242 write_ia(reply->ia);
ad80055f
SR
2243 } else {
2244 schedule_lease_timeout_reply(reply);
5279b8f3 2245 }
98bd7ca0 2246
5279b8f3
DH
2247 cleanup:
2248 if (packet_ia != NULL)
2249 option_state_dereference(&packet_ia, MDL);
2250 if (reply->reply_ia != NULL)
2251 option_state_dereference(&reply->reply_ia, MDL);
2252 if (ia_data.data != NULL)
2253 data_string_forget(&ia_data, MDL);
2254 if (data.data != NULL)
2255 data_string_forget(&data, MDL);
9322442f
FD
2256 if (reply->ia != NULL)
2257 ia_dereference(&reply->ia, MDL);
80c9fdb0 2258 if (reply->old_ia != NULL)
9322442f 2259 ia_dereference(&reply->old_ia, MDL);
5d89d60f 2260 if (reply->lease != NULL)
1d17db44 2261 iasubopt_dereference(&reply->lease, MDL);
5279b8f3
DH
2262 if (reply->fixed.data != NULL)
2263 data_string_forget(&reply->fixed, MDL);
2267da84
DH
2264 if (reply->subnet != NULL)
2265 subnet_dereference(&reply->subnet, MDL);
a7341359
SR
2266 if (reply->on_star.on_expiry != NULL)
2267 executable_statement_dereference
2268 (&reply->on_star.on_expiry, MDL);
2269 if (reply->on_star.on_release != NULL)
2270 executable_statement_dereference
2271 (&reply->on_star.on_release, MDL);
5279b8f3
DH
2272
2273 /*
2274 * ISC_R_CANCELED is a status code used by the addr processing to
2275 * indicate we're replying with a status code. This is still a
2276 * success at higher layers.
2277 */
2278 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2279}
2280
2281/*
9322442f 2282 * Process an IAADDR within a given IA_xA, storing any IAADDR reply contents
5279b8f3
DH
2283 * into the reply's current ia-scoped option cache. Returns ISC_R_CANCELED
2284 * in the event we are replying with a status code and do not wish to process
2285 * more IAADDRs within this IA.
2286 */
2287static isc_result_t
2288reply_process_addr(struct reply_state *reply, struct option_cache *addr) {
2289 u_int32_t pref_life, valid_life;
2290 struct binding_scope **scope;
2291 struct group *group;
2292 struct subnet *subnet;
2293 struct iaddr tmp_addr;
b024480e 2294 struct option_cache *oc;
5279b8f3
DH
2295 struct data_string iaaddr, data;
2296 isc_result_t status = ISC_R_SUCCESS;
2297
2298 /* Initializes values that will be cleaned up. */
2299 memset(&iaaddr, 0, sizeof(iaaddr));
2300 memset(&data, 0, sizeof(data));
2301 /* Note that reply->lease may be set by address_is_owned() */
2302
2303 /*
2304 * There is no point trying to process an incoming address if there
2305 * is no room for an outgoing address.
2306 */
2307 if ((reply->cursor + 28) > sizeof(reply->buf)) {
2308 log_error("reply_process_addr: Out of room for address.");
2309 return ISC_R_NOSPACE;
2310 }
2311
2312 /* Extract this IAADDR option. */
b31fe1d5 2313 if (!evaluate_option_cache(&iaaddr, reply->packet, NULL, NULL,
5279b8f3
DH
2314 reply->packet->options, NULL, &global_scope,
2315 addr, MDL) ||
2316 (iaaddr.len < IAADDR_OFFSET)) {
2317 log_error("reply_process_addr: error evaluating IAADDR.");
2318 status = ISC_R_FAILURE;
2319 goto cleanup;
2320 }
2321
bead14ea 2322 /* The first 16 bytes are the IPv6 address. */
5279b8f3
DH
2323 pref_life = getULong(iaaddr.data + 16);
2324 valid_life = getULong(iaaddr.data + 20);
2325
2326 if ((reply->client_valid == 0) ||
2327 (reply->client_valid > valid_life))
2328 reply->client_valid = valid_life;
2329
2330 if ((reply->client_prefer == 0) ||
2331 (reply->client_prefer > pref_life))
2332 reply->client_prefer = pref_life;
2333
b31fe1d5 2334 /*
5279b8f3
DH
2335 * Clients may choose to send :: as an address, with the idea to give
2336 * hints about preferred-lifetime or valid-lifetime.
2337 */
bead14ea
DH
2338 tmp_addr.len = 16;
2339 memset(tmp_addr.iabuf, 0, 16);
5279b8f3
DH
2340 if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
2341 /* Status remains success; we just ignore this one. */
2342 goto cleanup;
2343 }
2344
bead14ea
DH
2345 /* tmp_addr len remains 16 */
2346 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2347
5279b8f3
DH
2348 /*
2349 * Verify that this address is on the client's network.
2350 */
2351 for (subnet = reply->shared->subnets ; subnet != NULL ;
2352 subnet = subnet->next_sibling) {
2353 if (addr_eq(subnet_number(tmp_addr, subnet->netmask),
2354 subnet->net))
2355 break;
2356 }
98bd7ca0 2357
5279b8f3
DH
2358 /* Address not found on shared network. */
2359 if (subnet == NULL) {
2360 /* Ignore this address on 'soft' bindings. */
9322442f
FD
2361 if (reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
2362 /* disable rapid commit */
2363 reply->buf.reply.msg_type = DHCPV6_ADVERTISE;
2364 delete_option(&dhcpv6_universe,
2365 reply->opt_state,
2366 D6O_RAPID_COMMIT);
5279b8f3
DH
2367 /* status remains success */
2368 goto cleanup;
9322442f 2369 }
98bd7ca0 2370
5279b8f3
DH
2371 /*
2372 * RFC3315 section 18.2.1:
2373 *
2374 * If the server finds that the prefix on one or more IP
2375 * addresses in any IA in the message from the client is not
2376 * appropriate for the link to which the client is connected,
2377 * the server MUST return the IA to the client with a Status
2378 * Code option with the value NotOnLink.
2379 */
2380 if (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) {
2381 /* Rewind the IA_NA to empty. */
2382 option_state_dereference(&reply->reply_ia, MDL);
2383 if (!option_state_allocate(&reply->reply_ia, MDL)) {
2384 log_error("reply_process_addr: No memory for "
2385 "option state wipe.");
2386 status = ISC_R_NOMEMORY;
2387 goto cleanup;
2388 }
98bd7ca0 2389
5279b8f3
DH
2390 /* Append a NotOnLink status code. */
2391 if (!set_status_code(STATUS_NotOnLink,
2392 "Address not for use on this "
2393 "link.", reply->reply_ia)) {
2394 log_error("reply_process_addr: Failure "
2395 "setting status code.");
2396 status = ISC_R_FAILURE;
2397 goto cleanup;
98bd7ca0 2398 }
5279b8f3
DH
2399
2400 /* Fin (no more IAADDRs). */
2401 status = ISC_R_CANCELED;
2402 goto cleanup;
98bd7ca0
DH
2403 }
2404
2405 /*
5279b8f3
DH
2406 * RFC3315 sections 18.2.3 and 18.2.4 have identical language:
2407 *
2408 * If the server finds that any of the addresses are not
2409 * appropriate for the link to which the client is attached,
2410 * the server returns the address to the client with lifetimes
2411 * of 0.
98bd7ca0 2412 */
5279b8f3
DH
2413 if ((reply->packet->dhcpv6_msg_type != DHCPV6_RENEW) &&
2414 (reply->packet->dhcpv6_msg_type != DHCPV6_REBIND)) {
2415 log_error("It is impossible to lease a client that is "
f415516e 2416 "not sending a solicit, request, renew, or "
5279b8f3
DH
2417 "rebind.");
2418 status = ISC_R_FAILURE;
2419 goto cleanup;
98bd7ca0
DH
2420 }
2421
5279b8f3
DH
2422 reply->send_prefer = reply->send_valid = 0;
2423 goto send_addr;
2424 }
2425
2426 /* Verify the address belongs to the client. */
2427 if (!address_is_owned(reply, &tmp_addr)) {
98bd7ca0 2428 /*
5279b8f3
DH
2429 * For solicit and request, any addresses included are
2430 * 'requested' addresses. For rebind, we actually have
2431 * no direction on what to do from 3315 section 18.2.4!
2432 * So I think the best bet is to try and give it out, and if
2433 * we can't, zero lifetimes.
98bd7ca0 2434 */
5279b8f3
DH
2435 if ((reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) ||
2436 (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) ||
2437 (reply->packet->dhcpv6_msg_type == DHCPV6_REBIND)) {
2438 status = reply_process_try_addr(reply, &tmp_addr);
2439
1aa0fe5e
DH
2440 /*
2441 * If the address is in use, or isn't in any dynamic
2442 * range, continue as normal. If any other error was
2443 * found, error out.
2444 */
b31fe1d5 2445 if ((status != ISC_R_SUCCESS) &&
1aa0fe5e
DH
2446 (status != ISC_R_ADDRINUSE) &&
2447 (status != ISC_R_ADDRNOTAVAIL))
5279b8f3
DH
2448 goto cleanup;
2449
1aa0fe5e
DH
2450 /*
2451 * If we didn't honor this lease, for solicit and
2452 * request we simply omit it from our answer. For
2453 * rebind, we send it with zeroed lifetimes.
2454 */
5279b8f3
DH
2455 if (reply->lease == NULL) {
2456 if (reply->packet->dhcpv6_msg_type ==
2457 DHCPV6_REBIND) {
2458 reply->send_prefer = 0;
2459 reply->send_valid = 0;
2460 goto send_addr;
2461 }
2462
2463 /* status remains success - ignore */
2464 goto cleanup;
98bd7ca0 2465 }
5279b8f3
DH
2466 /*
2467 * RFC3315 section 18.2.3:
2468 *
2469 * If the server cannot find a client entry for the IA the
2470 * server returns the IA containing no addresses with a Status
2471 * Code option set to NoBinding in the Reply message.
892379ec
FD
2472 *
2473 * On mismatch we (ab)use this pretending we have not the IA
2474 * as soon as we have not an address.
5279b8f3
DH
2475 */
2476 } else if (reply->packet->dhcpv6_msg_type == DHCPV6_RENEW) {
2477 /* Rewind the IA_NA to empty. */
2478 option_state_dereference(&reply->reply_ia, MDL);
2479 if (!option_state_allocate(&reply->reply_ia, MDL)) {
2480 log_error("reply_process_addr: No memory for "
2481 "option state wipe.");
2482 status = ISC_R_NOMEMORY;
2483 goto cleanup;
98bd7ca0 2484 }
98bd7ca0 2485
5279b8f3
DH
2486 /* Append a NoBinding status code. */
2487 if (!set_status_code(STATUS_NoBinding,
2488 "Address not bound to this "
2489 "interface.", reply->reply_ia)) {
2490 log_error("reply_process_addr: Unable to "
2491 "attach status code.");
2492 status = ISC_R_FAILURE;
2493 goto cleanup;
98bd7ca0 2494 }
5279b8f3
DH
2495
2496 /* Fin (no more IAADDRs). */
2497 status = ISC_R_CANCELED;
2498 goto cleanup;
2499 } else {
2500 log_error("It is impossible to lease a client that is "
2501 "not sending a solicit, request, renew, or "
2502 "rebind message.");
2503 status = ISC_R_FAILURE;
2504 goto cleanup;
98bd7ca0 2505 }
5279b8f3 2506 }
98bd7ca0 2507
5279b8f3
DH
2508 if (reply->static_lease) {
2509 if (reply->host == NULL)
2510 log_fatal("Impossible condition at %s:%d.", MDL);
d9b43370 2511
5279b8f3 2512 scope = &global_scope;
2267da84 2513 group = reply->subnet->group;
5279b8f3
DH
2514 } else {
2515 if (reply->lease == NULL)
2516 log_fatal("Impossible condition at %s:%d.", MDL);
7285af30 2517
5279b8f3 2518 scope = &reply->lease->scope;
01fa619f 2519 group = reply->lease->ipv6_pool->ipv6_pond->group;
5279b8f3 2520 }
98bd7ca0 2521
b024480e 2522 /*
1d9774ab 2523 * If client_resources is nonzero, then the reply_process_is_addressed
b024480e
DH
2524 * function has executed configuration state into the reply option
2525 * cache. We will use that valid cache to derive configuration for
2526 * whether or not to engage in additional addresses, and similar.
2527 */
1d9774ab 2528 if (reply->client_resources != 0) {
b024480e
DH
2529 unsigned limit = 1;
2530
2531 /*
2532 * Does this client have "enough" addresses already? Default
2533 * to one. Everybody gets one, and one should be enough for
2534 * anybody.
2535 */
2536 oc = lookup_option(&server_universe, reply->opt_state,
2537 SV_LIMIT_ADDRS_PER_IA);
2538 if (oc != NULL) {
2539 if (!evaluate_option_cache(&data, reply->packet,
2540 NULL, NULL,
2541 reply->packet->options,
2542 reply->opt_state,
2543 scope, oc, MDL) ||
2544 (data.len != 4)) {
1d9774ab 2545 log_error("reply_process_addr: unable to "
b024480e
DH
2546 "evaluate addrs-per-ia value.");
2547 status = ISC_R_FAILURE;
2548 goto cleanup;
2549 }
2550
2551 limit = getULong(data.data);
2552 data_string_forget(&data, MDL);
2553 }
2554
2555 /*
2556 * If we wish to limit the client to a certain number of
2557 * addresses, then omit the address from the reply.
2558 */
1d9774ab 2559 if (reply->client_resources >= limit)
b024480e
DH
2560 goto cleanup;
2561 }
2562
9322442f 2563 status = reply_process_is_addressed(reply, scope, group);
5279b8f3
DH
2564 if (status != ISC_R_SUCCESS)
2565 goto cleanup;
98bd7ca0 2566
5279b8f3
DH
2567 send_addr:
2568 status = reply_process_send_addr(reply, &tmp_addr);
98bd7ca0 2569
5279b8f3
DH
2570 cleanup:
2571 if (iaaddr.data != NULL)
2572 data_string_forget(&iaaddr, MDL);
2573 if (data.data != NULL)
2574 data_string_forget(&data, MDL);
2575 if (reply->lease != NULL)
1d17db44 2576 iasubopt_dereference(&reply->lease, MDL);
98bd7ca0 2577
5279b8f3
DH
2578 return status;
2579}
98bd7ca0 2580
5279b8f3
DH
2581/*
2582 * Verify the address belongs to the client. If we've got a host
2583 * record with a fixed address, it has to be the assigned address
2584 * (fault out all else). Otherwise it's a dynamic address, so lookup
2585 * that address and make sure it belongs to this DUID:IAID pair.
2586 */
2587static isc_boolean_t
2588address_is_owned(struct reply_state *reply, struct iaddr *addr) {
2589 int i;
01fa619f 2590 struct ipv6_pond *pond;
98bd7ca0 2591
5279b8f3
DH
2592 /*
2593 * This faults out addresses that don't match fixed addresses.
2594 */
2595 if (reply->static_lease) {
2596 if (reply->fixed.data == NULL)
2597 log_fatal("Impossible condition at %s:%d.", MDL);
98bd7ca0 2598
5279b8f3 2599 if (memcmp(addr->iabuf, reply->fixed.data, 16) == 0)
bc7f8b8e 2600 return (ISC_TRUE);
98bd7ca0 2601
bc7f8b8e 2602 return (ISC_FALSE);
5279b8f3
DH
2603 }
2604
1d17db44 2605 if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
bc7f8b8e 2606 return (ISC_FALSE);
5279b8f3 2607
1d17db44
FD
2608 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2609 struct iasubopt *tmp;
5279b8f3 2610
1d17db44 2611 tmp = reply->old_ia->iasubopt[i];
5279b8f3
DH
2612
2613 if (memcmp(addr->iabuf, &tmp->addr, 16) == 0) {
bc7f8b8e
SR
2614 if (lease6_usable(tmp) == ISC_FALSE) {
2615 return (ISC_FALSE);
2616 }
01fa619f
SR
2617
2618 pond = tmp->ipv6_pool->ipv6_pond;
2619 if (((pond->prohibit_list != NULL) &&
2620 (permitted(reply->packet, pond->prohibit_list))) ||
2621 ((pond->permit_list != NULL) &&
2622 (!permitted(reply->packet, pond->permit_list))))
2623 return (ISC_FALSE);
2624
1d17db44 2625 iasubopt_reference(&reply->lease, tmp, MDL);
01fa619f 2626
bc7f8b8e 2627 return (ISC_TRUE);
98bd7ca0 2628 }
98bd7ca0
DH
2629 }
2630
bc7f8b8e 2631 return (ISC_FALSE);
5279b8f3
DH
2632}
2633
80c9fdb0
FD
2634/* Process a client-supplied IA_TA. This may append options to the tail of
2635 * the reply packet being built in the reply_state structure.
5279b8f3
DH
2636 */
2637static isc_result_t
80c9fdb0
FD
2638reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
2639 isc_result_t status = ISC_R_SUCCESS;
2640 u_int32_t iaid;
2641 unsigned ia_cursor;
2642 struct option_state *packet_ia;
2643 struct option_cache *oc;
2644 struct data_string ia_data, data;
2645 struct data_string iaaddr;
2646 u_int32_t pref_life, valid_life;
783259b1 2647 struct iaddr tmp_addr;
5279b8f3 2648
80c9fdb0
FD
2649 /* Initialize values that will get cleaned up on return. */
2650 packet_ia = NULL;
2651 memset(&ia_data, 0, sizeof(ia_data));
2652 memset(&data, 0, sizeof(data));
2653 memset(&iaaddr, 0, sizeof(iaaddr));
5279b8f3 2654
80c9fdb0
FD
2655 /* Make sure there is at least room for the header. */
2656 if ((reply->cursor + IA_TA_OFFSET + 4) > sizeof(reply->buf)) {
2657 log_error("reply_process_ia_ta: Reply too long for IA.");
2658 return ISC_R_NOSPACE;
98bd7ca0 2659 }
98bd7ca0 2660
5279b8f3 2661
80c9fdb0
FD
2662 /* Fetch the IA_TA contents. */
2663 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2664 ia, IA_TA_OFFSET)) {
9322442f 2665 log_error("reply_process_ia_ta: error evaluating ia");
80c9fdb0
FD
2666 status = ISC_R_FAILURE;
2667 goto cleanup;
98bd7ca0 2668 }
5279b8f3 2669
80c9fdb0
FD
2670 /* Extract IA_TA header contents. */
2671 iaid = getULong(ia_data.data);
5279b8f3 2672
80c9fdb0 2673 /* Create an IA_TA structure. */
783259b1 2674 if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
9322442f
FD
2675 reply->client_id.len, MDL) != ISC_R_SUCCESS) {
2676 log_error("reply_process_ia_ta: no memory for ia.");
80c9fdb0
FD
2677 status = ISC_R_NOMEMORY;
2678 goto cleanup;
98bd7ca0 2679 }
9322442f 2680 reply->ia->ia_type = D6O_IA_TA;
5279b8f3 2681
80c9fdb0 2682 /* Cache pre-existing IA, if any. */
9322442f
FD
2683 ia_hash_lookup(&reply->old_ia, ia_ta_active,
2684 (unsigned char *)reply->ia->iaid_duid.data,
2685 reply->ia->iaid_duid.len, MDL);
80c9fdb0
FD
2686
2687 /*
2688 * Create an option cache to carry the IA_TA option contents, and
2689 * execute any user-supplied values into it.
5279b8f3 2690 */
80c9fdb0
FD
2691 if (!option_state_allocate(&reply->reply_ia, MDL)) {
2692 status = ISC_R_NOMEMORY;
2693 goto cleanup;
98bd7ca0 2694 }
5279b8f3 2695
80c9fdb0
FD
2696 /*
2697 * Temporary leases are dynamic by definition.
2698 */
2699 reply->static_lease = ISC_FALSE;
5279b8f3 2700
80c9fdb0
FD
2701 /*
2702 * Save the cursor position at the start of the IA, so we can
2703 * set length later. We write a temporary
2704 * header out now just in case we decide to adjust the packet
2705 * within sub-process functions.
2706 */
2707 ia_cursor = reply->cursor;
2708
2709 /* Initialize the IA_TA header. First the code. */
2710 putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_TA);
2711 reply->cursor += 2;
2712
2713 /* Then option length. */
2714 putUShort(reply->buf.data + reply->cursor, 0x04u);
2715 reply->cursor += 2;
2716
2717 /* Then IA_TA header contents; IAID. */
2718 putULong(reply->buf.data + reply->cursor, iaid);
2719 reply->cursor += 4;
2720
b31fe1d5 2721 /*
80c9fdb0 2722 * Deal with an IAADDR for lifetimes.
783259b1 2723 * For all or none, process IAADDRs as hints.
80c9fdb0
FD
2724 */
2725 reply->valid = reply->prefer = 0xffffffff;
2726 reply->client_valid = reply->client_prefer = 0;
2727 oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
783259b1
FD
2728 for (; oc != NULL; oc = oc->next) {
2729 memset(&iaaddr, 0, sizeof(iaaddr));
80c9fdb0
FD
2730 if (!evaluate_option_cache(&iaaddr, reply->packet,
2731 NULL, NULL,
2732 reply->packet->options, NULL,
2733 &global_scope, oc, MDL) ||
2734 (iaaddr.len < IAADDR_OFFSET)) {
2735 log_error("reply_process_ia_ta: error "
2736 "evaluating IAADDR.");
2737 status = ISC_R_FAILURE;
2738 goto cleanup;
2739 }
2740 /* The first 16 bytes are the IPv6 address. */
2741 pref_life = getULong(iaaddr.data + 16);
2742 valid_life = getULong(iaaddr.data + 20);
2743
2744 if ((reply->client_valid == 0) ||
2745 (reply->client_valid > valid_life))
2746 reply->client_valid = valid_life;
2747
2748 if ((reply->client_prefer == 0) ||
2749 (reply->client_prefer > pref_life))
2750 reply->client_prefer = pref_life;
80c9fdb0 2751
783259b1
FD
2752 /* Nothing more if something has failed. */
2753 if (status == ISC_R_CANCELED)
2754 continue;
2755
2756 tmp_addr.len = 16;
2757 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2758 if (!temporary_is_available(reply, &tmp_addr))
2759 goto bad_temp;
2760 status = reply_process_is_addressed(reply,
2761 &reply->lease->scope,
01fa619f 2762 reply->lease->ipv6_pool->ipv6_pond->group);
783259b1
FD
2763 if (status != ISC_R_SUCCESS)
2764 goto bad_temp;
2765 status = reply_process_send_addr(reply, &tmp_addr);
2766 if (status != ISC_R_SUCCESS)
2767 goto bad_temp;
2768 if (reply->lease != NULL)
2769 iasubopt_dereference(&reply->lease, MDL);
2770 continue;
2771
2772 bad_temp:
2773 /* Rewind the IA_TA to empty. */
2774 option_state_dereference(&reply->reply_ia, MDL);
2775 if (!option_state_allocate(&reply->reply_ia, MDL)) {
2776 status = ISC_R_NOMEMORY;
80c9fdb0
FD
2777 goto cleanup;
2778 }
2779 status = ISC_R_CANCELED;
783259b1
FD
2780 reply->client_resources = 0;
2781 reply->resources_included = ISC_FALSE;
2782 if (reply->lease != NULL)
2783 iasubopt_dereference(&reply->lease, MDL);
80c9fdb0 2784 }
783259b1 2785 reply->ia_count++;
80c9fdb0
FD
2786
2787 /*
2788 * Give the client temporary addresses.
2789 */
783259b1
FD
2790 if (reply->client_resources != 0)
2791 goto store;
80c9fdb0
FD
2792 status = find_client_temporaries(reply);
2793 if (status == ISC_R_NORESOURCES) {
2794 switch (reply->packet->dhcpv6_msg_type) {
2795 case DHCPV6_SOLICIT:
2796 /*
2797 * No address for any IA is handled
2798 * by the caller.
2799 */
2800 /* FALL THROUGH */
2801
2802 case DHCPV6_REQUEST:
2803 /* Section 18.2.1 (Request):
2804 *
2805 * If the server cannot assign any addresses to
2806 * an IA in the message from the client, the
2807 * server MUST include the IA in the Reply
2808 * message with no addresses in the IA and a
2809 * Status Code option in the IA containing
2810 * status code NoAddrsAvail.
2811 */
2812 option_state_dereference(&reply->reply_ia, MDL);
2813 if (!option_state_allocate(&reply->reply_ia, MDL)) {
2814 log_error("reply_process_ia_ta: No "
2815 "memory for option state wipe.");
2816 status = ISC_R_NOMEMORY;
2817 goto cleanup;
2818 }
2819
2820 if (!set_status_code(STATUS_NoAddrsAvail,
2821 "No addresses available "
2822 "for this interface.",
2823 reply->reply_ia)) {
2824 log_error("reply_process_ia_ta: Unable "
2825 "to set NoAddrsAvail status code.");
2826 status = ISC_R_FAILURE;
2827 goto cleanup;
2828 }
2829
2830 status = ISC_R_SUCCESS;
2831 break;
2832
2833 default:
783259b1
FD
2834 /*
2835 * We don't want to include the IA if we
2836 * provide zero addresses including zeroed
2837 * lifetimes.
2838 */
2839 if (reply->resources_included)
2840 status = ISC_R_SUCCESS;
2841 else
2842 goto cleanup;
2843 break;
80c9fdb0
FD
2844 }
2845 } else if (status != ISC_R_SUCCESS)
2846 goto cleanup;
2847
2848 store:
2849 reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
2850 sizeof(reply->buf) - reply->cursor,
2851 reply->reply_ia, reply->packet,
2852 required_opts_IA, NULL);
2853
2854 /* Reset the length of this IA to match what was just written. */
2855 putUShort(reply->buf.data + ia_cursor + 2,
2856 reply->cursor - (ia_cursor + 4));
2857
2858 /*
d9b5c150
SR
2859 * yes, goto's aren't the best but we also want to avoid extra
2860 * indents
2861 */
2862 if (status == ISC_R_CANCELED)
2863 goto cleanup;
2864
2865 /*
2866 * If we have any addresses log what we are doing.
2867 */
2868 if (reply->ia->num_iasubopt != 0) {
2869 struct iasubopt *tmp;
2870 int i;
2871 char tmp_addr[INET6_ADDRSTRLEN];
2872
2873 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2874 tmp = reply->ia->iasubopt[i];
2875
2876 log_info("%s TA: address %s to client with duid %s "
36c4a037 2877 "iaid = %d valid for %u seconds",
d9b5c150
SR
2878 dhcpv6_type_names[reply->buf.reply.msg_type],
2879 inet_ntop(AF_INET6, &tmp->addr,
2880 tmp_addr, sizeof(tmp_addr)),
2881 print_hex_1(reply->client_id.len,
2882 reply->client_id.data, 60),
2883 iaid,
2884 tmp->valid);
2885 }
2886 }
2887
2888 /*
2889 * For hard bindings we consume the new changes into
2890 * the database (if any have been attached to the ia_ta).
80c9fdb0
FD
2891 *
2892 * Loop through the assigned dynamic addresses, referencing the
2893 * leases onto this IA_TA rather than any old ones, and updating
2894 * pool timers for each (if any).
2895 */
d9b5c150
SR
2896 if ((reply->ia->num_iasubopt != 0) &&
2897 (reply->buf.reply.msg_type == DHCPV6_REPLY)) {
1d17db44 2898 struct iasubopt *tmp;
80c9fdb0
FD
2899 struct data_string *ia_id;
2900 int i;
2901
1d17db44
FD
2902 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2903 tmp = reply->ia->iasubopt[i];
80c9fdb0 2904
9322442f
FD
2905 if (tmp->ia != NULL)
2906 ia_dereference(&tmp->ia, MDL);
2907 ia_reference(&tmp->ia, reply->ia, MDL);
80c9fdb0 2908
5d89d60f 2909 /* Commit 'hard' bindings. */
5d89d60f 2910 renew_lease6(tmp->ipv6_pool, tmp);
80c9fdb0
FD
2911 schedule_lease_timeout(tmp->ipv6_pool);
2912
a7341359
SR
2913 /* If we have anything to do on commit do it now */
2914 if (tmp->on_star.on_commit != NULL) {
2915 execute_statements(NULL, reply->packet,
b31fe1d5 2916 NULL, NULL,
a7341359
SR
2917 reply->packet->options,
2918 reply->opt_state,
58cb5d86 2919 &tmp->scope,
a7341359
SR
2920 tmp->on_star.on_commit,
2921 &tmp->on_star);
2922 executable_statement_dereference
2923 (&tmp->on_star.on_commit, MDL);
2924 }
2925
98bf1607 2926#if defined (NSUPDATE)
80c9fdb0
FD
2927 /*
2928 * Perform ddns updates.
2929 */
2930 oc = lookup_option(&server_universe, reply->opt_state,
2931 SV_DDNS_UPDATES);
2932 if ((oc == NULL) ||
2933 evaluate_boolean_option_cache(NULL, reply->packet,
2934 NULL, NULL,
2935 reply->packet->options,
2936 reply->opt_state,
2937 &tmp->scope,
2938 oc, MDL)) {
2939 ddns_updates(reply->packet, NULL, NULL,
2940 tmp, NULL, reply->opt_state);
2941 }
98bf1607 2942#endif
250f7134
SR
2943 /* Do our threshold check. */
2944 check_pool6_threshold(reply, tmp);
80c9fdb0
FD
2945 }
2946
9322442f 2947 /* Remove any old ia from the hash. */
80c9fdb0
FD
2948 if (reply->old_ia != NULL) {
2949 ia_id = &reply->old_ia->iaid_duid;
9322442f
FD
2950 ia_hash_delete(ia_ta_active,
2951 (unsigned char *)ia_id->data,
2952 ia_id->len, MDL);
2953 ia_dereference(&reply->old_ia, MDL);
80c9fdb0
FD
2954 }
2955
9322442f 2956 /* Put new ia into the hash. */
1acab09f 2957 reply->ia->cltt = cur_time;
9322442f
FD
2958 ia_id = &reply->ia->iaid_duid;
2959 ia_hash_add(ia_ta_active, (unsigned char *)ia_id->data,
2960 ia_id->len, reply->ia, MDL);
80c9fdb0 2961
9322442f 2962 write_ia(reply->ia);
ad80055f
SR
2963 } else {
2964 schedule_lease_timeout_reply(reply);
80c9fdb0
FD
2965 }
2966
2967 cleanup:
2968 if (packet_ia != NULL)
2969 option_state_dereference(&packet_ia, MDL);
2970 if (iaaddr.data != NULL)
2971 data_string_forget(&iaaddr, MDL);
2972 if (reply->reply_ia != NULL)
2973 option_state_dereference(&reply->reply_ia, MDL);
2974 if (ia_data.data != NULL)
2975 data_string_forget(&ia_data, MDL);
2976 if (data.data != NULL)
2977 data_string_forget(&data, MDL);
9322442f
FD
2978 if (reply->ia != NULL)
2979 ia_dereference(&reply->ia, MDL);
80c9fdb0 2980 if (reply->old_ia != NULL)
9322442f 2981 ia_dereference(&reply->old_ia, MDL);
5d89d60f 2982 if (reply->lease != NULL)
1d17db44 2983 iasubopt_dereference(&reply->lease, MDL);
80c9fdb0
FD
2984
2985 /*
2986 * ISC_R_CANCELED is a status code used by the addr processing to
783259b1 2987 * indicate we're replying with other addresses. This is still a
80c9fdb0
FD
2988 * success at higher layers.
2989 */
2990 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2991}
2992
783259b1
FD
2993/*
2994 * Verify the temporary address is available.
2995 */
2996static isc_boolean_t
2997temporary_is_available(struct reply_state *reply, struct iaddr *addr) {
2998 struct in6_addr tmp_addr;
2999 struct subnet *subnet;
01fa619f
SR
3000 struct ipv6_pool *pool = NULL;
3001 struct ipv6_pond *pond = NULL;
783259b1
FD
3002 int i;
3003
3004 memcpy(&tmp_addr, addr->iabuf, sizeof(tmp_addr));
3005 /*
3006 * Clients may choose to send :: as an address, with the idea to give
3007 * hints about preferred-lifetime or valid-lifetime.
3008 * So this is not a request for this address.
3009 */
3010 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
3011 return ISC_FALSE;
3012
3013 /*
3014 * Verify that this address is on the client's network.
3015 */
3016 for (subnet = reply->shared->subnets ; subnet != NULL ;
3017 subnet = subnet->next_sibling) {
3018 if (addr_eq(subnet_number(*addr, subnet->netmask),
3019 subnet->net))
3020 break;
3021 }
3022
3023 /* Address not found on shared network. */
3024 if (subnet == NULL)
3025 return ISC_FALSE;
3026
3027 /*
3028 * Check if this address is owned (must be before next step).
3029 */
3030 if (address_is_owned(reply, addr))
3031 return ISC_TRUE;
3032
3033 /*
3034 * Verify that this address is in a temporary pool and try to get it.
3035 */
01fa619f
SR
3036 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
3037 if (((pond->prohibit_list != NULL) &&
3038 (permitted(reply->packet, pond->prohibit_list))) ||
3039 ((pond->permit_list != NULL) &&
3040 (!permitted(reply->packet, pond->permit_list))))
783259b1 3041 continue;
01fa619f
SR
3042
3043 for (i = 0 ; (pool = pond->ipv6_pools[i]) != NULL ; i++) {
3044 if (pool->pool_type != D6O_IA_TA)
3045 continue;
3046
3047 if (ipv6_in_pool(&tmp_addr, pool))
3048 break;
3049 }
3050
3051 if (pool != NULL)
783259b1
FD
3052 break;
3053 }
01fa619f 3054
783259b1
FD
3055 if (pool == NULL)
3056 return ISC_FALSE;
3057 if (lease6_exists(pool, &tmp_addr))
3058 return ISC_FALSE;
3059 if (iasubopt_allocate(&reply->lease, MDL) != ISC_R_SUCCESS)
3060 return ISC_FALSE;
3061 reply->lease->addr = tmp_addr;
3062 reply->lease->plen = 0;
3063 /* Default is soft binding for 2 minutes. */
3064 if (add_lease6(pool, reply->lease, cur_time + 120) != ISC_R_SUCCESS)
3065 return ISC_FALSE;
3066
3067 return ISC_TRUE;
3068}
3069
80c9fdb0
FD
3070/*
3071 * Get a temporary address per prefix.
3072 */
3073static isc_result_t
3074find_client_temporaries(struct reply_state *reply) {
80c9fdb0 3075 int i;
f1ef85cf 3076 struct ipv6_pool *p = NULL;
01fa619f
SR
3077 struct ipv6_pond *pond;
3078 isc_result_t status = ISC_R_NORESOURCES;;
80c9fdb0
FD
3079 unsigned int attempts;
3080 struct iaddr send_addr;
3081
3082 /*
01fa619f
SR
3083 * Do a quick walk through of the ponds and pools
3084 * to see if we have any prefix pools
80c9fdb0 3085 */
01fa619f
SR
3086 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
3087 if (pond->ipv6_pools == NULL)
3088 continue;
3089
3090 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
3091 if (p->pool_type == D6O_IA_TA)
3092 break;
3093 }
3094 if (p != NULL)
3095 break;
3096 }
3097
3098 /* If we get here and p is NULL we have no useful pools */
3099 if (p == NULL) {
80c9fdb0
FD
3100 log_debug("Unable to get client addresses: "
3101 "no IPv6 pools on this shared network");
3102 return ISC_R_NORESOURCES;
3103 }
3104
01fa619f
SR
3105 /*
3106 * We have at least one pool that could provide an address
3107 * Now we walk through the ponds and pools again and check
3108 * to see if the client is permitted and if an address is
3109 * available
3110 */
3111
3112 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
3113 if (((pond->prohibit_list != NULL) &&
3114 (permitted(reply->packet, pond->prohibit_list))) ||
3115 ((pond->permit_list != NULL) &&
3116 (!permitted(reply->packet, pond->permit_list))))
80c9fdb0 3117 continue;
80c9fdb0 3118
01fa619f
SR
3119 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
3120 if (p->pool_type != D6O_IA_TA) {
3121 continue;
3122 }
80c9fdb0 3123
01fa619f
SR
3124 /*
3125 * Get an address in this temporary pool.
3126 */
3127 status = create_lease6(p, &reply->lease, &attempts,
3128 &reply->client_id, cur_time + 120);
3129 if (status != ISC_R_SUCCESS) {
3130 log_debug("Unable to get a temporary address.");
3131 goto cleanup;
3132 }
3133
3134 status = reply_process_is_addressed(reply,
3135 &reply->lease->scope,
3136 pond->group);
3137 if (status != ISC_R_SUCCESS) {
3138 goto cleanup;
3139 }
3140 send_addr.len = 16;
3141 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3142 status = reply_process_send_addr(reply, &send_addr);
3143 if (status != ISC_R_SUCCESS) {
3144 goto cleanup;
3145 }
3146 /*
3147 * reply->lease can't be null as we use it above
3148 * add check if that changes
3149 */
3150 iasubopt_dereference(&reply->lease, MDL);
80c9fdb0 3151 }
80c9fdb0
FD
3152 }
3153
3154 cleanup:
3155 if (reply->lease != NULL) {
1d17db44 3156 iasubopt_dereference(&reply->lease, MDL);
80c9fdb0
FD
3157 }
3158 return status;
3159}
3160
3161/*
3162 * This function only returns failure on 'hard' failures. If it succeeds,
3163 * it will leave a lease structure behind.
3164 */
3165static isc_result_t
3166reply_process_try_addr(struct reply_state *reply, struct iaddr *addr) {
d19fa5a1 3167 isc_result_t status = ISC_R_ADDRNOTAVAIL;
01fa619f
SR
3168 struct ipv6_pool *pool = NULL;
3169 struct ipv6_pond *pond = NULL;
80c9fdb0
FD
3170 int i;
3171 struct data_string data_addr;
3172
3173 if ((reply == NULL) || (reply->shared == NULL) ||
d19fa5a1
SR
3174 (addr == NULL) || (reply->lease != NULL))
3175 return (DHCP_R_INVALIDARG);
3176
01fa619f
SR
3177 /*
3178 * Do a quick walk through of the ponds and pools
3179 * to see if we have any NA address pools
3180 */
3181 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
3182 if (pond->ipv6_pools == NULL)
3183 continue;
3184
3185 for (i = 0; ; i++) {
3186 pool = pond->ipv6_pools[i];
3187 if ((pool == NULL) ||
3188 (pool->pool_type == D6O_IA_NA))
3189 break;
3190 }
3191 if (pool != NULL)
3192 break;
3193 }
3194
3195 /* If we get here and p is NULL we have no useful pools */
3196 if (pool == NULL) {
d19fa5a1 3197 return (ISC_R_ADDRNOTAVAIL);
01fa619f 3198 }
80c9fdb0
FD
3199
3200 memset(&data_addr, 0, sizeof(data_addr));
3201 data_addr.len = addr->len;
3202 data_addr.data = addr->iabuf;
3203
01fa619f
SR
3204 /*
3205 * We have at least one pool that could provide an address
3206 * Now we walk through the ponds and pools again and check
3207 * to see if the client is permitted and if an address is
3208 * available
b31fe1d5 3209 *
01fa619f
SR
3210 * Within a given pond we start looking at the last pool we
3211 * allocated from, unless it had a collision trying to allocate
3212 * an address. This will tend to move us into less-filled pools.
3213 */
3214
3215 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
3216 if (((pond->prohibit_list != NULL) &&
3217 (permitted(reply->packet, pond->prohibit_list))) ||
3218 ((pond->permit_list != NULL) &&
3219 (!permitted(reply->packet, pond->permit_list))))
9322442f 3220 continue;
01fa619f
SR
3221
3222 for (i = 0 ; (pool = pond->ipv6_pools[i]) != NULL ; i++) {
3223 if (pool->pool_type != D6O_IA_NA)
3224 continue;
3225
3226 status = try_client_v6_address(&reply->lease, pool,
3227 &data_addr);
3228 if (status == ISC_R_SUCCESS)
3229 break;
3230 }
3231
80c9fdb0
FD
3232 if (status == ISC_R_SUCCESS)
3233 break;
3234 }
3235
3236 /* Note that this is just pedantry. There is no allocation to free. */
3237 data_string_forget(&data_addr, MDL);
3238 /* Return just the most recent status... */
d19fa5a1 3239 return (status);
80c9fdb0
FD
3240}
3241
3242/* Look around for an address to give the client. First, look through the
3243 * old IA for addresses we can extend. Second, try to allocate a new address.
3244 * Finally, actually add that address into the current reply IA.
3245 */
3246static isc_result_t
3247find_client_address(struct reply_state *reply) {
3248 struct iaddr send_addr;
3249 isc_result_t status = ISC_R_NORESOURCES;
1d17db44 3250 struct iasubopt *lease, *best_lease = NULL;
80c9fdb0
FD
3251 struct binding_scope **scope;
3252 struct group *group;
3253 int i;
3254
80c9fdb0
FD
3255 if (reply->static_lease) {
3256 if (reply->host == NULL)
98bf1607 3257 return DHCP_R_INVALIDARG;
80c9fdb0
FD
3258
3259 send_addr.len = 16;
3260 memcpy(send_addr.iabuf, reply->fixed.data, 16);
3261
80c9fdb0 3262 scope = &global_scope;
2267da84 3263 group = reply->subnet->group;
80c9fdb0
FD
3264 goto send_addr;
3265 }
3266
3267 if (reply->old_ia != NULL) {
1d17db44 3268 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
0d8c3d6e 3269 struct shared_network *candidate_shared;
01fa619f 3270 struct ipv6_pond *pond;
0d8c3d6e 3271
1d17db44 3272 lease = reply->old_ia->iasubopt[i];
0d8c3d6e 3273 candidate_shared = lease->ipv6_pool->shared_network;
01fa619f 3274 pond = lease->ipv6_pool->ipv6_pond;
80c9fdb0 3275
0d8c3d6e
DH
3276 /*
3277 * Look for the best lease on the client's shared
01fa619f 3278 * network, that is still permitted
0d8c3d6e 3279 */
01fa619f
SR
3280
3281 if ((candidate_shared != reply->shared) ||
3282 (lease6_usable(lease) != ISC_TRUE))
3283 continue;
3284
3285 if (((pond->prohibit_list != NULL) &&
3286 (permitted(reply->packet, pond->prohibit_list))) ||
3287 ((pond->permit_list != NULL) &&
3288 (!permitted(reply->packet, pond->permit_list))))
3289 continue;
3290
3291 best_lease = lease_compare(lease, best_lease);
80c9fdb0
FD
3292 }
3293 }
3294
3295 /* Try to pick a new address if we didn't find one, or if we found an
3296 * abandoned lease.
3297 */
3298 if ((best_lease == NULL) || (best_lease->state == FTS_ABANDONED)) {
01fa619f 3299 status = pick_v6_address(reply);
80c9fdb0 3300 } else if (best_lease != NULL) {
1d17db44 3301 iasubopt_reference(&reply->lease, best_lease, MDL);
80c9fdb0
FD
3302 status = ISC_R_SUCCESS;
3303 }
3304
3305 /* Pick the abandoned lease as a last resort. */
3306 if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
3307 /* I don't see how this is supposed to be done right now. */
fb98e02e
TM
3308 log_error("Best match for DUID %s is an abandoned address,"
3309 " This may be a result of multiple clients attempting"
3310 " to use this DUID",
3311 print_hex_1(reply->client_id.len,
3312 reply->client_id.data, 60));
1d17db44 3313 /* iasubopt_reference(&reply->lease, best_lease, MDL); */
80c9fdb0
FD
3314 }
3315
3316 /* Give up now if we didn't find a lease. */
3317 if (status != ISC_R_SUCCESS)
3318 return status;
3319
3320 if (reply->lease == NULL)
3321 log_fatal("Impossible condition at %s:%d.", MDL);
3322
7d6180be
DH
3323 /* Draw binding scopes from the lease's binding scope, and config
3324 * from the lease's containing subnet and higher. Note that it may
3325 * be desirable to place the group attachment directly in the pool.
3326 */
80c9fdb0 3327 scope = &reply->lease->scope;
01fa619f 3328 group = reply->lease->ipv6_pool->ipv6_pond->group;
80c9fdb0
FD
3329
3330 send_addr.len = 16;
3331 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3332
3333 send_addr:
9322442f 3334 status = reply_process_is_addressed(reply, scope, group);
80c9fdb0
FD
3335 if (status != ISC_R_SUCCESS)
3336 return status;
3337
3338 status = reply_process_send_addr(reply, &send_addr);
3339 return status;
3340}
3341
3342/* Once an address is found for a client, perform several common functions;
3343 * Calculate and store valid and preferred lease times, draw client options
3344 * into the option state.
3345 */
3346static isc_result_t
9322442f 3347reply_process_is_addressed(struct reply_state *reply,
80c9fdb0
FD
3348 struct binding_scope **scope, struct group *group)
3349{
3350 isc_result_t status = ISC_R_SUCCESS;
3351 struct data_string data;
3352 struct option_cache *oc;
a7341359
SR
3353 struct option_state *tmp_options = NULL;
3354 struct on_star *on_star;
01fa619f 3355 int i;
80c9fdb0
FD
3356
3357 /* Initialize values we will cleanup. */
3358 memset(&data, 0, sizeof(data));
3359
a7341359
SR
3360 /*
3361 * Find the proper on_star block to use. We use the
3362 * one in the lease if we have a lease or the one in
3363 * the reply if we don't have a lease because this is
3364 * a static instance
3365 */
3366 if (reply->lease) {
3367 on_star = &reply->lease->on_star;
3368 } else {
3369 on_star = &reply->on_star;
3370 }
3371
3372 /*
3373 * Bring in the root configuration. We only do this to bring
3374 * in the on * statements, as we didn't have the lease available
3375 * we did it the first time.
3376 */
3377 option_state_allocate(&tmp_options, MDL);
3378 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3379 reply->packet->options, tmp_options,
3380 &global_scope, root_group, NULL,
3381 on_star);
3382 if (tmp_options != NULL) {
3383 option_state_dereference(&tmp_options, MDL);
3384 }
3385
2267da84
DH
3386 /*
3387 * Bring configured options into the root packet level cache - start
3388 * with the lease's closest enclosing group (passed in by the caller
3389 * as 'group').
3390 */
80c9fdb0
FD
3391 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3392 reply->packet->options, reply->opt_state,
a7341359 3393 scope, group, root_group, on_star);
80c9fdb0 3394
01fa619f
SR
3395 /* Execute statements from class scopes. */
3396 for (i = reply->packet->class_count; i > 0; i--) {
3397 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3398 reply->packet->options,
3399 reply->opt_state, scope,
3400 reply->packet->classes[i - 1]->group,
3401 group, on_star);
3402 }
3403
2267da84
DH
3404 /*
3405 * If there is a host record, over-ride with values configured there,
3406 * without re-evaluating configuration from the previously executed
3407 * group or its common enclosers.
3408 */
3409 if (reply->host != NULL)
3410 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3411 reply->packet->options,
3412 reply->opt_state, scope,
a7341359
SR
3413 reply->host->group, group,
3414 on_star);
2267da84 3415
80c9fdb0
FD
3416 /* Determine valid lifetime. */
3417 if (reply->client_valid == 0)
3418 reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
3419 else
3420 reply->send_valid = reply->client_valid;
3421
3422 oc = lookup_option(&server_universe, reply->opt_state,
3423 SV_DEFAULT_LEASE_TIME);
3424 if (oc != NULL) {
3425 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
3426 reply->packet->options,
3427 reply->opt_state,
3428 scope, oc, MDL) ||
3429 (data.len != 4)) {
3430 log_error("reply_process_is_addressed: unable to "
3431 "evaluate default lease time");
3432 status = ISC_R_FAILURE;
3433 goto cleanup;
3434 }
3435
3436 reply->send_valid = getULong(data.data);
3437 data_string_forget(&data, MDL);
3438 }
3439
36c4a037
SR
3440 /* Check to see if the lease time would cause us to wrap
3441 * in which case we make it infinite.
3442 * The following doesn't work on at least some systems:
3443 * (cur_time + reply->send_valid < cur_time)
3444 */
3445 if (reply->send_valid != 0xFFFFFFFF) {
3446 time_t test_time = cur_time + reply->send_valid;
3447 if (test_time < cur_time)
3448 reply->send_valid = 0xFFFFFFFF;
3449 }
3450
80c9fdb0
FD
3451 if (reply->client_prefer == 0)
3452 reply->send_prefer = reply->send_valid;
3453 else
3454 reply->send_prefer = reply->client_prefer;
3455
36c4a037
SR
3456 if ((reply->send_prefer >= reply->send_valid) &&
3457 (reply->send_valid != 0xFFFFFFFF))
80c9fdb0
FD
3458 reply->send_prefer = (reply->send_valid / 2) +
3459 (reply->send_valid / 8);
3460
3461 oc = lookup_option(&server_universe, reply->opt_state,
3462 SV_PREFER_LIFETIME);
3463 if (oc != NULL) {
3464 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
3465 reply->packet->options,
3466 reply->opt_state,
3467 scope, oc, MDL) ||
3468 (data.len != 4)) {
3469 log_error("reply_process_is_addressed: unable to "
3470 "evaluate preferred lease time");
3471 status = ISC_R_FAILURE;
3472 goto cleanup;
3473 }
3474
3475 reply->send_prefer = getULong(data.data);
3476 data_string_forget(&data, MDL);
3477 }
3478
3479 /* Note lowest values for later calculation of renew/rebind times. */
3480 if (reply->prefer > reply->send_prefer)
3481 reply->prefer = reply->send_prefer;
3482
3483 if (reply->valid > reply->send_valid)
3484 reply->valid = reply->send_valid;
3485
3486#if 0
3487 /*
3488 * XXX: Old 4.0.0 alpha code would change the host {} record
3489 * XXX: uid upon lease assignment. This was intended to cover the
3490 * XXX: case where a client first identifies itself using vendor
3491 * XXX: options in a solicit, or request, but later neglects to include
3492 * XXX: these options in a Renew or Rebind. It is not clear that this
3493 * XXX: is required, and has some startling ramifications (such as
3494 * XXX: how to recover this dynamic host {} state across restarts).
3495 */
3496 if (reply->host != NULL)
3497 change_host_uid(host, reply->client_id->data,
3498 reply->client_id->len);
3499#endif /* 0 */
3500
3501 /* Perform dynamic lease related update work. */
3502 if (reply->lease != NULL) {
1acab09f
FD
3503 /* Cached lifetimes */
3504 reply->lease->prefer = reply->send_prefer;
3505 reply->lease->valid = reply->send_valid;
3506
36c4a037
SR
3507 /* Advance (or rewind) the valid lifetime.
3508 * In the protocol 0xFFFFFFFF is infinite
3509 * when connecting to the lease file MAX_TIME is
3510 */
5d89d60f 3511 if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
36c4a037
SR
3512 if (reply->send_valid == 0xFFFFFFFF) {
3513 reply->lease->soft_lifetime_end_time = MAX_TIME;
3514 } else {
3515 reply->lease->soft_lifetime_end_time =
3516 cur_time + reply->send_valid;
3517 }
5d89d60f
FD
3518 /* Wait before renew! */
3519 }
80c9fdb0 3520
1d17db44 3521 status = ia_add_iasubopt(reply->ia, reply->lease, MDL);
80c9fdb0
FD
3522 if (status != ISC_R_SUCCESS) {
3523 log_fatal("reply_process_is_addressed: Unable to "
3524 "attach lease to new IA: %s",
3525 isc_result_totext(status));
3526 }
3527
3528 /*
3529 * If this is a new lease, make sure it is attached somewhere.
3530 */
9322442f
FD
3531 if (reply->lease->ia == NULL) {
3532 ia_reference(&reply->lease->ia, reply->ia, MDL);
80c9fdb0
FD
3533 }
3534 }
3535
3536 /* Bring a copy of the relevant options into the IA scope. */
3537 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3538 reply->packet->options, reply->reply_ia,
a7341359 3539 scope, group, root_group, NULL);
80c9fdb0 3540
01fa619f
SR
3541 /* Execute statements from class scopes. */
3542 for (i = reply->packet->class_count; i > 0; i--) {
3543 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3544 reply->packet->options,
3545 reply->reply_ia, scope,
3546 reply->packet->classes[i - 1]->group,
3547 group, NULL);
3548 }
b31fe1d5 3549
2267da84
DH
3550 /*
3551 * And bring in host record configuration, if any, but not to overlap
3552 * the previous group or its common enclosers.
3553 */
3554 if (reply->host != NULL)
3555 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3556 reply->packet->options,
3557 reply->reply_ia, scope,
a7341359 3558 reply->host->group, group, NULL);
2267da84 3559
80c9fdb0
FD
3560 cleanup:
3561 if (data.data != NULL)
3562 data_string_forget(&data, MDL);
3563
3564 if (status == ISC_R_SUCCESS)
3565 reply->client_resources++;
3566
3567 return status;
3568}
3569
3570/* Simply send an IAADDR within the IA scope as described. */
3571static isc_result_t
3572reply_process_send_addr(struct reply_state *reply, struct iaddr *addr) {
3573 isc_result_t status = ISC_R_SUCCESS;
3574 struct data_string data;
3575
3576 memset(&data, 0, sizeof(data));
3577
3578 /* Now append the lease. */
3579 data.len = IAADDR_OFFSET;
3580 if (!buffer_allocate(&data.buffer, data.len, MDL)) {
3581 log_error("reply_process_send_addr: out of memory"
3582 "allocating new IAADDR buffer.");
3583 status = ISC_R_NOMEMORY;
3584 goto cleanup;
3585 }
3586 data.data = data.buffer->data;
3587
3588 memcpy(data.buffer->data, addr->iabuf, 16);
3589 putULong(data.buffer->data + 16, reply->send_prefer);
3590 putULong(data.buffer->data + 20, reply->send_valid);
3591
3592 if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
3593 data.buffer, data.buffer->data,
3594 data.len, D6O_IAADDR, 0)) {
3595 log_error("reply_process_send_addr: unable "
3596 "to save IAADDR option");
3597 status = ISC_R_FAILURE;
3598 goto cleanup;
3599 }
3600
9322442f 3601 reply->resources_included = ISC_TRUE;
80c9fdb0
FD
3602
3603 cleanup:
3604 if (data.data != NULL)
3605 data_string_forget(&data, MDL);
3606
3607 return status;
3608}
3609
3610/* Choose the better of two leases. */
1d17db44
FD
3611static struct iasubopt *
3612lease_compare(struct iasubopt *alpha, struct iasubopt *beta) {
80c9fdb0
FD
3613 if (alpha == NULL)
3614 return beta;
3615 if (beta == NULL)
3616 return alpha;
3617
3618 switch(alpha->state) {
3619 case FTS_ACTIVE:
3620 switch(beta->state) {
3621 case FTS_ACTIVE:
3622 /* Choose the lease with the longest lifetime (most
3623 * likely the most recently allocated).
3624 */
b31fe1d5 3625 if (alpha->hard_lifetime_end_time <
5d89d60f 3626 beta->hard_lifetime_end_time)
80c9fdb0
FD
3627 return beta;
3628 else
3629 return alpha;
3630
3631 case FTS_EXPIRED:
3632 case FTS_ABANDONED:
3633 return alpha;
3634
3635 default:
3636 log_fatal("Impossible condition at %s:%d.", MDL);
3637 }
3638 break;
3639
3640 case FTS_EXPIRED:
3641 switch (beta->state) {
3642 case FTS_ACTIVE:
3643 return beta;
3644
3645 case FTS_EXPIRED:
3646 /* Choose the most recently expired lease. */
5d89d60f
FD
3647 if (alpha->hard_lifetime_end_time <
3648 beta->hard_lifetime_end_time)
3649 return beta;
3650 else if ((alpha->hard_lifetime_end_time ==
3651 beta->hard_lifetime_end_time) &&
3652 (alpha->soft_lifetime_end_time <
3653 beta->soft_lifetime_end_time))
80c9fdb0
FD
3654 return beta;
3655 else
3656 return alpha;
3657
3658 case FTS_ABANDONED:
3659 return alpha;
3660
3661 default:
3662 log_fatal("Impossible condition at %s:%d.", MDL);
3663 }
3664 break;
3665
3666 case FTS_ABANDONED:
3667 switch (beta->state) {
3668 case FTS_ACTIVE:
3669 case FTS_EXPIRED:
3670 return alpha;
3671
3672 case FTS_ABANDONED:
3673 /* Choose the lease that was abandoned longest ago. */
5d89d60f
FD
3674 if (alpha->hard_lifetime_end_time <
3675 beta->hard_lifetime_end_time)
80c9fdb0 3676 return alpha;
a07d99bb
TM
3677 else
3678 return beta;
80c9fdb0
FD
3679
3680 default:
3681 log_fatal("Impossible condition at %s:%d.", MDL);
3682 }
3683 break;
3684
3685 default:
3686 log_fatal("Impossible condition at %s:%d.", MDL);
3687 }
3688
3689 log_fatal("Triple impossible condition at %s:%d.", MDL);
3690 return NULL;
3691}
3692
3693/* Process a client-supplied IA_PD. This may append options to the tail of
3694 * the reply packet being built in the reply_state structure.
3695 */
3696static isc_result_t
9322442f 3697reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
80c9fdb0
FD
3698 isc_result_t status = ISC_R_SUCCESS;
3699 u_int32_t iaid;
3700 unsigned ia_cursor;
3701 struct option_state *packet_ia;
3702 struct option_cache *oc;
9322442f 3703 struct data_string ia_data, data;
80c9fdb0
FD
3704
3705 /* Initialize values that will get cleaned up on return. */
3706 packet_ia = NULL;
9322442f 3707 memset(&ia_data, 0, sizeof(ia_data));
80c9fdb0 3708 memset(&data, 0, sizeof(data));
b31fe1d5 3709 /*
9322442f 3710 * Note that find_client_prefix() may set reply->lease.
80c9fdb0
FD
3711 */
3712
3713 /* Make sure there is at least room for the header. */
3714 if ((reply->cursor + IA_PD_OFFSET + 4) > sizeof(reply->buf)) {
3715 log_error("reply_process_ia_pd: Reply too long for IA.");
3716 return ISC_R_NOSPACE;
3717 }
3718
3719
3720 /* Fetch the IA_PD contents. */
9322442f
FD
3721 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
3722 ia, IA_PD_OFFSET)) {
3723 log_error("reply_process_ia_pd: error evaluating ia");
80c9fdb0
FD
3724 status = ISC_R_FAILURE;
3725 goto cleanup;
3726 }
3727
3728 /* Extract IA_PD header contents. */
9322442f
FD
3729 iaid = getULong(ia_data.data);
3730 reply->renew = getULong(ia_data.data + 4);
3731 reply->rebind = getULong(ia_data.data + 8);
80c9fdb0
FD
3732
3733 /* Create an IA_PD structure. */
b31fe1d5 3734 if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
9322442f
FD
3735 reply->client_id.len, MDL) != ISC_R_SUCCESS) {
3736 log_error("reply_process_ia_pd: no memory for ia.");
80c9fdb0
FD
3737 status = ISC_R_NOMEMORY;
3738 goto cleanup;
3739 }
9322442f 3740 reply->ia->ia_type = D6O_IA_PD;
80c9fdb0
FD
3741
3742 /* Cache pre-existing IA_PD, if any. */
9322442f
FD
3743 ia_hash_lookup(&reply->old_ia, ia_pd_active,
3744 (unsigned char *)reply->ia->iaid_duid.data,
3745 reply->ia->iaid_duid.len, MDL);
80c9fdb0
FD
3746
3747 /*
3748 * Create an option cache to carry the IA_PD option contents, and
3749 * execute any user-supplied values into it.
3750 */
3751 if (!option_state_allocate(&reply->reply_ia, MDL)) {
3752 status = ISC_R_NOMEMORY;
3753 goto cleanup;
3754 }
3755
3756 /* Check & count the fixed prefix host records. */
3757 reply->static_prefixes = 0;
3758 if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
3759 struct iaddrcidrnetlist *fp;
3760
3761 for (fp = reply->host->fixed_prefix; fp != NULL;
3762 fp = fp->next) {
3763 reply->static_prefixes += 1;
3764 }
3765 }
3766
3767 /*
3768 * Save the cursor position at the start of the IA_PD, so we can
3769 * set length and adjust t1/t2 values later. We write a temporary
3770 * header out now just in case we decide to adjust the packet
3771 * within sub-process functions.
3772 */
3773 ia_cursor = reply->cursor;
3774
3775 /* Initialize the IA_PD header. First the code. */
3776 putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_PD);
3777 reply->cursor += 2;
3778
3779 /* Then option length. */
3780 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
3781 reply->cursor += 2;
3782
3783 /* Then IA_PD header contents; IAID. */
3784 putULong(reply->buf.data + reply->cursor, iaid);
3785 reply->cursor += 4;
3786
3787 /* We store the client's t1 for now, and may over-ride it later. */
3788 putULong(reply->buf.data + reply->cursor, reply->renew);
3789 reply->cursor += 4;
3790
3791 /* We store the client's t2 for now, and may over-ride it later. */
3792 putULong(reply->buf.data + reply->cursor, reply->rebind);
3793 reply->cursor += 4;
3794
b31fe1d5 3795 /*
80c9fdb0
FD
3796 * For each prefix in this IA_PD, decide what to do about it.
3797 */
3798 oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAPREFIX);
3799 reply->valid = reply->prefer = 0xffffffff;
3800 reply->client_valid = reply->client_prefer = 0;
3801 reply->preflen = -1;
3802 for (; oc != NULL ; oc = oc->next) {
3803 status = reply_process_prefix(reply, oc);
3804
3805 /*
3806 * Canceled means we did not allocate prefixes to the
3807 * client, but we're "done" with this IA - we set a status
3808 * code. So transmit this reply, e.g., move on to the next
3809 * IA.
3810 */
3811 if (status == ISC_R_CANCELED)
3812 break;
3813
d19fa5a1
SR
3814 if ((status != ISC_R_SUCCESS) &&
3815 (status != ISC_R_ADDRINUSE) &&
3816 (status != ISC_R_ADDRNOTAVAIL))
80c9fdb0
FD
3817 goto cleanup;
3818 }
3819
9322442f 3820 reply->pd_count++;
80c9fdb0
FD
3821
3822 /*
3823 * If we fell through the above and never gave the client
3824 * a prefix, give it one now.
3825 */
3826 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
3827 status = find_client_prefix(reply);
3828
3829 if (status == ISC_R_NORESOURCES) {
3830 switch (reply->packet->dhcpv6_msg_type) {
3831 case DHCPV6_SOLICIT:
3832 /*
3833 * No prefix for any IA is handled
3834 * by the caller.
3835 */
3836 /* FALL THROUGH */
3837
3838 case DHCPV6_REQUEST:
3839 /* Same than for addresses. */
3840 option_state_dereference(&reply->reply_ia, MDL);
3841 if (!option_state_allocate(&reply->reply_ia,
3842 MDL))
3843 {
3844 log_error("reply_process_ia_pd: No "
3845 "memory for option state "
3846 "wipe.");
3847 status = ISC_R_NOMEMORY;
3848 goto cleanup;
3849 }
3850
3851 if (!set_status_code(STATUS_NoPrefixAvail,
3852 "No prefixes available "
3853 "for this interface.",
3854 reply->reply_ia)) {
3855 log_error("reply_process_ia_pd: "
3856 "Unable to set "
3857 "NoPrefixAvail status "
3858 "code.");
3859 status = ISC_R_FAILURE;
3860 goto cleanup;
3861 }
3862
3863 status = ISC_R_SUCCESS;
3864 break;
3865
3866 default:
9322442f 3867 if (reply->resources_included)
80c9fdb0
FD
3868 status = ISC_R_SUCCESS;
3869 else
3870 goto cleanup;
3871 break;
3872 }
3873 }
3874
3875 if (status != ISC_R_SUCCESS)
3876 goto cleanup;
3877 }
3878
3879 reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
3880 sizeof(reply->buf) - reply->cursor,
3881 reply->reply_ia, reply->packet,
3882 required_opts_IA_PD, NULL);
3883
3884 /* Reset the length of this IA_PD to match what was just written. */
3885 putUShort(reply->buf.data + ia_cursor + 2,
3886 reply->cursor - (ia_cursor + 4));
3887
3888 /*
3889 * T1/T2 time selection is kind of weird. We actually use DHCP
3890 * (v4) scoped options as handy existing places where these might
3891 * be configured by an administrator. A value of zero tells the
3892 * client it may choose its own renewal time.
3893 */
3894 reply->renew = 0;
3895 oc = lookup_option(&dhcp_universe, reply->opt_state,
3896 DHO_DHCP_RENEWAL_TIME);
3897 if (oc != NULL) {
3898 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
3899 reply->packet->options,
3900 reply->opt_state, &global_scope,
3901 oc, MDL) ||
3902 (data.len != 4)) {
3903 log_error("Invalid renewal time.");
3904 } else {
3905 reply->renew = getULong(data.data);
3906 }
3907
3908 if (data.data != NULL)
3909 data_string_forget(&data, MDL);
3910 }
3911 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
3912
3913 /* Now T2. */
3914 reply->rebind = 0;
3915 oc = lookup_option(&dhcp_universe, reply->opt_state,
3916 DHO_DHCP_REBINDING_TIME);
3917 if (oc != NULL) {
3918 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
3919 reply->packet->options,
3920 reply->opt_state, &global_scope,
3921 oc, MDL) ||
3922 (data.len != 4)) {
3923 log_error("Invalid rebinding time.");
3924 } else {
3925 reply->rebind = getULong(data.data);
3926 }
3927
3928 if (data.data != NULL)
3929 data_string_forget(&data, MDL);
3930 }
3931 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
3932
d9b5c150
SR
3933 /*
3934 * yes, goto's aren't the best but we also want to avoid extra
3935 * indents
3936 */
3937 if (status == ISC_R_CANCELED)
3938 goto cleanup;
3939
3940 /*
3941 * Handle static prefixes, we always log stuff and if it's
3942 * a hard binding we run any commit statements that we have
3943 */
3944 if (reply->static_prefixes != 0) {
3945 char tmp_addr[INET6_ADDRSTRLEN];
3946 log_info("%s PD: address %s/%d to client with duid %s "
3947 "iaid = %d static",
3948 dhcpv6_type_names[reply->buf.reply.msg_type],
3949 inet_ntop(AF_INET6, reply->fixed_pref.lo_addr.iabuf,
3950 tmp_addr, sizeof(tmp_addr)),
3951 reply->fixed_pref.bits,
3952 print_hex_1(reply->client_id.len,
3953 reply->client_id.data, 60),
3954 iaid);
3955 if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
3956 (reply->on_star.on_commit != NULL)) {
3957 execute_statements(NULL, reply->packet, NULL, NULL,
3958 reply->packet->options,
3959 reply->opt_state,
3960 NULL, reply->on_star.on_commit,
3961 NULL);
3962 executable_statement_dereference
3963 (&reply->on_star.on_commit, MDL);
3964 }
3965 goto cleanup;
3966 }
3967
3968 /*
3969 * If we have any addresses log what we are doing.
3970 */
3971 if (reply->ia->num_iasubopt != 0) {
3972 struct iasubopt *tmp;
3973 int i;
3974 char tmp_addr[INET6_ADDRSTRLEN];
3975
3976 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3977 tmp = reply->ia->iasubopt[i];
3978
3979 log_info("%s PD: address %s/%d to client with duid %s"
36c4a037 3980 " iaid = %d valid for %u seconds",
d9b5c150
SR
3981 dhcpv6_type_names[reply->buf.reply.msg_type],
3982 inet_ntop(AF_INET6, &tmp->addr,
3983 tmp_addr, sizeof(tmp_addr)),
3984 (int)tmp->plen,
3985 print_hex_1(reply->client_id.len,
3986 reply->client_id.data, 60),
3987 iaid, tmp->valid);
3988 }
3989 }
3990
80c9fdb0
FD
3991 /*
3992 * If this is not a 'soft' binding, consume the new changes into
3993 * the database (if any have been attached to the ia_pd).
3994 *
3995 * Loop through the assigned dynamic prefixes, referencing the
3996 * prefixes onto this IA_PD rather than any old ones, and updating
3997 * prefix pool timers for each (if any).
3998 */
d9b5c150 3999 if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
1d17db44
FD
4000 (reply->ia->num_iasubopt != 0)) {
4001 struct iasubopt *tmp;
80c9fdb0
FD
4002 struct data_string *ia_id;
4003 int i;
4004
1d17db44
FD
4005 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
4006 tmp = reply->ia->iasubopt[i];
80c9fdb0 4007
9322442f
FD
4008 if (tmp->ia != NULL)
4009 ia_dereference(&tmp->ia, MDL);
4010 ia_reference(&tmp->ia, reply->ia, MDL);
80c9fdb0 4011
5d89d60f 4012 /* Commit 'hard' bindings. */
9322442f
FD
4013 renew_lease6(tmp->ipv6_pool, tmp);
4014 schedule_lease_timeout(tmp->ipv6_pool);
a7341359
SR
4015
4016 /* If we have anything to do on commit do it now */
4017 if (tmp->on_star.on_commit != NULL) {
4018 execute_statements(NULL, reply->packet,
b31fe1d5 4019 NULL, NULL,
a7341359
SR
4020 reply->packet->options,
4021 reply->opt_state,
58cb5d86 4022 &tmp->scope,
a7341359
SR
4023 tmp->on_star.on_commit,
4024 &tmp->on_star);
4025 executable_statement_dereference
4026 (&tmp->on_star.on_commit, MDL);
4027 }
250f7134
SR
4028
4029 /* Do our threshold check. */
4030 check_pool6_threshold(reply, tmp);
80c9fdb0
FD
4031 }
4032
9322442f
FD
4033 /* Remove any old ia from the hash. */
4034 if (reply->old_ia != NULL) {
4035 ia_id = &reply->old_ia->iaid_duid;
4036 ia_hash_delete(ia_pd_active,
4037 (unsigned char *)ia_id->data,
4038 ia_id->len, MDL);
4039 ia_dereference(&reply->old_ia, MDL);
80c9fdb0
FD
4040 }
4041
9322442f 4042 /* Put new ia into the hash. */
1acab09f 4043 reply->ia->cltt = cur_time;
9322442f
FD
4044 ia_id = &reply->ia->iaid_duid;
4045 ia_hash_add(ia_pd_active, (unsigned char *)ia_id->data,
4046 ia_id->len, reply->ia, MDL);
80c9fdb0 4047
9322442f 4048 write_ia(reply->ia);
ad80055f
SR
4049 } else {
4050 schedule_lease_timeout_reply(reply);
80c9fdb0
FD
4051 }
4052
4053 cleanup:
4054 if (packet_ia != NULL)
4055 option_state_dereference(&packet_ia, MDL);
4056 if (reply->reply_ia != NULL)
4057 option_state_dereference(&reply->reply_ia, MDL);
9322442f
FD
4058 if (ia_data.data != NULL)
4059 data_string_forget(&ia_data, MDL);
80c9fdb0
FD
4060 if (data.data != NULL)
4061 data_string_forget(&data, MDL);
9322442f
FD
4062 if (reply->ia != NULL)
4063 ia_dereference(&reply->ia, MDL);
4064 if (reply->old_ia != NULL)
4065 ia_dereference(&reply->old_ia, MDL);
4066 if (reply->lease != NULL)
1d17db44 4067 iasubopt_dereference(&reply->lease, MDL);
a7341359
SR
4068 if (reply->on_star.on_expiry != NULL)
4069 executable_statement_dereference
4070 (&reply->on_star.on_expiry, MDL);
4071 if (reply->on_star.on_release != NULL)
4072 executable_statement_dereference
4073 (&reply->on_star.on_release, MDL);
80c9fdb0
FD
4074
4075 /*
4076 * ISC_R_CANCELED is a status code used by the prefix processing to
4077 * indicate we're replying with a status code. This is still a
4078 * success at higher layers.
4079 */
4080 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
4081}
4082
34711bb7
SR
4083/*!
4084 *
4085 * \brief Find the proper scoping group for use with a v6 static prefix.
4086 *
4087 * We start by trying to find a subnet based on the given prefix and
4088 * the shared network. If we don't find one then the prefix has been
4089 * declared outside of any subnets. If there is a static address
4090 * associated with the host we use it to try and find a subnet (this
4091 * should succeed). If there isn't a static address we fall back
4092 * to the shared subnet itself.
4093 * Once we have a subnet we extract the group from it and return it.
4094 *
4095 * \param reply - the reply structure we use to collect information
4096 * we will use the fields shared, fixed_pref and host
4097 * from the structure
4098 *
4099 * \return a pointer to the group structure to use for scoping
4100 */
4101
4102static struct group *
4103find_group_by_prefix(struct reply_state *reply) {
4104 /* default group if we don't find anything better */
4105 struct group *group = reply->shared->group;
4106 struct subnet *subnet = NULL;
4107 struct iaddr tmp_addr;
4108 struct data_string fixed_addr;
4109
4110 /* Try with the prefix first */
4111 if (find_grouped_subnet(&subnet, reply->shared,
4112 reply->fixed_pref.lo_addr, MDL) != 0) {
4113 group = subnet->group;
4114 subnet_dereference(&subnet, MDL);
4115 return (group);
4116 }
4117
4118 /* Didn't find a subnet via prefix, what about fixed address */
4119 /* The caller has already tested reply->host != NULL */
4120
4121 memset(&fixed_addr, 0, sizeof(fixed_addr));
4122
4123 if ((reply->host->fixed_addr != NULL) &&
4124 (evaluate_option_cache(&fixed_addr, NULL, NULL, NULL,
4125 NULL, NULL, &global_scope,
4126 reply->host->fixed_addr, MDL))) {
4127 if (fixed_addr.len >= 16) {
4128 tmp_addr.len = 16;
4129 memcpy(tmp_addr.iabuf, fixed_addr.data, 16);
4130 if (find_grouped_subnet(&subnet, reply->shared,
4131 tmp_addr, MDL) != 0) {
4132 group = subnet->group;
4133 subnet_dereference(&subnet, MDL);
4134 }
4135 }
4136 data_string_forget(&fixed_addr, MDL);
4137 }
4138
4139 /* return whatever we got */
4140 return (group);
4141}
4142
80c9fdb0
FD
4143/*
4144 * Process an IAPREFIX within a given IA_PD, storing any IAPREFIX reply
4145 * contents into the reply's current ia_pd-scoped option cache. Returns
4146 * ISC_R_CANCELED in the event we are replying with a status code and do
4147 * not wish to process more IAPREFIXes within this IA_PD.
4148 */
4149static isc_result_t
4150reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
4151 u_int32_t pref_life, valid_life;
4152 struct binding_scope **scope;
80c9fdb0
FD
4153 struct iaddrcidrnet tmp_pref;
4154 struct option_cache *oc;
4155 struct data_string iapref, data;
80c9fdb0 4156 isc_result_t status = ISC_R_SUCCESS;
01fa619f 4157 struct group *group;
80c9fdb0
FD
4158
4159 /* Initializes values that will be cleaned up. */
80c9fdb0
FD
4160 memset(&iapref, 0, sizeof(iapref));
4161 memset(&data, 0, sizeof(data));
9322442f 4162 /* Note that reply->lease may be set by prefix_is_owned() */
80c9fdb0
FD
4163
4164 /*
4165 * There is no point trying to process an incoming prefix if there
4166 * is no room for an outgoing prefix.
4167 */
4168 if ((reply->cursor + 29) > sizeof(reply->buf)) {
4169 log_error("reply_process_prefix: Out of room for prefix.");
4170 return ISC_R_NOSPACE;
4171 }
4172
4173 /* Extract this IAPREFIX option. */
b31fe1d5 4174 if (!evaluate_option_cache(&iapref, reply->packet, NULL, NULL,
80c9fdb0
FD
4175 reply->packet->options, NULL, &global_scope,
4176 pref, MDL) ||
4177 (iapref.len < IAPREFIX_OFFSET)) {
4178 log_error("reply_process_prefix: error evaluating IAPREFIX.");
4179 status = ISC_R_FAILURE;
4180 goto cleanup;
4181 }
4182
4183 /*
4184 * Layout: preferred and valid lifetimes followed by the prefix
4185 * length and the IPv6 address.
4186 */
4187 pref_life = getULong(iapref.data);
4188 valid_life = getULong(iapref.data + 4);
4189
4190 if ((reply->client_valid == 0) ||
4191 (reply->client_valid > valid_life))
4192 reply->client_valid = valid_life;
4193
4194 if ((reply->client_prefer == 0) ||
4195 (reply->client_prefer > pref_life))
4196 reply->client_prefer = pref_life;
4197
b31fe1d5 4198 /*
80c9fdb0
FD
4199 * Clients may choose to send ::/0 as a prefix, with the idea to give
4200 * hints about preferred-lifetime or valid-lifetime.
4201 */
4202 tmp_pref.lo_addr.len = 16;
4203 memset(tmp_pref.lo_addr.iabuf, 0, 16);
4204 if ((iapref.data[8] == 0) &&
4205 (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
4206 /* Status remains success; we just ignore this one. */
4207 goto cleanup;
4208 }
4209
4210 /*
4211 * Clients may choose to send ::/X as a prefix to specify a
4212 * preferred/requested prefix length. Note X is never zero here.
4213 */
4214 tmp_pref.bits = (int) iapref.data[8];
4215 if (reply->preflen < 0) {
4216 /* Cache the first preferred prefix length. */
4217 reply->preflen = tmp_pref.bits;
4218 }
4219 if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
4220 goto cleanup;
4221 }
4222
4223 memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
4224
4225 /* Verify the prefix belongs to the client. */
4226 if (!prefix_is_owned(reply, &tmp_pref)) {
4227 /* Same than for addresses. */
4228 if ((reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) ||
4229 (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) ||
4230 (reply->packet->dhcpv6_msg_type == DHCPV6_REBIND)) {
4231 status = reply_process_try_prefix(reply, &tmp_pref);
4232
4233 /* Either error out or skip this prefix. */
d19fa5a1
SR
4234 if ((status != ISC_R_SUCCESS) &&
4235 (status != ISC_R_ADDRINUSE) &&
4236 (status != ISC_R_ADDRNOTAVAIL))
80c9fdb0
FD
4237 goto cleanup;
4238
9322442f 4239 if (reply->lease == NULL) {
80c9fdb0
FD
4240 if (reply->packet->dhcpv6_msg_type ==
4241 DHCPV6_REBIND) {
4242 reply->send_prefer = 0;
4243 reply->send_valid = 0;
4244 goto send_pref;
4245 }
4246
4247 /* status remains success - ignore */
4248 goto cleanup;
4249 }
80c9fdb0
FD
4250 /*
4251 * RFC3633 section 18.2.3:
4252 *
4253 * If the delegating router cannot find a binding
4254 * for the requesting router's IA_PD the delegating
4255 * router returns the IA_PD containing no prefixes
4256 * with a Status Code option set to NoBinding in the
4257 * Reply message.
4258 *
4259 * On mismatch we (ab)use this pretending we have not the IA
4260 * as soon as we have not a prefix.
4261 */
4262 } else if (reply->packet->dhcpv6_msg_type == DHCPV6_RENEW) {
4263 /* Rewind the IA_PD to empty. */
4264 option_state_dereference(&reply->reply_ia, MDL);
4265 if (!option_state_allocate(&reply->reply_ia, MDL)) {
4266 log_error("reply_process_prefix: No memory "
4267 "for option state wipe.");
4268 status = ISC_R_NOMEMORY;
4269 goto cleanup;
4270 }
4271
4272 /* Append a NoBinding status code. */
4273 if (!set_status_code(STATUS_NoBinding,
4274 "Prefix not bound to this "
4275 "interface.", reply->reply_ia)) {
4276 log_error("reply_process_prefix: Unable to "
4277 "attach status code.");
4278 status = ISC_R_FAILURE;
4279 goto cleanup;
4280 }
4281
4282 /* Fin (no more IAPREFIXes). */
4283 status = ISC_R_CANCELED;
4284 goto cleanup;
4285 } else {
4286 log_error("It is impossible to lease a client that is "
4287 "not sending a solicit, request, renew, or "
4288 "rebind message.");
4289 status = ISC_R_FAILURE;
4290 goto cleanup;
4291 }
4292 }
4293
4294 if (reply->static_prefixes > 0) {
4295 if (reply->host == NULL)
4296 log_fatal("Impossible condition at %s:%d.", MDL);
4297
4298 scope = &global_scope;
01fa619f 4299
34711bb7 4300 /* Copy the static prefix for logging and finding the group */
d9b5c150 4301 memcpy(&reply->fixed_pref, &tmp_pref, sizeof(tmp_pref));
34711bb7
SR
4302
4303 /* Try to find a group for the static prefix */
4304 group = find_group_by_prefix(reply);
80c9fdb0 4305 } else {
9322442f 4306 if (reply->lease == NULL)
80c9fdb0
FD
4307 log_fatal("Impossible condition at %s:%d.", MDL);
4308
9322442f 4309 scope = &reply->lease->scope;
01fa619f 4310 group = reply->lease->ipv6_pool->ipv6_pond->group;
80c9fdb0
FD
4311 }
4312
4313 /*
4314 * If client_resources is nonzero, then the reply_process_is_prefixed
4315 * function has executed configuration state into the reply option
4316 * cache. We will use that valid cache to derive configuration for
4317 * whether or not to engage in additional prefixes, and similar.
4318 */
4319 if (reply->client_resources != 0) {
4320 unsigned limit = 1;
4321
4322 /*
4323 * Does this client have "enough" prefixes already? Default
4324 * to one. Everybody gets one, and one should be enough for
4325 * anybody.
4326 */
4327 oc = lookup_option(&server_universe, reply->opt_state,
4328 SV_LIMIT_PREFS_PER_IA);
4329 if (oc != NULL) {
4330 if (!evaluate_option_cache(&data, reply->packet,
4331 NULL, NULL,
4332 reply->packet->options,
4333 reply->opt_state,
4334 scope, oc, MDL) ||
4335 (data.len != 4)) {
4336 log_error("reply_process_prefix: unable to "
4337 "evaluate prefs-per-ia value.");
4338 status = ISC_R_FAILURE;
4339 goto cleanup;
4340 }
4341
4342 limit = getULong(data.data);
4343 data_string_forget(&data, MDL);
4344 }
4345
4346 /*
4347 * If we wish to limit the client to a certain number of
4348 * prefixes, then omit the prefix from the reply.
4349 */
4350 if (reply->client_resources >= limit)
4351 goto cleanup;
4352 }
4353
01fa619f 4354 status = reply_process_is_prefixed(reply, scope, group);
80c9fdb0
FD
4355 if (status != ISC_R_SUCCESS)
4356 goto cleanup;
4357
4358 send_pref:
4359 status = reply_process_send_prefix(reply, &tmp_pref);
4360
4361 cleanup:
4362 if (iapref.data != NULL)
4363 data_string_forget(&iapref, MDL);
4364 if (data.data != NULL)
4365 data_string_forget(&data, MDL);
9322442f 4366 if (reply->lease != NULL)
1d17db44 4367 iasubopt_dereference(&reply->lease, MDL);
80c9fdb0
FD
4368
4369 return status;
4370}
4371
4372/*
4373 * Verify the prefix belongs to the client. If we've got a host
4374 * record with fixed prefixes, it has to be an assigned prefix
4375 * (fault out all else). Otherwise it's a dynamic prefix, so lookup
4376 * that prefix and make sure it belongs to this DUID:IAID pair.
4377 */
4378static isc_boolean_t
4379prefix_is_owned(struct reply_state *reply, struct iaddrcidrnet *pref) {
4380 struct iaddrcidrnetlist *l;
4381 int i;
01fa619f 4382 struct ipv6_pond *pond;
80c9fdb0
FD
4383
4384 /*
4385 * This faults out prefixes that don't match fixed prefixes.
4386 */
4387 if (reply->static_prefixes > 0) {
4388 for (l = reply->host->fixed_prefix; l != NULL; l = l->next) {
4389 if ((pref->bits == l->cidrnet.bits) &&
4390 (memcmp(pref->lo_addr.iabuf,
4391 l->cidrnet.lo_addr.iabuf, 16) == 0))
bc7f8b8e 4392 return (ISC_TRUE);
80c9fdb0 4393 }
bc7f8b8e 4394 return (ISC_FALSE);
80c9fdb0
FD
4395 }
4396
9322442f 4397 if ((reply->old_ia == NULL) ||
1d17db44 4398 (reply->old_ia->num_iasubopt == 0))
bc7f8b8e 4399 return (ISC_FALSE);
80c9fdb0 4400
1d17db44
FD
4401 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4402 struct iasubopt *tmp;
80c9fdb0 4403
1d17db44 4404 tmp = reply->old_ia->iasubopt[i];
80c9fdb0
FD
4405
4406 if ((pref->bits == (int) tmp->plen) &&
bc7f8b8e
SR
4407 (memcmp(pref->lo_addr.iabuf, &tmp->addr, 16) == 0)) {
4408 if (lease6_usable(tmp) == ISC_FALSE) {
4409 return (ISC_FALSE);
4410 }
01fa619f
SR
4411
4412 pond = tmp->ipv6_pool->ipv6_pond;
4413 if (((pond->prohibit_list != NULL) &&
4414 (permitted(reply->packet, pond->prohibit_list))) ||
4415 ((pond->permit_list != NULL) &&
4416 (!permitted(reply->packet, pond->permit_list))))
4417 return (ISC_FALSE);
4418
1d17db44 4419 iasubopt_reference(&reply->lease, tmp, MDL);
bc7f8b8e 4420 return (ISC_TRUE);
80c9fdb0
FD
4421 }
4422 }
4423
bc7f8b8e 4424 return (ISC_FALSE);
80c9fdb0
FD
4425}
4426
4427/*
4428 * This function only returns failure on 'hard' failures. If it succeeds,
4429 * it will leave a prefix structure behind.
4430 */
4431static isc_result_t
4432reply_process_try_prefix(struct reply_state *reply,
4433 struct iaddrcidrnet *pref) {
d19fa5a1 4434 isc_result_t status = ISC_R_ADDRNOTAVAIL;
01fa619f
SR
4435 struct ipv6_pool *pool = NULL;
4436 struct ipv6_pond *pond = NULL;
80c9fdb0
FD
4437 int i;
4438 struct data_string data_pref;
4439
bd72740e 4440 if ((reply == NULL) || (reply->shared == NULL) ||
d19fa5a1
SR
4441 (pref == NULL) || (reply->lease != NULL))
4442 return (DHCP_R_INVALIDARG);
4443
01fa619f
SR
4444 /*
4445 * Do a quick walk through of the ponds and pools
4446 * to see if we have any prefix pools
4447 */
4448 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
4449 if (pond->ipv6_pools == NULL)
4450 continue;
4451
4452 for (i = 0; (pool = pond->ipv6_pools[i]) != NULL; i++) {
4453 if (pool->pool_type == D6O_IA_PD)
4454 break;
4455 }
4456 if (pool != NULL)
4457 break;
4458 }
4459
4460 /* If we get here and p is NULL we have no useful pools */
4461 if (pool == NULL) {
d19fa5a1 4462 return (ISC_R_ADDRNOTAVAIL);
01fa619f 4463 }
80c9fdb0
FD
4464
4465 memset(&data_pref, 0, sizeof(data_pref));
4466 data_pref.len = 17;
4467 if (!buffer_allocate(&data_pref.buffer, data_pref.len, MDL)) {
4468 log_error("reply_process_try_prefix: out of memory.");
d19fa5a1 4469 return (ISC_R_NOMEMORY);
80c9fdb0
FD
4470 }
4471 data_pref.data = data_pref.buffer->data;
4472 data_pref.buffer->data[0] = (u_int8_t) pref->bits;
4473 memcpy(data_pref.buffer->data + 1, pref->lo_addr.iabuf, 16);
4474
01fa619f
SR
4475 /*
4476 * We have at least one pool that could provide a prefix
4477 * Now we walk through the ponds and pools again and check
4478 * to see if the client is permitted and if an prefix is
4479 * available
b31fe1d5 4480 *
01fa619f
SR
4481 */
4482
4483 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
4484 if (((pond->prohibit_list != NULL) &&
4485 (permitted(reply->packet, pond->prohibit_list))) ||
4486 ((pond->permit_list != NULL) &&
4487 (!permitted(reply->packet, pond->permit_list))))
9322442f 4488 continue;
01fa619f
SR
4489
4490 for (i = 0; (pool = pond->ipv6_pools[i]) != NULL; i++) {
4491 if (pool->pool_type != D6O_IA_PD) {
4492 continue;
4493 }
4494
4495 status = try_client_v6_prefix(&reply->lease, pool,
4496 &data_pref);
b31fe1d5 4497 /* If we found it in this pool (either in use or available),
01fa619f
SR
4498 there is no need to look further. */
4499 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4500 break;
4501 }
c7aa4dd4 4502 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
80c9fdb0
FD
4503 break;
4504 }
4505
4506 data_string_forget(&data_pref, MDL);
4507 /* Return just the most recent status... */
d19fa5a1 4508 return (status);
80c9fdb0
FD
4509}
4510
4511/* Look around for a prefix to give the client. First, look through the old
4512 * IA_PD for prefixes we can extend. Second, try to allocate a new prefix.
4513 * Finally, actually add that prefix into the current reply IA_PD.
4514 */
4515static isc_result_t
4516find_client_prefix(struct reply_state *reply) {
4517 struct iaddrcidrnet send_pref;
4518 isc_result_t status = ISC_R_NORESOURCES;
1d17db44 4519 struct iasubopt *prefix, *best_prefix = NULL;
80c9fdb0 4520 struct binding_scope **scope;
80c9fdb0 4521 int i;
01fa619f 4522 struct group *group;
80c9fdb0 4523
80c9fdb0
FD
4524 if (reply->static_prefixes > 0) {
4525 struct iaddrcidrnetlist *l;
4526
4527 if (reply->host == NULL)
98bf1607 4528 return DHCP_R_INVALIDARG;
80c9fdb0
FD
4529
4530 for (l = reply->host->fixed_prefix; l != NULL; l = l->next) {
4531 if (l->cidrnet.bits == reply->preflen)
4532 break;
4533 }
4534 if (l == NULL) {
4535 /*
4536 * If no fixed prefix has the preferred length,
4537 * get the first one.
4538 */
4539 l = reply->host->fixed_prefix;
4540 }
4541 memcpy(&send_pref, &l->cidrnet, sizeof(send_pref));
4542
80c9fdb0 4543 scope = &global_scope;
01fa619f 4544
d9b5c150
SR
4545 /* Copy the prefix for logging purposes */
4546 memcpy(&reply->fixed_pref, &l->cidrnet, sizeof(send_pref));
4547
34711bb7
SR
4548 /* Try to find a group for the static prefix */
4549 group = find_group_by_prefix(reply);
4550
80c9fdb0
FD
4551 goto send_pref;
4552 }
4553
9322442f 4554 if (reply->old_ia != NULL) {
1d17db44 4555 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
0d8c3d6e 4556 struct shared_network *candidate_shared;
01fa619f 4557 struct ipv6_pond *pond;
0d8c3d6e 4558
1d17db44 4559 prefix = reply->old_ia->iasubopt[i];
0d8c3d6e 4560 candidate_shared = prefix->ipv6_pool->shared_network;
01fa619f 4561 pond = prefix->ipv6_pool->ipv6_pond;
80c9fdb0 4562
0d8c3d6e
DH
4563 /*
4564 * Consider this prefix if it is in a global pool or
4565 * if it is scoped in a pool under the client's shared
4566 * network.
4567 */
01fa619f
SR
4568 if (((candidate_shared != NULL) &&
4569 (candidate_shared != reply->shared)) ||
4570 (lease6_usable(prefix) != ISC_TRUE))
4571 continue;
4572
4573 /*
4574 * And check if the prefix is still permitted
4575 */
4576
4577 if (((pond->prohibit_list != NULL) &&
4578 (permitted(reply->packet, pond->prohibit_list))) ||
4579 ((pond->permit_list != NULL) &&
4580 (!permitted(reply->packet, pond->permit_list))))
4581 continue;
4582
4583 best_prefix = prefix_compare(reply, prefix,
4584 best_prefix);
80c9fdb0
FD
4585 }
4586 }
4587
4588 /* Try to pick a new prefix if we didn't find one, or if we found an
4589 * abandoned prefix.
4590 */
4591 if ((best_prefix == NULL) || (best_prefix->state == FTS_ABANDONED)) {
01fa619f 4592 status = pick_v6_prefix(reply);
80c9fdb0 4593 } else if (best_prefix != NULL) {
1d17db44 4594 iasubopt_reference(&reply->lease, best_prefix, MDL);
80c9fdb0
FD
4595 status = ISC_R_SUCCESS;
4596 }
4597
4598 /* Pick the abandoned prefix as a last resort. */
4599 if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
4600 /* I don't see how this is supposed to be done right now. */
4601 log_error("Reclaiming abandoned prefixes is not yet "
4602 "supported. Treating this as an out of space "
4603 "condition.");
1d17db44 4604 /* iasubopt_reference(&reply->lease, best_prefix, MDL); */
80c9fdb0
FD
4605 }
4606
4607 /* Give up now if we didn't find a prefix. */
4608 if (status != ISC_R_SUCCESS)
5279b8f3
DH
4609 return status;
4610
9322442f 4611 if (reply->lease == NULL)
5279b8f3
DH
4612 log_fatal("Impossible condition at %s:%d.", MDL);
4613
9322442f 4614 scope = &reply->lease->scope;
01fa619f 4615 group = reply->lease->ipv6_pool->ipv6_pond->group;
5279b8f3 4616
80c9fdb0 4617 send_pref.lo_addr.len = 16;
9322442f
FD
4618 memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
4619 send_pref.bits = (int) reply->lease->plen;
5279b8f3 4620
80c9fdb0 4621 send_pref:
01fa619f 4622 status = reply_process_is_prefixed(reply, scope, group);
5279b8f3
DH
4623 if (status != ISC_R_SUCCESS)
4624 return status;
4625
80c9fdb0 4626 status = reply_process_send_prefix(reply, &send_pref);
5279b8f3
DH
4627 return status;
4628}
4629
80c9fdb0
FD
4630/* Once a prefix is found for a client, perform several common functions;
4631 * Calculate and store valid and preferred prefix times, draw client options
5279b8f3
DH
4632 * into the option state.
4633 */
4634static isc_result_t
9322442f 4635reply_process_is_prefixed(struct reply_state *reply,
80c9fdb0 4636 struct binding_scope **scope, struct group *group)
5279b8f3
DH
4637{
4638 isc_result_t status = ISC_R_SUCCESS;
4639 struct data_string data;
4640 struct option_cache *oc;
a7341359
SR
4641 struct option_state *tmp_options = NULL;
4642 struct on_star *on_star;
01fa619f 4643 int i;
5279b8f3
DH
4644
4645 /* Initialize values we will cleanup. */
4646 memset(&data, 0, sizeof(data));
4647
a7341359
SR
4648 /*
4649 * Find the proper on_star block to use. We use the
4650 * one in the lease if we have a lease or the one in
4651 * the reply if we don't have a lease because this is
4652 * a static instance
4653 */
4654 if (reply->lease) {
4655 on_star = &reply->lease->on_star;
4656 } else {
4657 on_star = &reply->on_star;
4658 }
4659
4660 /*
4661 * Bring in the root configuration. We only do this to bring
4662 * in the on * statements, as we didn't have the lease available
4663 * we we did it the first time.
4664 */
4665 option_state_allocate(&tmp_options, MDL);
4666 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4667 reply->packet->options, tmp_options,
4668 &global_scope, root_group, NULL,
4669 on_star);
4670 if (tmp_options != NULL) {
4671 option_state_dereference(&tmp_options, MDL);
4672 }
4673
2267da84
DH
4674 /*
4675 * Bring configured options into the root packet level cache - start
4676 * with the lease's closest enclosing group (passed in by the caller
4677 * as 'group').
4678 */
5279b8f3
DH
4679 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4680 reply->packet->options, reply->opt_state,
a7341359 4681 scope, group, root_group, on_star);
5279b8f3 4682
01fa619f
SR
4683 /* Execute statements from class scopes. */
4684 for (i = reply->packet->class_count; i > 0; i--) {
4685 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4686 reply->packet->options,
4687 reply->opt_state, scope,
4688 reply->packet->classes[i - 1]->group,
4689 group, on_star);
4690 }
b31fe1d5 4691
2267da84
DH
4692 /*
4693 * If there is a host record, over-ride with values configured there,
4694 * without re-evaluating configuration from the previously executed
4695 * group or its common enclosers.
4696 */
4697 if (reply->host != NULL)
4698 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4699 reply->packet->options,
4700 reply->opt_state, scope,
a7341359
SR
4701 reply->host->group, group,
4702 on_star);
2267da84 4703
5279b8f3
DH
4704 /* Determine valid lifetime. */
4705 if (reply->client_valid == 0)
4706 reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
4707 else
4708 reply->send_valid = reply->client_valid;
4709
4710 oc = lookup_option(&server_universe, reply->opt_state,
4711 SV_DEFAULT_LEASE_TIME);
4712 if (oc != NULL) {
b024480e 4713 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
5279b8f3
DH
4714 reply->packet->options,
4715 reply->opt_state,
b024480e 4716 scope, oc, MDL) ||
5279b8f3 4717 (data.len != 4)) {
80c9fdb0
FD
4718 log_error("reply_process_is_prefixed: unable to "
4719 "evaluate default prefix time");
5279b8f3
DH
4720 status = ISC_R_FAILURE;
4721 goto cleanup;
4722 }
4723
4724 reply->send_valid = getULong(data.data);
4725 data_string_forget(&data, MDL);
98bd7ca0 4726 }
5279b8f3 4727
36c4a037
SR
4728 /* Check to see if the lease time would cause us to wrap
4729 * in which case we make it infinite.
4730 * The following doesn't work on at least some systems:
4731 * (cur_time + reply->send_valid < cur_time)
4732 */
4733 if (reply->send_valid != 0xFFFFFFFF) {
4734 time_t test_time = cur_time + reply->send_valid;
4735 if (test_time < cur_time)
4736 reply->send_valid = 0xFFFFFFFF;
4737 }
4738
5279b8f3
DH
4739 if (reply->client_prefer == 0)
4740 reply->send_prefer = reply->send_valid;
4741 else
4742 reply->send_prefer = reply->client_prefer;
4743
36c4a037
SR
4744 if ((reply->send_prefer >= reply->send_valid) &&
4745 (reply->send_valid != 0xFFFFFFFF))
5279b8f3
DH
4746 reply->send_prefer = (reply->send_valid / 2) +
4747 (reply->send_valid / 8);
4748
4749 oc = lookup_option(&server_universe, reply->opt_state,
4750 SV_PREFER_LIFETIME);
4751 if (oc != NULL) {
b024480e 4752 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
5279b8f3
DH
4753 reply->packet->options,
4754 reply->opt_state,
b024480e 4755 scope, oc, MDL) ||
5279b8f3 4756 (data.len != 4)) {
80c9fdb0
FD
4757 log_error("reply_process_is_prefixed: unable to "
4758 "evaluate preferred prefix time");
5279b8f3
DH
4759 status = ISC_R_FAILURE;
4760 goto cleanup;
4761 }
4762
4763 reply->send_prefer = getULong(data.data);
4764 data_string_forget(&data, MDL);
98bd7ca0 4765 }
5279b8f3
DH
4766
4767 /* Note lowest values for later calculation of renew/rebind times. */
4768 if (reply->prefer > reply->send_prefer)
4769 reply->prefer = reply->send_prefer;
4770
4771 if (reply->valid > reply->send_valid)
4772 reply->valid = reply->send_valid;
4773
80c9fdb0 4774 /* Perform dynamic prefix related update work. */
9322442f 4775 if (reply->lease != NULL) {
1acab09f
FD
4776 /* Cached lifetimes */
4777 reply->lease->prefer = reply->send_prefer;
4778 reply->lease->valid = reply->send_valid;
4779
36c4a037
SR
4780 /* Advance (or rewind) the valid lifetime.
4781 * In the protocol 0xFFFFFFFF is infinite
4782 * when connecting to the lease file MAX_TIME is
4783 */
5d89d60f 4784 if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
36c4a037
SR
4785 if (reply->send_valid == 0xFFFFFFFF) {
4786 reply->lease->soft_lifetime_end_time = MAX_TIME;
4787 } else {
4788 reply->lease->soft_lifetime_end_time =
4789 cur_time + reply->send_valid;
4790 }
5d89d60f
FD
4791 /* Wait before renew! */
4792 }
5279b8f3 4793
1d17db44 4794 status = ia_add_iasubopt(reply->ia, reply->lease, MDL);
5279b8f3 4795 if (status != ISC_R_SUCCESS) {
80c9fdb0
FD
4796 log_fatal("reply_process_is_prefixed: Unable to "
4797 "attach prefix to new IA_PD: %s",
4798 isc_result_totext(status));
5279b8f3
DH
4799 }
4800
4801 /*
80c9fdb0 4802 * If this is a new prefix, make sure it is attached somewhere.
5279b8f3 4803 */
9322442f
FD
4804 if (reply->lease->ia == NULL) {
4805 ia_reference(&reply->lease->ia, reply->ia, MDL);
5279b8f3 4806 }
98bd7ca0 4807 }
5279b8f3 4808
80c9fdb0 4809 /* Bring a copy of the relevant options into the IA_PD scope. */
5279b8f3
DH
4810 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4811 reply->packet->options, reply->reply_ia,
a7341359 4812 scope, group, root_group, NULL);
5279b8f3 4813
01fa619f
SR
4814 /* Execute statements from class scopes. */
4815 for (i = reply->packet->class_count; i > 0; i--) {
4816 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4817 reply->packet->options,
4818 reply->reply_ia, scope,
4819 reply->packet->classes[i - 1]->group,
4820 group, NULL);
4821 }
b31fe1d5 4822
2267da84
DH
4823 /*
4824 * And bring in host record configuration, if any, but not to overlap
4825 * the previous group or its common enclosers.
4826 */
4827 if (reply->host != NULL)
4828 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
4829 reply->packet->options,
4830 reply->reply_ia, scope,
a7341359 4831 reply->host->group, group, NULL);
2267da84 4832
5279b8f3
DH
4833 cleanup:
4834 if (data.data != NULL)
4835 data_string_forget(&data, MDL);
4836
4837 if (status == ISC_R_SUCCESS)
1d9774ab 4838 reply->client_resources++;
5279b8f3
DH
4839
4840 return status;
4841}
4842
80c9fdb0 4843/* Simply send an IAPREFIX within the IA_PD scope as described. */
5279b8f3 4844static isc_result_t
80c9fdb0
FD
4845reply_process_send_prefix(struct reply_state *reply,
4846 struct iaddrcidrnet *pref) {
5279b8f3
DH
4847 isc_result_t status = ISC_R_SUCCESS;
4848 struct data_string data;
4849
4850 memset(&data, 0, sizeof(data));
4851
80c9fdb0
FD
4852 /* Now append the prefix. */
4853 data.len = IAPREFIX_OFFSET;
5279b8f3 4854 if (!buffer_allocate(&data.buffer, data.len, MDL)) {
80c9fdb0
FD
4855 log_error("reply_process_send_prefix: out of memory"
4856 "allocating new IAPREFIX buffer.");
5279b8f3
DH
4857 status = ISC_R_NOMEMORY;
4858 goto cleanup;
98bd7ca0 4859 }
5279b8f3
DH
4860 data.data = data.buffer->data;
4861
80c9fdb0
FD
4862 putULong(data.buffer->data, reply->send_prefer);
4863 putULong(data.buffer->data + 4, reply->send_valid);
4864 data.buffer->data[8] = pref->bits;
4865 memcpy(data.buffer->data + 9, pref->lo_addr.iabuf, 16);
5279b8f3 4866
bead14ea
DH
4867 if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
4868 data.buffer, data.buffer->data,
80c9fdb0
FD
4869 data.len, D6O_IAPREFIX, 0)) {
4870 log_error("reply_process_send_prefix: unable "
4871 "to save IAPREFIX option");
5279b8f3
DH
4872 status = ISC_R_FAILURE;
4873 goto cleanup;
4874 }
4875
9322442f 4876 reply->resources_included = ISC_TRUE;
9f1d5a2f 4877
5279b8f3
DH
4878 cleanup:
4879 if (data.data != NULL)
4880 data_string_forget(&data, MDL);
4881
4882 return status;
4883}
4884
80c9fdb0 4885/* Choose the better of two prefixes. */
1d17db44 4886static struct iasubopt *
80c9fdb0 4887prefix_compare(struct reply_state *reply,
1d17db44 4888 struct iasubopt *alpha, struct iasubopt *beta) {
5279b8f3
DH
4889 if (alpha == NULL)
4890 return beta;
4891 if (beta == NULL)
4892 return alpha;
4893
80c9fdb0
FD
4894 if (reply->preflen >= 0) {
4895 if ((alpha->plen == reply->preflen) &&
4896 (beta->plen != reply->preflen))
4897 return alpha;
4898 if ((beta->plen == reply->preflen) &&
4899 (alpha->plen != reply->preflen))
4900 return beta;
4901 }
4902
5279b8f3
DH
4903 switch(alpha->state) {
4904 case FTS_ACTIVE:
4905 switch(beta->state) {
4906 case FTS_ACTIVE:
80c9fdb0 4907 /* Choose the prefix with the longest lifetime (most
5279b8f3
DH
4908 * likely the most recently allocated).
4909 */
b31fe1d5 4910 if (alpha->hard_lifetime_end_time <
5d89d60f 4911 beta->hard_lifetime_end_time)
5279b8f3
DH
4912 return beta;
4913 else
4914 return alpha;
4915
4916 case FTS_EXPIRED:
4917 case FTS_ABANDONED:
4918 return alpha;
4919
4920 default:
4921 log_fatal("Impossible condition at %s:%d.", MDL);
4922 }
4923 break;
4924
4925 case FTS_EXPIRED:
4926 switch (beta->state) {
4927 case FTS_ACTIVE:
4928 return beta;
4929
4930 case FTS_EXPIRED:
80c9fdb0 4931 /* Choose the most recently expired prefix. */
5d89d60f
FD
4932 if (alpha->hard_lifetime_end_time <
4933 beta->hard_lifetime_end_time)
4934 return beta;
4935 else if ((alpha->hard_lifetime_end_time ==
4936 beta->hard_lifetime_end_time) &&
4937 (alpha->soft_lifetime_end_time <
4938 beta->soft_lifetime_end_time))
5279b8f3
DH
4939 return beta;
4940 else
4941 return alpha;
4942
4943 case FTS_ABANDONED:
4944 return alpha;
4945
4946 default:
4947 log_fatal("Impossible condition at %s:%d.", MDL);
4948 }
4949 break;
4950
4951 case FTS_ABANDONED:
4952 switch (beta->state) {
4953 case FTS_ACTIVE:
4954 case FTS_EXPIRED:
4955 return alpha;
4956
4957 case FTS_ABANDONED:
80c9fdb0 4958 /* Choose the prefix that was abandoned longest ago. */
5d89d60f
FD
4959 if (alpha->hard_lifetime_end_time <
4960 beta->hard_lifetime_end_time)
5279b8f3 4961 return alpha;
a07d99bb
TM
4962 else
4963 return beta;
5279b8f3
DH
4964
4965 default:
4966 log_fatal("Impossible condition at %s:%d.", MDL);
4967 }
4968 break;
4969
4970 default:
4971 log_fatal("Impossible condition at %s:%d.", MDL);
98bd7ca0 4972 }
5279b8f3
DH
4973
4974 log_fatal("Triple impossible condition at %s:%d.", MDL);
4975 return NULL;
98bd7ca0
DH
4976}
4977
4978/*
4979 * Solicit is how a client starts requesting addresses.
4980 *
b31fe1d5 4981 * If the client asks for rapid commit, and we support it, we will
98bd7ca0
DH
4982 * allocate the addresses and reply.
4983 *
4984 * Otherwise we will send an advertise message.
4985 */
4986
98bd7ca0
DH
4987static void
4988dhcpv6_solicit(struct data_string *reply_ret, struct packet *packet) {
4989 struct data_string client_id;
98bd7ca0 4990
b31fe1d5 4991 /*
98bd7ca0
DH
4992 * Validate our input.
4993 */
4994 if (!valid_client_msg(packet, &client_id)) {
4995 return;
4996 }
4997
4998 lease_to_client(reply_ret, packet, &client_id, NULL);
4999
5000 /*
5001 * Clean up.
5002 */
5003 data_string_forget(&client_id, MDL);
5004}
5005
5006/*
5007 * Request is how a client actually requests addresses.
5008 *
5009 * Very similar to Solicit handling, except the server DUID is required.
5010 */
5011
98bd7ca0
DH
5012static void
5013dhcpv6_request(struct data_string *reply_ret, struct packet *packet) {
5014 struct data_string client_id;
5015 struct data_string server_id;
5016
5017 /*
5018 * Validate our input.
5019 */
5020 if (!valid_client_resp(packet, &client_id, &server_id)) {
5021 return;
5022 }
5023
b31fe1d5
TM
5024 /* If the REQUEST arrived via unicast and unicast option isn't set,
5025 * reject it per RFC 3315, Sec 18.2.1 */
5026 if (packet->unicast == ISC_TRUE &&
5027 is_unicast_option_defined(packet) == ISC_FALSE) {
5028 unicast_reject(reply_ret, packet, &client_id, &server_id);
5029 } else {
5030 /*
5031 * Issue our lease.
5032 */
5033 lease_to_client(reply_ret, packet, &client_id, &server_id);
5034 }
98bd7ca0
DH
5035
5036 /*
5037 * Cleanup.
5038 */
5039 data_string_forget(&client_id, MDL);
5040 data_string_forget(&server_id, MDL);
5041}
5042
8eab95f2
DH
5043/* Find a DHCPv6 packet's shared network from hints in the packet.
5044 */
bd72740e 5045static isc_result_t
8eab95f2
DH
5046shared_network_from_packet6(struct shared_network **shared,
5047 struct packet *packet)
5048{
5049 const struct packet *chk_packet;
5050 const struct in6_addr *link_addr, *first_link_addr;
5051 struct iaddr tmp_addr;
5052 struct subnet *subnet;
bd72740e 5053 isc_result_t status;
8eab95f2 5054
bd72740e 5055 if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
98bf1607 5056 return DHCP_R_INVALIDARG;
8eab95f2
DH
5057
5058 /*
5059 * First, find the link address where the packet from the client
5060 * first appeared (if this packet was relayed).
5061 */
5062 first_link_addr = NULL;
5063 chk_packet = packet->dhcpv6_container_packet;
5064 while (chk_packet != NULL) {
5065 link_addr = &chk_packet->dhcpv6_link_address;
5066 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
5067 !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
5068 first_link_addr = link_addr;
b445a411 5069 break;
8eab95f2
DH
5070 }
5071 chk_packet = chk_packet->dhcpv6_container_packet;
5072 }
5073
5074 /*
5075 * If there is a relayed link address, find the subnet associated
5076 * with that, and use that to get the appropriate
5077 * shared_network.
5078 */
5079 if (first_link_addr != NULL) {
5080 tmp_addr.len = sizeof(*first_link_addr);
5081 memcpy(tmp_addr.iabuf,
5082 first_link_addr, sizeof(*first_link_addr));
5083 subnet = NULL;
5084 if (!find_subnet(&subnet, tmp_addr, MDL)) {
5085 log_debug("No subnet found for link-address %s.",
5086 piaddr(tmp_addr));
bd72740e 5087 return ISC_R_NOTFOUND;
8eab95f2 5088 }
bd72740e
FD
5089 status = shared_network_reference(shared,
5090 subnet->shared_network, MDL);
8eab95f2
DH
5091 subnet_dereference(&subnet, MDL);
5092
5093 /*
5094 * If there is no link address, we will use the interface
5095 * that this packet came in on to pick the shared_network.
5096 */
4dc5a6b1 5097 } else if (packet->interface != NULL) {
bd72740e 5098 status = shared_network_reference(shared,
8eab95f2
DH
5099 packet->interface->shared_network,
5100 MDL);
4dc5a6b1
SR
5101 if (packet->dhcpv6_container_packet != NULL) {
5102 log_info("[L2 Relay] No link address in relay packet "
5103 "assuming L2 relay and using receiving "
5104 "interface");
5105 }
5106
5107 } else {
5108 /*
5109 * We shouldn't be able to get here but if there is no link
5110 * address and no interface we don't know where to get the
5111 * pool from log an error and return an error.
5112 */
b31fe1d5 5113 log_error("No interface and no link address "
4dc5a6b1
SR
5114 "can't determine pool");
5115 status = DHCP_R_INVALIDARG;
8eab95f2 5116 }
bd72740e
FD
5117
5118 return status;
8eab95f2
DH
5119}
5120
98bd7ca0 5121/*
b31fe1d5 5122 * When a client thinks it might be on a new link, it sends a
98bd7ca0 5123 * Confirm message.
8eab95f2
DH
5124 *
5125 * From RFC3315 section 18.2.2:
5126 *
5127 * When the server receives a Confirm message, the server determines
5128 * whether the addresses in the Confirm message are appropriate for the
5129 * link to which the client is attached. If all of the addresses in the
5130 * Confirm message pass this test, the server returns a status of
5131 * Success. If any of the addresses do not pass this test, the server
5132 * returns a status of NotOnLink. If the server is unable to perform
5133 * this test (for example, the server does not have information about
5134 * prefixes on the link to which the client is connected), or there were
5135 * no addresses in any of the IAs sent by the client, the server MUST
5136 * NOT send a reply to the client.
98bd7ca0
DH
5137 */
5138
98bd7ca0
DH
5139static void
5140dhcpv6_confirm(struct data_string *reply_ret, struct packet *packet) {
8eab95f2
DH
5141 struct shared_network *shared;
5142 struct subnet *subnet;
5143 struct option_cache *ia, *ta, *oc;
5144 struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
5145 struct option_state *cli_enc_opt_state, *opt_state;
5146 struct iaddr cli_addr;
5147 int pass;
5148 isc_boolean_t inappropriate, has_addrs;
98bd7ca0
DH
5149 char reply_data[65536];
5150 struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
a3528574 5151 int reply_ofs = (int)(offsetof(struct dhcpv6_packet, options));
98bd7ca0 5152
b31fe1d5 5153 /*
8eab95f2 5154 * Basic client message validation.
98bd7ca0 5155 */
8eab95f2 5156 memset(&client_id, 0, sizeof(client_id));
98bd7ca0
DH
5157 if (!valid_client_msg(packet, &client_id)) {
5158 return;
5159 }
5160
80c9fdb0
FD
5161 /*
5162 * Do not process Confirms that do not have IA's we do not recognize.
8eab95f2
DH
5163 */
5164 ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
5165 ta = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
5166 if ((ia == NULL) && (ta == NULL))
5167 return;
5168
80c9fdb0
FD
5169 /*
5170 * IA_PD's are simply ignored.
5171 */
5172 delete_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
5173
b31fe1d5 5174 /*
98bd7ca0
DH
5175 * Bit of variable initialization.
5176 */
8eab95f2
DH
5177 opt_state = cli_enc_opt_state = NULL;
5178 memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
98bd7ca0 5179 memset(&iaaddr, 0, sizeof(iaaddr));
98bd7ca0
DH
5180 memset(&packet_oro, 0, sizeof(packet_oro));
5181
8eab95f2
DH
5182 /* Determine what shared network the client is connected to. We
5183 * must not respond if we don't have any information about the
5184 * network the client is on.
98bd7ca0 5185 */
8eab95f2 5186 shared = NULL;
bd72740e
FD
5187 if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
5188 (shared == NULL))
98bd7ca0 5189 goto exit;
98bd7ca0 5190
8eab95f2
DH
5191 /* If there are no recorded subnets, then we have no
5192 * information about this subnet - ignore Confirms.
98bd7ca0 5193 */
8eab95f2
DH
5194 subnet = shared->subnets;
5195 if (subnet == NULL)
5196 goto exit;
98bd7ca0 5197
8eab95f2
DH
5198 /* Are the addresses in all the IA's appropriate for that link? */
5199 has_addrs = inappropriate = ISC_FALSE;
5200 pass = D6O_IA_NA;
5201 while(!inappropriate) {
5202 /* If we've reached the end of the IA_NA pass, move to the
5203 * IA_TA pass.
5204 */
5205 if ((pass == D6O_IA_NA) && (ia == NULL)) {
5206 pass = D6O_IA_TA;
5207 ia = ta;
98bd7ca0
DH
5208 }
5209
8eab95f2
DH
5210 /* If we've reached the end of all passes, we're done. */
5211 if (ia == NULL)
5212 break;
98bd7ca0 5213
8eab95f2
DH
5214 if (((pass == D6O_IA_NA) &&
5215 !get_encapsulated_IA_state(&cli_enc_opt_state,
5216 &cli_enc_opt_data,
5217 packet, ia, IA_NA_OFFSET)) ||
5218 ((pass == D6O_IA_TA) &&
5219 !get_encapsulated_IA_state(&cli_enc_opt_state,
5220 &cli_enc_opt_data,
5221 packet, ia, IA_TA_OFFSET))) {
98bd7ca0
DH
5222 goto exit;
5223 }
5224
8eab95f2
DH
5225 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
5226 D6O_IAADDR);
98bd7ca0 5227
8eab95f2
DH
5228 for ( ; oc != NULL ; oc = oc->next) {
5229 if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL,
5230 packet->options, NULL,
5231 &global_scope, oc, MDL) ||
5279b8f3 5232 (iaaddr.len < IAADDR_OFFSET)) {
8eab95f2
DH
5233 log_error("dhcpv6_confirm: "
5234 "error evaluating IAADDR.");
98bd7ca0
DH
5235 goto exit;
5236 }
8eab95f2
DH
5237
5238 /* Copy out the IPv6 address for processing. */
5239 cli_addr.len = 16;
5240 memcpy(cli_addr.iabuf, iaaddr.data, 16);
5241
5279b8f3
DH
5242 data_string_forget(&iaaddr, MDL);
5243
8eab95f2
DH
5244 /* Record that we've processed at least one address. */
5245 has_addrs = ISC_TRUE;
5246
5247 /* Find out if any subnets cover this address. */
5248 for (subnet = shared->subnets ; subnet != NULL ;
5249 subnet = subnet->next_sibling) {
5250 if (addr_eq(subnet_number(cli_addr,
5251 subnet->netmask),
5252 subnet->net))
5253 break;
5254 }
5255
8eab95f2
DH
5256 /* If we reach the end of the subnet list, and no
5257 * subnet matches the client address, then it must
5258 * be inappropriate to the link (so far as our
5259 * configuration says). Once we've found one
5260 * inappropriate address, there is no reason to
5261 * continue searching.
5262 */
5263 if (subnet == NULL) {
5264 inappropriate = ISC_TRUE;
98bd7ca0
DH
5265 break;
5266 }
5279b8f3 5267 }
98bd7ca0 5268
8eab95f2
DH
5269 option_state_dereference(&cli_enc_opt_state, MDL);
5270 data_string_forget(&cli_enc_opt_data, MDL);
98bd7ca0 5271
8eab95f2
DH
5272 /* Advance to the next IA_*. */
5273 ia = ia->next;
98bd7ca0
DH
5274 }
5275
8eab95f2
DH
5276 /* If the client supplied no addresses, do not reply. */
5277 if (!has_addrs)
5278 goto exit;
5279
b31fe1d5 5280 /*
8eab95f2 5281 * Set up reply.
98bd7ca0 5282 */
8eab95f2 5283 if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
98bd7ca0
DH
5284 goto exit;
5285 }
5286
b31fe1d5 5287 /*
98bd7ca0
DH
5288 * Set our status.
5289 */
8eab95f2 5290 if (inappropriate) {
b31fe1d5 5291 if (!set_status_code(STATUS_NotOnLink,
98bd7ca0
DH
5292 "Some of the addresses are not on link.",
5293 opt_state)) {
5294 goto exit;
5295 }
5296 } else {
b31fe1d5 5297 if (!set_status_code(STATUS_Success,
98bd7ca0
DH
5298 "All addresses still on link.",
5299 opt_state)) {
5300 goto exit;
5301 }
5302 }
5303
b31fe1d5 5304 /*
98bd7ca0
DH
5305 * Only one option: add it.
5306 */
5307 reply_ofs += store_options6(reply_data+reply_ofs,
b31fe1d5 5308 sizeof(reply_data)-reply_ofs,
98bd7ca0
DH
5309 opt_state, packet,
5310 required_opts, &packet_oro);
5311
b31fe1d5 5312 /*
98bd7ca0
DH
5313 * Return our reply to the caller.
5314 */
5315 reply_ret->len = reply_ofs;
5316 reply_ret->buffer = NULL;
5317 if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
5318 log_fatal("No memory to store reply.");
5319 }
5320 reply_ret->data = reply_ret->buffer->data;
5321 memcpy(reply_ret->buffer->data, reply, reply_ofs);
5322
5323exit:
8eab95f2
DH
5324 /* Cleanup any stale data strings. */
5325 if (cli_enc_opt_data.buffer != NULL)
5326 data_string_forget(&cli_enc_opt_data, MDL);
5327 if (iaaddr.buffer != NULL)
98bd7ca0 5328 data_string_forget(&iaaddr, MDL);
8eab95f2
DH
5329 if (client_id.buffer != NULL)
5330 data_string_forget(&client_id, MDL);
5331 if (packet_oro.buffer != NULL)
5332 data_string_forget(&packet_oro, MDL);
5333
5334 /* Release any stale option states. */
5335 if (cli_enc_opt_state != NULL)
5336 option_state_dereference(&cli_enc_opt_state, MDL);
5337 if (opt_state != NULL)
5338 option_state_dereference(&opt_state, MDL);
98bd7ca0
DH
5339}
5340
5341/*
80c9fdb0 5342 * Renew is when a client wants to extend its lease/prefix, at time T1.
98bd7ca0 5343 *
80c9fdb0
FD
5344 * We handle this the same as if the client wants a new lease/prefix,
5345 * except for the error code of when addresses don't match.
98bd7ca0
DH
5346 */
5347
98bd7ca0
DH
5348static void
5349dhcpv6_renew(struct data_string *reply, struct packet *packet) {
5350 struct data_string client_id;
5351 struct data_string server_id;
5352
b31fe1d5 5353 /*
98bd7ca0
DH
5354 * Validate the request.
5355 */
5356 if (!valid_client_resp(packet, &client_id, &server_id)) {
5357 return;
5358 }
5359
b31fe1d5
TM
5360 /* If the RENEW arrived via unicast and unicast option isn't set,
5361 * reject it per RFC 3315, Sec 18.2.3 */
5362 if (packet->unicast == ISC_TRUE &&
5363 is_unicast_option_defined(packet) == ISC_FALSE) {
5364 unicast_reject(reply, packet, &client_id, &server_id);
5365 } else {
5366 /*
5367 * Renew our lease.
5368 */
5369 lease_to_client(reply, packet, &client_id, &server_id);
5370 }
98bd7ca0
DH
5371
5372 /*
5373 * Cleanup.
5374 */
5375 data_string_forget(&server_id, MDL);
5376 data_string_forget(&client_id, MDL);
5377}
5378
5379/*
5380 * Rebind is when a client wants to extend its lease, at time T2.
5381 *
5382 * We handle this the same as if the client wants a new lease, except
5383 * for the error code of when addresses don't match.
5384 */
5385
98bd7ca0
DH
5386static void
5387dhcpv6_rebind(struct data_string *reply, struct packet *packet) {
5388 struct data_string client_id;
5389
5390 if (!valid_client_msg(packet, &client_id)) {
5391 return;
5392 }
5393
5279b8f3 5394 lease_to_client(reply, packet, &client_id, NULL);
98bd7ca0
DH
5395
5396 data_string_forget(&client_id, MDL);
5397}
5398
5399static void
5400ia_na_match_decline(const struct data_string *client_id,
5401 const struct data_string *iaaddr,
1d17db44 5402 struct iasubopt *lease)
c382bc98 5403{
98bd7ca0
DH
5404 char tmp_addr[INET6_ADDRSTRLEN];
5405
5406 log_error("Client %s reports address %s is "
5407 "already in use by another host!",
5408 print_hex_1(client_id->len, client_id->data, 60),
b31fe1d5 5409 inet_ntop(AF_INET6, iaaddr->data,
98bd7ca0
DH
5410 tmp_addr, sizeof(tmp_addr)));
5411 if (lease != NULL) {
5412 decline_lease6(lease->ipv6_pool, lease);
1acab09f 5413 lease->ia->cltt = cur_time;
9322442f 5414 write_ia(lease->ia);
98bd7ca0
DH
5415 }
5416}
5417
5418static void
5419ia_na_nomatch_decline(const struct data_string *client_id,
5420 const struct data_string *iaaddr,
5421 u_int32_t *ia_na_id,
5422 struct packet *packet,
5423 char *reply_data,
5424 int *reply_ofs,
c382bc98
SK
5425 int reply_len)
5426{
98bd7ca0
DH
5427 char tmp_addr[INET6_ADDRSTRLEN];
5428 struct option_state *host_opt_state;
5429 int len;
5430
5431 log_info("Client %s declines address %s, which is not offered to it.",
5432 print_hex_1(client_id->len, client_id->data, 60),
5433 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
5434
5435 /*
5436 * Create state for this IA_NA.
5437 */
5438 host_opt_state = NULL;
5439 if (!option_state_allocate(&host_opt_state, MDL)) {
5440 log_error("ia_na_nomatch_decline: out of memory "
5441 "allocating option_state.");
5442 goto exit;
5443 }
5444
5445 if (!set_status_code(STATUS_NoBinding, "Decline for unknown address.",
5446 host_opt_state)) {
5447 goto exit;
5448 }
5449
5450 /*
5451 * Insure we have enough space
5452 */
5453 if (reply_len < (*reply_ofs + 16)) {
5454 log_error("ia_na_nomatch_decline: "
5455 "out of space for reply packet.");
5456 goto exit;
5457 }
5458
5459 /*
5460 * Put our status code into the reply packet.
5461 */
5462 len = store_options6(reply_data+(*reply_ofs)+16,
5463 reply_len-(*reply_ofs)-16,
5464 host_opt_state, packet,
5465 required_opts_STATUS_CODE, NULL);
5466
5467 /*
b31fe1d5
TM
5468 * Store the non-encapsulated option data for this
5469 * IA_NA into our reply packet. Defined in RFC 3315,
5470 * section 22.4.
98bd7ca0
DH
5471 */
5472 /* option number */
28868515 5473 putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
98bd7ca0 5474 /* option length */
28868515 5475 putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
98bd7ca0
DH
5476 /* IA_NA, copied from the client */
5477 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5478 /* t1 and t2, odd that we need them, but here it is */
28868515
SK
5479 putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
5480 putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
98bd7ca0
DH
5481
5482 /*
5483 * Get ready for next IA_NA.
5484 */
5485 *reply_ofs += (len + 16);
5486
5487exit:
5488 option_state_dereference(&host_opt_state, MDL);
5489}
5490
5491static void
b31fe1d5 5492iterate_over_ia_na(struct data_string *reply_ret,
98bd7ca0
DH
5493 struct packet *packet,
5494 const struct data_string *client_id,
5495 const struct data_string *server_id,
06eb8bab 5496 const char *packet_type,
98bd7ca0 5497 void (*ia_na_match)(),
c382bc98
SK
5498 void (*ia_na_nomatch)())
5499{
98bd7ca0
DH
5500 struct option_state *opt_state;
5501 struct host_decl *packet_host;
5502 struct option_cache *ia;
5503 struct option_cache *oc;
5504 /* cli_enc_... variables come from the IA_NA/IA_TA options */
5505 struct data_string cli_enc_opt_data;
5506 struct option_state *cli_enc_opt_state;
5507 struct host_decl *host;
5508 struct option_state *host_opt_state;
98bd7ca0
DH
5509 struct data_string iaaddr;
5510 struct data_string fixed_addr;
98bd7ca0
DH
5511 char reply_data[65536];
5512 struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
a3528574 5513 int reply_ofs = (int)(offsetof(struct dhcpv6_packet, options));
98bd7ca0 5514 char status_msg[32];
1d17db44 5515 struct iasubopt *lease;
9322442f 5516 struct ia_xx *existing_ia_na;
98bd7ca0
DH
5517 int i;
5518 struct data_string key;
5519 u_int32_t iaid;
5520
5521 /*
5522 * Initialize to empty values, in case we have to exit early.
5523 */
5524 opt_state = NULL;
5525 memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
5526 cli_enc_opt_state = NULL;
5527 memset(&iaaddr, 0, sizeof(iaaddr));
5528 memset(&fixed_addr, 0, sizeof(fixed_addr));
5529 host_opt_state = NULL;
5530 lease = NULL;
5531
b31fe1d5 5532 /*
98bd7ca0
DH
5533 * Find the host record that matches from the packet, if any.
5534 */
5535 packet_host = NULL;
62a9eb91 5536 find_hosts6(&packet_host, packet, client_id, MDL);
98bd7ca0 5537
b31fe1d5 5538 /*
98bd7ca0
DH
5539 * Set our reply information.
5540 */
5541 reply->msg_type = DHCPV6_REPLY;
b31fe1d5 5542 memcpy(reply->transaction_id, packet->dhcpv6_transaction_id,
98bd7ca0
DH
5543 sizeof(reply->transaction_id));
5544
5545 /*
5546 * Build our option state for reply.
5547 */
5548 opt_state = NULL;
5549 if (!option_state_allocate(&opt_state, MDL)) {
5550 log_error("iterate_over_ia_na: no memory for option_state.");
5551 goto exit;
5552 }
b31fe1d5
TM
5553 execute_statements_in_scope(NULL, packet, NULL, NULL,
5554 packet->options, opt_state,
a7341359 5555 &global_scope, root_group, NULL, NULL);
98bd7ca0 5556
b31fe1d5 5557 /*
98bd7ca0
DH
5558 * RFC 3315, section 18.2.7 tells us which options to include.
5559 */
5560 oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
5561 if (oc == NULL) {
b31fe1d5
TM
5562 if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
5563 (unsigned char *)server_duid.data,
98bd7ca0
DH
5564 server_duid.len, D6O_SERVERID, 0)) {
5565 log_error("iterate_over_ia_na: "
5566 "error saving server identifier.");
5567 goto exit;
5568 }
5569 }
5570
b31fe1d5
TM
5571 if (!save_option_buffer(&dhcpv6_universe, opt_state,
5572 client_id->buffer,
98bd7ca0 5573 (unsigned char *)client_id->data,
b31fe1d5 5574 client_id->len,
98bd7ca0
DH
5575 D6O_CLIENTID, 0)) {
5576 log_error("iterate_over_ia_na: "
5577 "error saving client identifier.");
5578 goto exit;
5579 }
5580
5581 snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type);
5582 if (!set_status_code(STATUS_Success, status_msg, opt_state)) {
5583 goto exit;
5584 }
5585
b31fe1d5
TM
5586 /*
5587 * Add our options that are not associated with any IA_NA or IA_TA.
98bd7ca0
DH
5588 */
5589 reply_ofs += store_options6(reply_data+reply_ofs,
b31fe1d5 5590 sizeof(reply_data)-reply_ofs,
98bd7ca0
DH
5591 opt_state, packet,
5592 required_opts, NULL);
5593
5594 /*
5595 * Loop through the IA_NA reported by the client, and deal with
5596 * addresses reported as already in use.
5597 */
5598 for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
5599 ia != NULL; ia = ia->next) {
98bd7ca0
DH
5600
5601 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5602 &cli_enc_opt_data,
8eab95f2 5603 packet, ia, IA_NA_OFFSET)) {
98bd7ca0
DH
5604 goto exit;
5605 }
5606
5607 iaid = getULong(cli_enc_opt_data.data);
5608
b31fe1d5 5609 /*
98bd7ca0 5610 * XXX: It is possible that we can get multiple addresses
b31fe1d5
TM
5611 * sent by the client. We don't send multiple
5612 * addresses, so this indicates a client error.
98bd7ca0
DH
5613 * We should check for multiple IAADDR options, log
5614 * if found, and set as an error.
5615 */
b31fe1d5 5616 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
98bd7ca0
DH
5617 D6O_IAADDR);
5618 if (oc == NULL) {
5619 /* no address given for this IA, ignore */
5620 option_state_dereference(&cli_enc_opt_state, MDL);
5621 data_string_forget(&cli_enc_opt_data, MDL);
5622 continue;
5623 }
5624
5625 memset(&iaaddr, 0, sizeof(iaaddr));
b31fe1d5 5626 if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL,
98bd7ca0
DH
5627 packet->options, NULL,
5628 &global_scope, oc, MDL)) {
5629 log_error("iterate_over_ia_na: "
5630 "error evaluating IAADDR.");
5631 goto exit;
5632 }
5633
b31fe1d5 5634 /*
98bd7ca0 5635 * Now we need to figure out which host record matches
c900c5b2
DH
5636 * this IA_NA and IAADDR (encapsulated option contents
5637 * matching a host record by option).
98bd7ca0
DH
5638 *
5639 * XXX: We don't currently track IA_NA separately, but
5640 * we will need to do this!
5641 */
5642 host = NULL;
b31fe1d5
TM
5643 if (!find_hosts_by_option(&host, packet,
5644 cli_enc_opt_state, MDL)) {
98bd7ca0
DH
5645 if (packet_host != NULL) {
5646 host = packet_host;
5647 } else {
5648 host = NULL;
5649 }
5650 }
5651 while (host != NULL) {
5652 if (host->fixed_addr != NULL) {
b31fe1d5
TM
5653 if (!evaluate_option_cache(&fixed_addr, NULL,
5654 NULL, NULL, NULL,
98bd7ca0 5655 NULL, &global_scope,
b31fe1d5 5656 host->fixed_addr,
98bd7ca0
DH
5657 MDL)) {
5658 log_error("iterate_over_ia_na: error "
5659 "evaluating host address.");
5660 goto exit;
5661 }
5662 if ((iaaddr.len >= 16) &&
5663 !memcmp(fixed_addr.data, iaaddr.data, 16)) {
5664 data_string_forget(&fixed_addr, MDL);
5665 break;
5666 }
5667 data_string_forget(&fixed_addr, MDL);
5668 }
5669 host = host->n_ipaddr;
5670 }
5671
5279b8f3 5672 if ((host == NULL) && (iaaddr.len >= IAADDR_OFFSET)) {
98bd7ca0
DH
5673 /*
5674 * Find existing IA_NA.
5675 */
b31fe1d5 5676 if (ia_make_key(&key, iaid,
1d9774ab 5677 (char *)client_id->data,
b31fe1d5 5678 client_id->len,
1d9774ab 5679 MDL) != ISC_R_SUCCESS) {
98bd7ca0
DH
5680 log_fatal("iterate_over_ia_na: no memory for "
5681 "key.");
5682 }
5683
5684 existing_ia_na = NULL;
b31fe1d5
TM
5685 if (ia_hash_lookup(&existing_ia_na, ia_na_active,
5686 (unsigned char *)key.data,
9322442f 5687 key.len, MDL)) {
b31fe1d5 5688 /*
98bd7ca0
DH
5689 * Make sure this address is in the IA_NA.
5690 */
1d17db44
FD
5691 for (i=0; i<existing_ia_na->num_iasubopt; i++) {
5692 struct iasubopt *tmp;
98bd7ca0
DH
5693 struct in6_addr *in6_addr;
5694
1d17db44 5695 tmp = existing_ia_na->iasubopt[i];
98bd7ca0 5696 in6_addr = &tmp->addr;
b31fe1d5 5697 if (memcmp(in6_addr,
98bd7ca0 5698 iaaddr.data, 16) == 0) {
1d17db44
FD
5699 iasubopt_reference(&lease,
5700 tmp, MDL);
98bd7ca0 5701 break;
5279b8f3 5702 }
98bd7ca0
DH
5703 }
5704 }
5705
5706 data_string_forget(&key, MDL);
5707 }
5708
5709 if ((host != NULL) || (lease != NULL)) {
5710 ia_na_match(client_id, &iaaddr, lease);
5711 } else {
b31fe1d5
TM
5712 ia_na_nomatch(client_id, &iaaddr,
5713 (u_int32_t *)cli_enc_opt_data.data,
5714 packet, reply_data, &reply_ofs,
98bd7ca0
DH
5715 sizeof(reply_data));
5716 }
5717
5718 if (lease != NULL) {
1d17db44 5719 iasubopt_dereference(&lease, MDL);
98bd7ca0
DH
5720 }
5721
5722 data_string_forget(&iaaddr, MDL);
5723 option_state_dereference(&cli_enc_opt_state, MDL);
5724 data_string_forget(&cli_enc_opt_data, MDL);
5725 }
5726
b31fe1d5 5727 /*
98bd7ca0
DH
5728 * Return our reply to the caller.
5729 */
5730 reply_ret->len = reply_ofs;
5731 reply_ret->buffer = NULL;
5732 if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
5733 log_fatal("No memory to store reply.");
5734 }
5735 reply_ret->data = reply_ret->buffer->data;
5736 memcpy(reply_ret->buffer->data, reply, reply_ofs);
5737
5738exit:
5739 if (lease != NULL) {
1d17db44 5740 iasubopt_dereference(&lease, MDL);
98bd7ca0
DH
5741 }
5742 if (host_opt_state != NULL) {
5743 option_state_dereference(&host_opt_state, MDL);
5744 }
5745 if (fixed_addr.buffer != NULL) {
5746 data_string_forget(&fixed_addr, MDL);
5747 }
5748 if (iaaddr.buffer != NULL) {
5749 data_string_forget(&iaaddr, MDL);
5750 }
5751 if (cli_enc_opt_state != NULL) {
5752 option_state_dereference(&cli_enc_opt_state, MDL);
5753 }
5754 if (cli_enc_opt_data.buffer != NULL) {
5755 data_string_forget(&cli_enc_opt_data, MDL);
5756 }
5757 if (opt_state != NULL) {
5758 option_state_dereference(&opt_state, MDL);
5759 }
5760}
5761
5762/*
5763 * Decline means a client has detected that something else is using an
5764 * address we gave it.
5765 *
5766 * Since we're only dealing with fixed leases for now, there's not
20ae1aff 5767 * much we can do, other that log the occurrence.
b31fe1d5 5768 *
98bd7ca0
DH
5769 * When we start issuing addresses from pools, then we will have to
5770 * record our declined addresses and issue another. In general with
5771 * IPv6 there is no worry about DoS by clients exhausting space, but
5772 * we still need to be aware of this possibility.
5773 */
5774
98bd7ca0
DH
5775/* TODO: IA_TA */
5776static void
5777dhcpv6_decline(struct data_string *reply, struct packet *packet) {
5778 struct data_string client_id;
5779 struct data_string server_id;
5780
b31fe1d5 5781 /*
98bd7ca0
DH
5782 * Validate our input.
5783 */
5784 if (!valid_client_resp(packet, &client_id, &server_id)) {
5785 return;
5786 }
5787
b31fe1d5
TM
5788 /* If the DECLINE arrived via unicast and unicast option isn't set,
5789 * reject it per RFC 3315, Sec 18.2.7 */
5790 if (packet->unicast == ISC_TRUE &&
5791 is_unicast_option_defined(packet) == ISC_FALSE) {
5792 unicast_reject(reply, packet, &client_id, &server_id);
5793 } else {
5794 /*
5795 * Undefined for IA_PD.
5796 */
5797 delete_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
80c9fdb0 5798
b31fe1d5
TM
5799 /*
5800 * And operate on each IA_NA in this packet.
5801 */
5802 iterate_over_ia_na(reply, packet, &client_id, &server_id,
5803 "Decline", ia_na_match_decline,
5804 ia_na_nomatch_decline);
5805
5806 }
80c9fdb0
FD
5807
5808 data_string_forget(&server_id, MDL);
5809 data_string_forget(&client_id, MDL);
98bd7ca0
DH
5810}
5811
5812static void
5813ia_na_match_release(const struct data_string *client_id,
5814 const struct data_string *iaaddr,
1d17db44 5815 struct iasubopt *lease)
c382bc98 5816{
98bd7ca0
DH
5817 char tmp_addr[INET6_ADDRSTRLEN];
5818
5819 log_info("Client %s releases address %s",
5820 print_hex_1(client_id->len, client_id->data, 60),
5821 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
5822 if (lease != NULL) {
5823 release_lease6(lease->ipv6_pool, lease);
1acab09f 5824 lease->ia->cltt = cur_time;
9322442f 5825 write_ia(lease->ia);
98bd7ca0
DH
5826 }
5827}
5828
5829static void
5830ia_na_nomatch_release(const struct data_string *client_id,
5831 const struct data_string *iaaddr,
5832 u_int32_t *ia_na_id,
5833 struct packet *packet,
5834 char *reply_data,
5835 int *reply_ofs,
c382bc98
SK
5836 int reply_len)
5837{
98bd7ca0
DH
5838 char tmp_addr[INET6_ADDRSTRLEN];
5839 struct option_state *host_opt_state;
5840 int len;
5841
5842 log_info("Client %s releases address %s, which is not leased to it.",
5843 print_hex_1(client_id->len, client_id->data, 60),
5844 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
5845
5846 /*
5847 * Create state for this IA_NA.
5848 */
5849 host_opt_state = NULL;
5850 if (!option_state_allocate(&host_opt_state, MDL)) {
c382bc98 5851 log_error("ia_na_nomatch_release: out of memory "
98bd7ca0
DH
5852 "allocating option_state.");
5853 goto exit;
5854 }
5855
b31fe1d5 5856 if (!set_status_code(STATUS_NoBinding,
98bd7ca0
DH
5857 "Release for non-leased address.",
5858 host_opt_state)) {
5859 goto exit;
5860 }
5861
5862 /*
5863 * Insure we have enough space
5864 */
5865 if (reply_len < (*reply_ofs + 16)) {
c382bc98 5866 log_error("ia_na_nomatch_release: "
98bd7ca0
DH
5867 "out of space for reply packet.");
5868 goto exit;
5869 }
5870
5871 /*
5872 * Put our status code into the reply packet.
5873 */
5874 len = store_options6(reply_data+(*reply_ofs)+16,
5875 reply_len-(*reply_ofs)-16,
5876 host_opt_state, packet,
5877 required_opts_STATUS_CODE, NULL);
5878
5879 /*
b31fe1d5
TM
5880 * Store the non-encapsulated option data for this
5881 * IA_NA into our reply packet. Defined in RFC 3315,
5882 * section 22.4.
98bd7ca0
DH
5883 */
5884 /* option number */
28868515 5885 putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
98bd7ca0 5886 /* option length */
28868515 5887 putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
98bd7ca0
DH
5888 /* IA_NA, copied from the client */
5889 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5890 /* t1 and t2, odd that we need them, but here it is */
28868515
SK
5891 putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
5892 putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
98bd7ca0
DH
5893
5894 /*
5895 * Get ready for next IA_NA.
5896 */
5897 *reply_ofs += (len + 16);
5898
5899exit:
5900 option_state_dereference(&host_opt_state, MDL);
5901}
5902
80c9fdb0
FD
5903static void
5904ia_pd_match_release(const struct data_string *client_id,
5905 const struct data_string *iapref,
1d17db44 5906 struct iasubopt *prefix)
80c9fdb0
FD
5907{
5908 char tmp_addr[INET6_ADDRSTRLEN];
5909
5910 log_info("Client %s releases prefix %s/%u",
5911 print_hex_1(client_id->len, client_id->data, 60),
5912 inet_ntop(AF_INET6, iapref->data + 9,
5913 tmp_addr, sizeof(tmp_addr)),
5914 (unsigned) getUChar(iapref->data + 8));
5915 if (prefix != NULL) {
9322442f 5916 release_lease6(prefix->ipv6_pool, prefix);
1acab09f 5917 prefix->ia->cltt = cur_time;
9322442f 5918 write_ia(prefix->ia);
80c9fdb0
FD
5919 }
5920}
5921
5922static void
5923ia_pd_nomatch_release(const struct data_string *client_id,
5924 const struct data_string *iapref,
5925 u_int32_t *ia_pd_id,
5926 struct packet *packet,
5927 char *reply_data,
5928 int *reply_ofs,
5929 int reply_len)
5930{
5931 char tmp_addr[INET6_ADDRSTRLEN];
5932 struct option_state *host_opt_state;
5933 int len;
5934
5935 log_info("Client %s releases prefix %s/%u, which is not leased to it.",
5936 print_hex_1(client_id->len, client_id->data, 60),
5937 inet_ntop(AF_INET6, iapref->data + 9,
5938 tmp_addr, sizeof(tmp_addr)),
5939 (unsigned) getUChar(iapref->data + 8));
5940
5941 /*
5942 * Create state for this IA_PD.
5943 */
5944 host_opt_state = NULL;
5945 if (!option_state_allocate(&host_opt_state, MDL)) {
5946 log_error("ia_pd_nomatch_release: out of memory "
5947 "allocating option_state.");
5948 goto exit;
5949 }
5950
b31fe1d5 5951 if (!set_status_code(STATUS_NoBinding,
80c9fdb0
FD
5952 "Release for non-leased prefix.",
5953 host_opt_state)) {
5954 goto exit;
5955 }
5956
5957 /*
5958 * Insure we have enough space
5959 */
5960 if (reply_len < (*reply_ofs + 16)) {
5961 log_error("ia_pd_nomatch_release: "
5962 "out of space for reply packet.");
5963 goto exit;
5964 }
5965
5966 /*
5967 * Put our status code into the reply packet.
5968 */
5969 len = store_options6(reply_data+(*reply_ofs)+16,
5970 reply_len-(*reply_ofs)-16,
5971 host_opt_state, packet,
5972 required_opts_STATUS_CODE, NULL);
5973
5974 /*
b31fe1d5
TM
5975 * Store the non-encapsulated option data for this
5976 * IA_PD into our reply packet. Defined in RFC 3315,
5977 * section 22.4.
80c9fdb0
FD
5978 */
5979 /* option number */
5980 putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_PD);
5981 /* option length */
5982 putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5983 /* IA_PD, copied from the client */
5984 memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
5985 /* t1 and t2, odd that we need them, but here it is */
5986 putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
5987 putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
5988
5989 /*
5990 * Get ready for next IA_PD.
5991 */
5992 *reply_ofs += (len + 16);
5993
5994exit:
5995 option_state_dereference(&host_opt_state, MDL);
5996}
5997
5998static void
b31fe1d5 5999iterate_over_ia_pd(struct data_string *reply_ret,
80c9fdb0
FD
6000 struct packet *packet,
6001 const struct data_string *client_id,
6002 const struct data_string *server_id,
6003 const char *packet_type,
6004 void (*ia_pd_match)(),
6005 void (*ia_pd_nomatch)())
6006{
6007 struct data_string reply_new;
6008 int reply_len;
6009 struct option_state *opt_state;
6010 struct host_decl *packet_host;
6011 struct option_cache *ia;
6012 struct option_cache *oc;
6013 /* cli_enc_... variables come from the IA_PD options */
6014 struct data_string cli_enc_opt_data;
6015 struct option_state *cli_enc_opt_state;
6016 struct host_decl *host;
6017 struct option_state *host_opt_state;
6018 struct data_string iaprefix;
80c9fdb0
FD
6019 char reply_data[65536];
6020 int reply_ofs;
1d17db44 6021 struct iasubopt *prefix;
9322442f 6022 struct ia_xx *existing_ia_pd;
80c9fdb0
FD
6023 int i;
6024 struct data_string key;
6025 u_int32_t iaid;
6026
6027 /*
6028 * Initialize to empty values, in case we have to exit early.
6029 */
6030 memset(&reply_new, 0, sizeof(reply_new));
6031 opt_state = NULL;
6032 memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
6033 cli_enc_opt_state = NULL;
6034 memset(&iaprefix, 0, sizeof(iaprefix));
6035 host_opt_state = NULL;
6036 prefix = NULL;
6037
6038 /*
6039 * Compute the available length for the reply.
6040 */
6041 reply_len = sizeof(reply_data) - reply_ret->len;
6042 reply_ofs = 0;
6043
b31fe1d5 6044 /*
80c9fdb0
FD
6045 * Find the host record that matches from the packet, if any.
6046 */
6047 packet_host = NULL;
62a9eb91 6048 find_hosts6(&packet_host, packet, client_id, MDL);
80c9fdb0
FD
6049
6050 /*
6051 * Build our option state for reply.
6052 */
6053 opt_state = NULL;
6054 if (!option_state_allocate(&opt_state, MDL)) {
6055 log_error("iterate_over_ia_pd: no memory for option_state.");
6056 goto exit;
6057 }
b31fe1d5
TM
6058 execute_statements_in_scope(NULL, packet, NULL, NULL,
6059 packet->options, opt_state,
a7341359 6060 &global_scope, root_group, NULL, NULL);
80c9fdb0
FD
6061
6062 /*
6063 * Loop through the IA_PD reported by the client, and deal with
6064 * prefixes reported as already in use.
6065 */
6066 for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
6067 ia != NULL; ia = ia->next) {
80c9fdb0
FD
6068
6069 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
6070 &cli_enc_opt_data,
6071 packet, ia, IA_PD_OFFSET)) {
6072 goto exit;
6073 }
6074
6075 iaid = getULong(cli_enc_opt_data.data);
6076
b31fe1d5 6077 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
80c9fdb0
FD
6078 D6O_IAPREFIX);
6079 if (oc == NULL) {
6080 /* no prefix given for this IA_PD, ignore */
6081 option_state_dereference(&cli_enc_opt_state, MDL);
6082 data_string_forget(&cli_enc_opt_data, MDL);
6083 continue;
6084 }
6085
6086 for (; oc != NULL; oc = oc->next) {
6087 memset(&iaprefix, 0, sizeof(iaprefix));
b31fe1d5 6088 if (!evaluate_option_cache(&iaprefix, packet, NULL, NULL,
80c9fdb0
FD
6089 packet->options, NULL,
6090 &global_scope, oc, MDL)) {
6091 log_error("iterate_over_ia_pd: "
6092 "error evaluating IAPREFIX.");
6093 goto exit;
6094 }
6095
b31fe1d5 6096 /*
80c9fdb0 6097 * Now we need to figure out which host record matches
c900c5b2
DH
6098 * this IA_PD and IAPREFIX (encapsulated option contents
6099 * matching a host record by option).
80c9fdb0
FD
6100 *
6101 * XXX: We don't currently track IA_PD separately, but
6102 * we will need to do this!
6103 */
6104 host = NULL;
b31fe1d5
TM
6105 if (!find_hosts_by_option(&host, packet,
6106 cli_enc_opt_state, MDL)) {
80c9fdb0
FD
6107 if (packet_host != NULL) {
6108 host = packet_host;
6109 } else {
6110 host = NULL;
6111 }
6112 }
6113 while (host != NULL) {
6114 if (host->fixed_prefix != NULL) {
6115 struct iaddrcidrnetlist *l;
6116 int plen = (int) getUChar(iaprefix.data + 8);
6117
6118 for (l = host->fixed_prefix; l != NULL;
6119 l = l->next) {
6120 if (plen != l->cidrnet.bits)
6121 continue;
6122 if (memcmp(iaprefix.data + 9,
6123 l->cidrnet.lo_addr.iabuf,
6124 16) == 0)
6125 break;
6126 }
6127 if ((l != NULL) && (iaprefix.len >= 17))
6128 break;
6129 }
6130 host = host->n_ipaddr;
6131 }
6132
6133 if ((host == NULL) && (iaprefix.len >= IAPREFIX_OFFSET)) {
6134 /*
6135 * Find existing IA_PD.
6136 */
b31fe1d5 6137 if (ia_make_key(&key, iaid,
80c9fdb0 6138 (char *)client_id->data,
b31fe1d5 6139 client_id->len,
80c9fdb0
FD
6140 MDL) != ISC_R_SUCCESS) {
6141 log_fatal("iterate_over_ia_pd: no memory for "
6142 "key.");
6143 }
6144
6145 existing_ia_pd = NULL;
b31fe1d5
TM
6146 if (ia_hash_lookup(&existing_ia_pd, ia_pd_active,
6147 (unsigned char *)key.data,
9322442f 6148 key.len, MDL)) {
b31fe1d5 6149 /*
80c9fdb0
FD
6150 * Make sure this prefix is in the IA_PD.
6151 */
6152 for (i = 0;
1d17db44 6153 i < existing_ia_pd->num_iasubopt;
80c9fdb0 6154 i++) {
1d17db44 6155 struct iasubopt *tmp;
80c9fdb0
FD
6156 u_int8_t plen;
6157
6158 plen = getUChar(iaprefix.data + 8);
1d17db44 6159 tmp = existing_ia_pd->iasubopt[i];
80c9fdb0 6160 if ((tmp->plen == plen) &&
9322442f 6161 (memcmp(&tmp->addr,
80c9fdb0
FD
6162 iaprefix.data + 9,
6163 16) == 0)) {
1d17db44
FD
6164 iasubopt_reference(&prefix,
6165 tmp, MDL);
80c9fdb0
FD
6166 break;
6167 }
6168 }
6169 }
6170
6171 data_string_forget(&key, MDL);
6172 }
6173
6174 if ((host != NULL) || (prefix != NULL)) {
6175 ia_pd_match(client_id, &iaprefix, prefix);
6176 } else {
b31fe1d5
TM
6177 ia_pd_nomatch(client_id, &iaprefix,
6178 (u_int32_t *)cli_enc_opt_data.data,
6179 packet, reply_data, &reply_ofs,
80c9fdb0
FD
6180 reply_len - reply_ofs);
6181 }
6182
6183 if (prefix != NULL) {
1d17db44 6184 iasubopt_dereference(&prefix, MDL);
80c9fdb0
FD
6185 }
6186
6187 data_string_forget(&iaprefix, MDL);
6188 }
6189
6190 option_state_dereference(&cli_enc_opt_state, MDL);
6191 data_string_forget(&cli_enc_opt_data, MDL);
6192 }
6193
b31fe1d5 6194 /*
80c9fdb0
FD
6195 * Return our reply to the caller.
6196 * The IA_NA routine has already filled at least the header.
6197 */
6198 reply_new.len = reply_ret->len + reply_ofs;
6199 if (!buffer_allocate(&reply_new.buffer, reply_new.len, MDL)) {
6200 log_fatal("No memory to store reply.");
6201 }
6202 reply_new.data = reply_new.buffer->data;
6203 memcpy(reply_new.buffer->data,
6204 reply_ret->buffer->data, reply_ret->len);
6205 memcpy(reply_new.buffer->data + reply_ret->len,
6206 reply_data, reply_ofs);
6207 data_string_forget(reply_ret, MDL);
6208 data_string_copy(reply_ret, &reply_new, MDL);
6209 data_string_forget(&reply_new, MDL);
6210
6211exit:
6212 if (prefix != NULL) {
1d17db44 6213 iasubopt_dereference(&prefix, MDL);
80c9fdb0
FD
6214 }
6215 if (host_opt_state != NULL) {
6216 option_state_dereference(&host_opt_state, MDL);
6217 }
6218 if (iaprefix.buffer != NULL) {
6219 data_string_forget(&iaprefix, MDL);
6220 }
6221 if (cli_enc_opt_state != NULL) {
6222 option_state_dereference(&cli_enc_opt_state, MDL);
6223 }
6224 if (cli_enc_opt_data.buffer != NULL) {
6225 data_string_forget(&cli_enc_opt_data, MDL);
6226 }
6227 if (opt_state != NULL) {
6228 option_state_dereference(&opt_state, MDL);
6229 }
6230}
6231
98bd7ca0 6232/*
9322442f 6233 * Release means a client is done with the leases.
98bd7ca0
DH
6234 */
6235
98bd7ca0
DH
6236static void
6237dhcpv6_release(struct data_string *reply, struct packet *packet) {
6238 struct data_string client_id;
6239 struct data_string server_id;
6240
b31fe1d5 6241 /*
98bd7ca0
DH
6242 * Validate our input.
6243 */
6244 if (!valid_client_resp(packet, &client_id, &server_id)) {
6245 return;
6246 }
6247
b31fe1d5
TM
6248 /* If the RELEASE arrived via unicast and unicast option isn't set,
6249 * reject it per RFC 3315, Sec 18.2.6 */
6250 if (packet->unicast == ISC_TRUE &&
6251 is_unicast_option_defined(packet) == ISC_FALSE) {
6252 unicast_reject(reply, packet, &client_id, &server_id);
6253 } else {
6254 /*
6255 * And operate on each IA_NA in this packet.
6256 */
6257 iterate_over_ia_na(reply, packet, &client_id, &server_id,
6258 "Release", ia_na_match_release,
6259 ia_na_nomatch_release);
98bd7ca0 6260
b31fe1d5
TM
6261 /*
6262 * And operate on each IA_PD in this packet.
6263 */
6264 iterate_over_ia_pd(reply, packet, &client_id, &server_id,
6265 "Release", ia_pd_match_release,
6266 ia_pd_nomatch_release);
6267 }
80c9fdb0 6268
98bd7ca0
DH
6269 data_string_forget(&server_id, MDL);
6270 data_string_forget(&client_id, MDL);
6271}
6272
6273/*
6274 * Information-Request is used by clients who have obtained an address
6275 * from other means, but want configuration information from the server.
6276 */
6277
98bd7ca0
DH
6278static void
6279dhcpv6_information_request(struct data_string *reply, struct packet *packet) {
6280 struct data_string client_id;
6281 struct data_string server_id;
6282
6283 /*
6284 * Validate our input.
6285 */
6286 if (!valid_client_info_req(packet, &server_id)) {
6287 return;
6288 }
6289
6290 /*
6291 * Get our client ID, if there is one.
6292 */
6293 memset(&client_id, 0, sizeof(client_id));
6294 if (get_client_id(packet, &client_id) != ISC_R_SUCCESS) {
6295 data_string_forget(&client_id, MDL);
6296 }
6297
6298 /*
b31fe1d5
TM
6299 * Use the lease_to_client() function. This will work fine,
6300 * because the valid_client_info_req() insures that we
80c9fdb0
FD
6301 * don't have any IA that would cause us to allocate
6302 * resources to the client.
98bd7ca0 6303 */
4f963ddc
FD
6304 lease_to_client(reply, packet, &client_id,
6305 server_id.data != NULL ? &server_id : NULL);
98bd7ca0
DH
6306
6307 /*
6308 * Cleanup.
6309 */
6310 if (client_id.data != NULL) {
6311 data_string_forget(&client_id, MDL);
6312 }
6313 data_string_forget(&server_id, MDL);
6314}
6315
b31fe1d5 6316/*
98bd7ca0
DH
6317 * The Relay-forw message is sent by relays. It typically contains a
6318 * single option, which encapsulates an entire packet.
6319 *
6320 * We need to build an encapsulated reply.
6321 */
6322
6323/* XXX: this is very, very similar to do_packet6(), and should probably
6324 be combined in a clever way */
6325static void
6326dhcpv6_relay_forw(struct data_string *reply_ret, struct packet *packet) {
98bd7ca0
DH
6327 struct option_cache *oc;
6328 struct data_string enc_opt_data;
6329 struct packet *enc_packet;
6330 unsigned char msg_type;
5279b8f3
DH
6331 const struct dhcpv6_packet *msg;
6332 const struct dhcpv6_relay_packet *relay;
98bd7ca0
DH
6333 struct data_string enc_reply;
6334 char link_addr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6335 char peer_addr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
2b964ac0
FD
6336 struct data_string a_opt, packet_ero;
6337 struct option_state *opt_state;
6338 static char reply_data[65536];
6339 struct dhcpv6_relay_packet *reply;
6340 int reply_ofs;
98bd7ca0 6341
b31fe1d5 6342 /*
20ae1aff 6343 * Initialize variables for early exit.
98bd7ca0 6344 */
93c769ce 6345 opt_state = NULL;
2b964ac0
FD
6346 memset(&a_opt, 0, sizeof(a_opt));
6347 memset(&packet_ero, 0, sizeof(packet_ero));
93c769ce
FD
6348 memset(&enc_reply, 0, sizeof(enc_reply));
6349 memset(&enc_opt_data, 0, sizeof(enc_opt_data));
6350 enc_packet = NULL;
98bd7ca0
DH
6351
6352 /*
6353 * Get our encapsulated relay message.
6354 */
6355 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_RELAY_MSG);
6356 if (oc == NULL) {
6357 inet_ntop(AF_INET6, &packet->dhcpv6_link_address,
6358 link_addr, sizeof(link_addr));
6359 inet_ntop(AF_INET6, &packet->dhcpv6_peer_address,
6360 peer_addr, sizeof(peer_addr));
6361 log_info("Relay-forward from %s with link address=%s and "
6362 "peer address=%s missing Relay Message option.",
6363 piaddr(packet->client_addr), link_addr, peer_addr);
6364 goto exit;
6365 }
6366
b31fe1d5 6367 if (!evaluate_option_cache(&enc_opt_data, NULL, NULL, NULL,
98bd7ca0
DH
6368 NULL, NULL, &global_scope, oc, MDL)) {
6369 log_error("dhcpv6_forw_relay: error evaluating "
6370 "relayed message.");
6371 goto exit;
6372 }
6373
28868515 6374 if (!packet6_len_okay((char *)enc_opt_data.data, enc_opt_data.len)) {
98bd7ca0
DH
6375 log_error("dhcpv6_forw_relay: encapsulated packet too short.");
6376 goto exit;
6377 }
6378
6379 /*
6380 * Build a packet structure from this encapsulated packet.
6381 */
6382 enc_packet = NULL;
6383 if (!packet_allocate(&enc_packet, MDL)) {
6384 log_error("dhcpv6_forw_relay: "
6385 "no memory for encapsulated packet.");
6386 goto exit;
6387 }
6388
6389 if (!option_state_allocate(&enc_packet->options, MDL)) {
6390 log_error("dhcpv6_forw_relay: "
6391 "no memory for encapsulated packet's options.");
6392 goto exit;
6393 }
6394
6395 enc_packet->client_port = packet->client_port;
6396 enc_packet->client_addr = packet->client_addr;
4dc5a6b1 6397 interface_reference(&enc_packet->interface, packet->interface, MDL);
98bd7ca0
DH
6398 enc_packet->dhcpv6_container_packet = packet;
6399
6400 msg_type = enc_opt_data.data[0];
5279b8f3
DH
6401 if ((msg_type == DHCPV6_RELAY_FORW) ||
6402 (msg_type == DHCPV6_RELAY_REPL)) {
b342f2e7 6403 int relaylen = (int)(offsetof(struct dhcpv6_relay_packet, options));
5279b8f3
DH
6404 relay = (struct dhcpv6_relay_packet *)enc_opt_data.data;
6405 enc_packet->dhcpv6_msg_type = relay->msg_type;
98bd7ca0 6406
5279b8f3
DH
6407 /* relay-specific data */
6408 enc_packet->dhcpv6_hop_count = relay->hop_count;
98bd7ca0
DH
6409 memcpy(&enc_packet->dhcpv6_link_address,
6410 relay->link_address, sizeof(relay->link_address));
6411 memcpy(&enc_packet->dhcpv6_peer_address,
6412 relay->peer_address, sizeof(relay->peer_address));
6413
5279b8f3 6414 if (!parse_option_buffer(enc_packet->options,
b31fe1d5 6415 relay->options,
b342f2e7 6416 enc_opt_data.len - relaylen,
5279b8f3
DH
6417 &dhcpv6_universe)) {
6418 /* no logging here, as parse_option_buffer() logs all
6419 cases where it fails */
6420 goto exit;
6421 }
6422 } else {
b342f2e7 6423 int msglen = (int)(offsetof(struct dhcpv6_packet, options));
5279b8f3
DH
6424 msg = (struct dhcpv6_packet *)enc_opt_data.data;
6425 enc_packet->dhcpv6_msg_type = msg->msg_type;
6426
6427 /* message-specific data */
6428 memcpy(enc_packet->dhcpv6_transaction_id,
6429 msg->transaction_id,
6430 sizeof(enc_packet->dhcpv6_transaction_id));
6431
6432 if (!parse_option_buffer(enc_packet->options,
b31fe1d5 6433 msg->options,
b342f2e7 6434 enc_opt_data.len - msglen,
5279b8f3
DH
6435 &dhcpv6_universe)) {
6436 /* no logging here, as parse_option_buffer() logs all
6437 cases where it fails */
6438 goto exit;
6439 }
6440 }
98bd7ca0
DH
6441
6442 /*
6443 * This is recursive. It is possible to exceed maximum packet size.
6444 * XXX: This will cause the packet send to fail.
6445 */
6446 build_dhcpv6_reply(&enc_reply, enc_packet);
6447
6448 /*
6449 * If we got no encapsulated data, then it is discarded, and
6450 * our reply-forw is also discarded.
6451 */
6452 if (enc_reply.data == NULL) {
6453 goto exit;
6454 }
6455
6456 /*
2b964ac0
FD
6457 * Now we can use the reply_data buffer.
6458 * Packet header stuff all comes from the forward message.
6459 */
6460 reply = (struct dhcpv6_relay_packet *)reply_data;
6461 reply->msg_type = DHCPV6_RELAY_REPL;
6462 reply->hop_count = packet->dhcpv6_hop_count;
6463 memcpy(reply->link_address, &packet->dhcpv6_link_address,
6464 sizeof(reply->link_address));
6465 memcpy(reply->peer_address, &packet->dhcpv6_peer_address,
6466 sizeof(reply->peer_address));
a3528574 6467 reply_ofs = (int)(offsetof(struct dhcpv6_relay_packet, options));
2b964ac0
FD
6468
6469 /*
6470 * Get the reply option state.
6471 */
6472 opt_state = NULL;
6473 if (!option_state_allocate(&opt_state, MDL)) {
6474 log_error("dhcpv6_relay_forw: no memory for option state.");
6475 goto exit;
6476 }
6477
6478 /*
6479 * Append the interface-id if present.
98bd7ca0 6480 */
2b964ac0
FD
6481 oc = lookup_option(&dhcpv6_universe, packet->options,
6482 D6O_INTERFACE_ID);
98bd7ca0 6483 if (oc != NULL) {
2b964ac0 6484 if (!evaluate_option_cache(&a_opt, packet,
b31fe1d5 6485 NULL, NULL,
2b964ac0
FD
6486 packet->options, NULL,
6487 &global_scope, oc, MDL)) {
6488 log_error("dhcpv6_relay_forw: error evaluating "
6489 "Interface ID.");
6490 goto exit;
6491 }
6492 if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
6493 (unsigned char *)a_opt.data,
6494 a_opt.len,
6495 D6O_INTERFACE_ID, 0)) {
6496 log_error("dhcpv6_relay_forw: error saving "
98bd7ca0
DH
6497 "Interface ID.");
6498 goto exit;
6499 }
2b964ac0 6500 data_string_forget(&a_opt, MDL);
98bd7ca0
DH
6501 }
6502
b31fe1d5 6503 /*
2b964ac0 6504 * Append our encapsulated stuff for caller.
98bd7ca0 6505 */
2b964ac0
FD
6506 if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
6507 (unsigned char *)enc_reply.data,
6508 enc_reply.len,
6509 D6O_RELAY_MSG, 0)) {
6510 log_error("dhcpv6_relay_forw: error saving Relay MSG.");
6511 goto exit;
98bd7ca0 6512 }
2b964ac0
FD
6513
6514 /*
6515 * Get the ERO if any.
98bd7ca0 6516 */
2b964ac0
FD
6517 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ERO);
6518 if (oc != NULL) {
6519 unsigned req;
6520 int i;
6521
6522 if (!evaluate_option_cache(&packet_ero, packet,
6523 NULL, NULL,
6524 packet->options, NULL,
6525 &global_scope, oc, MDL) ||
6526 (packet_ero.len & 1)) {
6527 log_error("dhcpv6_relay_forw: error evaluating ERO.");
6528 goto exit;
6529 }
6530
6531 /* Decode and apply the ERO. */
6532 for (i = 0; i < packet_ero.len; i += 2) {
6533 req = getUShort(packet_ero.data + i);
6534 /* Already in the reply? */
6535 oc = lookup_option(&dhcpv6_universe, opt_state, req);
6536 if (oc != NULL)
6537 continue;
6538 /* Get it from the packet if present. */
6539 oc = lookup_option(&dhcpv6_universe,
6540 packet->options,
6541 req);
6542 if (oc == NULL)
6543 continue;
6544 if (!evaluate_option_cache(&a_opt, packet,
6545 NULL, NULL,
6546 packet->options, NULL,
6547 &global_scope, oc, MDL)) {
6548 log_error("dhcpv6_relay_forw: error "
6549 "evaluating option %u.", req);
6550 goto exit;
6551 }
6552 if (!save_option_buffer(&dhcpv6_universe,
6553 opt_state,
6554 NULL,
6555 (unsigned char *)a_opt.data,
6556 a_opt.len,
6557 req,
6558 0)) {
6559 log_error("dhcpv6_relay_forw: error saving "
6560 "option %u.", req);
6561 goto exit;
6562 }
6563 data_string_forget(&a_opt, MDL);
6564 }
98bd7ca0 6565 }
2b964ac0
FD
6566
6567 reply_ofs += store_options6(reply_data + reply_ofs,
6568 sizeof(reply_data) - reply_ofs,
6569 opt_state, packet,
6570 required_opts_agent, &packet_ero);
6571
6572 /*
6573 * Return our reply to the caller.
6574 */
6575 reply_ret->len = reply_ofs;
98bd7ca0
DH
6576 reply_ret->buffer = NULL;
6577 if (!buffer_allocate(&reply_ret->buffer, reply_ret->len, MDL)) {
6578 log_fatal("No memory to store reply.");
6579 }
6580 reply_ret->data = reply_ret->buffer->data;
2b964ac0 6581 memcpy(reply_ret->buffer->data, reply_data, reply_ofs);
98bd7ca0
DH
6582
6583exit:
2b964ac0
FD
6584 if (opt_state != NULL)
6585 option_state_dereference(&opt_state, MDL);
6586 if (a_opt.data != NULL) {
6587 data_string_forget(&a_opt, MDL);
6588 }
6589 if (packet_ero.data != NULL) {
6590 data_string_forget(&packet_ero, MDL);
98bd7ca0
DH
6591 }
6592 if (enc_reply.data != NULL) {
6593 data_string_forget(&enc_reply, MDL);
6594 }
6595 if (enc_opt_data.data != NULL) {
6596 data_string_forget(&enc_opt_data, MDL);
6597 }
6598 if (enc_packet != NULL) {
6599 packet_dereference(&enc_packet, MDL);
6600 }
6601}
6602
6603static void
6604dhcpv6_discard(struct packet *packet) {
6605 /* INSIST(packet->msg_type > 0); */
6606 /* INSIST(packet->msg_type < dhcpv6_type_name_max); */
6607
b31fe1d5 6608 log_debug("Discarding %s from %s; message type not handled by server",
98bd7ca0
DH
6609 dhcpv6_type_names[packet->dhcpv6_msg_type],
6610 piaddr(packet->client_addr));
6611}
6612
b31fe1d5 6613static void
98bd7ca0
DH
6614build_dhcpv6_reply(struct data_string *reply, struct packet *packet) {
6615 memset(reply, 0, sizeof(*reply));
01fa619f 6616
619304cd
SR
6617 /* I would like to classify the client once here, but
6618 * as I don't want to classify all of the incoming packets
6619 * I need to do it before handling specific types.
6620 * We don't need to classify if we are tossing the packet
6621 * or if it is a relay - the classification step will get
6622 * done when we process the inner client packet.
6623 */
01fa619f 6624
98bd7ca0
DH
6625 switch (packet->dhcpv6_msg_type) {
6626 case DHCPV6_SOLICIT:
619304cd 6627 classify_client(packet);
98bd7ca0
DH
6628 dhcpv6_solicit(reply, packet);
6629 break;
6630 case DHCPV6_ADVERTISE:
6631 dhcpv6_discard(packet);
6632 break;
6633 case DHCPV6_REQUEST:
619304cd 6634 classify_client(packet);
98bd7ca0
DH
6635 dhcpv6_request(reply, packet);
6636 break;
6637 case DHCPV6_CONFIRM:
619304cd 6638 classify_client(packet);
98bd7ca0
DH
6639 dhcpv6_confirm(reply, packet);
6640 break;
6641 case DHCPV6_RENEW:
619304cd 6642 classify_client(packet);
98bd7ca0
DH
6643 dhcpv6_renew(reply, packet);
6644 break;
6645 case DHCPV6_REBIND:
619304cd 6646 classify_client(packet);
98bd7ca0
DH
6647 dhcpv6_rebind(reply, packet);
6648 break;
6649 case DHCPV6_REPLY:
6650 dhcpv6_discard(packet);
6651 break;
6652 case DHCPV6_RELEASE:
619304cd 6653 classify_client(packet);
98bd7ca0
DH
6654 dhcpv6_release(reply, packet);
6655 break;
6656 case DHCPV6_DECLINE:
619304cd 6657 classify_client(packet);
98bd7ca0
DH
6658 dhcpv6_decline(reply, packet);
6659 break;
6660 case DHCPV6_RECONFIGURE:
6661 dhcpv6_discard(packet);
6662 break;
6663 case DHCPV6_INFORMATION_REQUEST:
619304cd 6664 classify_client(packet);
98bd7ca0
DH
6665 dhcpv6_information_request(reply, packet);
6666 break;
6667 case DHCPV6_RELAY_FORW:
6668 dhcpv6_relay_forw(reply, packet);
6669 break;
6670 case DHCPV6_RELAY_REPL:
6671 dhcpv6_discard(packet);
6672 break;
37ec5845 6673 case DHCPV6_LEASEQUERY:
619304cd 6674 classify_client(packet);
37ec5845
FD
6675 dhcpv6_leasequery(reply, packet);
6676 break;
6677 case DHCPV6_LEASEQUERY_REPLY:
6678 dhcpv6_discard(packet);
6679 break;
98bd7ca0 6680 default:
b31fe1d5 6681 /* XXX: would be nice if we had "notice" level,
98bd7ca0
DH
6682 as syslog, for this */
6683 log_info("Discarding unknown DHCPv6 message type %d "
b31fe1d5 6684 "from %s", packet->dhcpv6_msg_type,
98bd7ca0
DH
6685 piaddr(packet->client_addr));
6686 }
6687}
6688
6689static void
6690log_packet_in(const struct packet *packet) {
6691 struct data_string s;
6692 u_int32_t tid;
6693 char tmp_addr[INET6_ADDRSTRLEN];
6694 const void *addr;
98bd7ca0
DH
6695
6696 memset(&s, 0, sizeof(s));
6697
6698 if (packet->dhcpv6_msg_type < dhcpv6_type_name_max) {
6699 data_string_sprintfa(&s, "%s message from %s port %d",
6700 dhcpv6_type_names[packet->dhcpv6_msg_type],
6701 piaddr(packet->client_addr),
6702 ntohs(packet->client_port));
6703 } else {
b31fe1d5 6704 data_string_sprintfa(&s,
98bd7ca0
DH
6705 "Unknown message type %d from %s port %d",
6706 packet->dhcpv6_msg_type,
6707 piaddr(packet->client_addr),
6708 ntohs(packet->client_port));
6709 }
b31fe1d5 6710 if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) ||
98bd7ca0
DH
6711 (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
6712 addr = &packet->dhcpv6_link_address;
b31fe1d5
TM
6713 data_string_sprintfa(&s, ", link address %s",
6714 inet_ntop(AF_INET6, addr,
98bd7ca0
DH
6715 tmp_addr, sizeof(tmp_addr)));
6716 addr = &packet->dhcpv6_peer_address;
b31fe1d5
TM
6717 data_string_sprintfa(&s, ", peer address %s",
6718 inet_ntop(AF_INET6, addr,
98bd7ca0
DH
6719 tmp_addr, sizeof(tmp_addr)));
6720 } else {
6721 tid = 0;
6722 memcpy(((char *)&tid)+1, packet->dhcpv6_transaction_id, 3);
6723 data_string_sprintfa(&s, ", transaction ID 0x%06X", tid);
6724
6725/*
b31fe1d5 6726 oc = lookup_option(&dhcpv6_universe, packet->options,
98bd7ca0
DH
6727 D6O_CLIENTID);
6728 if (oc != NULL) {
6729 memset(&tmp_ds, 0, sizeof(tmp_ds_));
b31fe1d5 6730 if (!evaluate_option_cache(&tmp_ds, packet, NULL, NULL,
98bd7ca0
DH
6731 packet->options, NULL,
6732 &global_scope, oc, MDL)) {
6733 log_error("Error evaluating Client Identifier");
6734 } else {
6735 data_strint_sprintf(&s, ", client ID %s",
6736
6737 data_string_forget(&tmp_ds, MDL);
6738 }
6739 }
6740*/
6741
6742 }
6743 log_info("%s", s.data);
6744
6745 data_string_forget(&s, MDL);
6746}
6747
b31fe1d5 6748void
98bd7ca0
DH
6749dhcpv6(struct packet *packet) {
6750 struct data_string reply;
6751 struct sockaddr_in6 to_addr;
6752 int send_ret;
6753
b31fe1d5 6754 /*
98bd7ca0
DH
6755 * Log a message that we received this packet.
6756 */
b31fe1d5 6757 log_packet_in(packet);
98bd7ca0
DH
6758
6759 /*
6760 * Build our reply packet.
6761 */
6762 build_dhcpv6_reply(&reply, packet);
6763
6764 if (reply.data != NULL) {
b31fe1d5 6765 /*
98bd7ca0
DH
6766 * Send our reply, if we have one.
6767 */
6768 memset(&to_addr, 0, sizeof(to_addr));
6769 to_addr.sin6_family = AF_INET6;
b31fe1d5 6770 if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) ||
98bd7ca0
DH
6771 (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
6772 to_addr.sin6_port = local_port;
6773 } else {
6774 to_addr.sin6_port = remote_port;
6775 }
fb30f3fc
SR
6776
6777#if defined (REPLY_TO_SOURCE_PORT)
6778 /*
6779 * This appears to have been included for testing so we would
6780 * not need a root client, but was accidently left in the
6781 * final code. We continue to include it in case
6782 * some users have come to rely upon it, but leave
6783 * it off by default as it's a bad idea.
6784 */
98bd7ca0 6785 to_addr.sin6_port = packet->client_port;
fb30f3fc
SR
6786#endif
6787
b31fe1d5 6788 memcpy(&to_addr.sin6_addr, packet->client_addr.iabuf,
98bd7ca0
DH
6789 sizeof(to_addr.sin6_addr));
6790
b31fe1d5 6791 log_info("Sending %s to %s port %d",
98bd7ca0
DH
6792 dhcpv6_type_names[reply.data[0]],
6793 piaddr(packet->client_addr),
6794 ntohs(to_addr.sin6_port));
6795
b31fe1d5 6796 send_ret = send_packet6(packet->interface,
98bd7ca0
DH
6797 reply.data, reply.len, &to_addr);
6798 if (send_ret != reply.len) {
6799 log_error("dhcpv6: send_packet6() sent %d of %d bytes",
6800 send_ret, reply.len);
6801 }
6802 data_string_forget(&reply, MDL);
6803 }
6804}
6805
5279b8f3
DH
6806static void
6807seek_shared_host(struct host_decl **hp, struct shared_network *shared) {
6808 struct host_decl *nofixed = NULL;
6809 struct host_decl *seek, *hold = NULL;
6810
6811 /*
bd72740e
FD
6812 * Seek forward through fixed addresses for the right link.
6813 *
6814 * Note: how to do this for fixed prefixes???
5279b8f3
DH
6815 */
6816 host_reference(&hold, *hp, MDL);
6817 host_dereference(hp, MDL);
6818 seek = hold;
6819 while (seek != NULL) {
6820 if (seek->fixed_addr == NULL)
6821 nofixed = seek;
6822 else if (fixed_matches_shared(seek, shared))
6823 break;
6824
6825 seek = seek->n_ipaddr;
6826 }
6827
6828 if ((seek == NULL) && (nofixed != NULL))
6829 seek = nofixed;
6830
6831 if (seek != NULL)
6832 host_reference(hp, seek, MDL);
6833}
6834
6835static isc_boolean_t
6836fixed_matches_shared(struct host_decl *host, struct shared_network *shared) {
6837 struct subnet *subnet;
6838 struct data_string addr;
6839 isc_boolean_t matched;
6840 struct iaddr fixed;
6841
6842 if (host->fixed_addr == NULL)
6843 return ISC_FALSE;
6844
6845 memset(&addr, 0, sizeof(addr));
6846 if (!evaluate_option_cache(&addr, NULL, NULL, NULL, NULL, NULL,
6847 &global_scope, host->fixed_addr, MDL))
6848 return ISC_FALSE;
6849
6850 if (addr.len < 16) {
6851 data_string_forget(&addr, MDL);
6852 return ISC_FALSE;
6853 }
6854
6855 fixed.len = 16;
6856 memcpy(fixed.iabuf, addr.data, 16);
6857
6858 matched = ISC_FALSE;
6859 for (subnet = shared->subnets ; subnet != NULL ;
6860 subnet = subnet->next_sibling) {
6861 if (addr_eq(subnet_number(fixed, subnet->netmask),
6862 subnet->net)) {
6863 matched = ISC_TRUE;
6864 break;
6865 }
6866 }
6867
6868 data_string_forget(&addr, MDL);
6869 return matched;
6870}
6871
b31fe1d5
TM
6872/*!
6873 *
6874 * \brief Constructs a REPLY with status of UseMulticast to a given packet
6875 *
6876 * Per RFC 3315 Secs 18.2.1,3,6 & 7, when a server rejects a client's
6877 * unicast-sent packet, the response must only contain the client id,
6878 * server id, and a status code option of 5 (UseMulticast). This function
6879 * constructs such a packet and returns it as a data_string.
6880 *
6881 * \param reply_ret = data_string which will receive the newly constructed
6882 * reply
6883 * \param packet = client request which is being rejected
6884 * \param client_id = data_string which contains the client id
6885 * \param server_id = data_string which which contains the server id
6886 *
6887 */
6888void
6889unicast_reject(struct data_string *reply_ret,
6890 struct packet *packet,
6891 const struct data_string *client_id,
6892 const struct data_string *server_id)
6893{
6894 struct reply_state reply;
6895 memset(&reply, 0x0, sizeof(struct reply_state));
6896
6897 /* Locate the client. */
6898 if (shared_network_from_packet6(&reply.shared, packet)
6899 != ISC_R_SUCCESS) {
6900 log_error("unicast_reject: could not locate client.");
6901 return;
6902 }
6903
6904 /* Initialize the reply. */
6905 packet_reference(&reply.packet, packet, MDL);
6906 data_string_copy(&reply.client_id, client_id, MDL);
6907
6908 if (start_reply(packet, client_id, server_id, &reply.opt_state,
6909 &reply.buf.reply)) {
6910 /* Set the UseMulticast status code. */
6911 if (!set_status_code(STATUS_UseMulticast,
6912 "Unicast not allowed by server.",
6913 reply.opt_state)) {
6914 log_error("unicast_reject: Unable to set status code.");
6915 } else {
6916 /* Set write cursor to just past the reply header. */
6917 reply.cursor = REPLY_OPTIONS_INDEX;
6918 reply.cursor += store_options6(((char *)reply.buf.data
6919 + reply.cursor),
6920 (sizeof(reply.buf)
6921 - reply.cursor),
6922 reply.opt_state,
6923 reply.packet,
6924 unicast_reject_opts,
6925 NULL);
6926
6927 /* Return our reply to the caller. */
6928 reply_ret->len = reply.cursor;
6929 reply_ret->buffer = NULL;
6930 if (!buffer_allocate(&reply_ret->buffer,
6931 reply.cursor, MDL)) {
6932 log_fatal("unicast_reject:"
6933 "No memory to store Reply.");
6934 }
6935
6936 memcpy(reply_ret->buffer->data, reply.buf.data,
6937 reply.cursor);
6938 reply_ret->data = reply_ret->buffer->data;
6939 }
6940
6941 }
6942
6943 /* Cleanup. */
6944 if (reply.shared != NULL)
6945 shared_network_dereference(&reply.shared, MDL);
6946 if (reply.opt_state != NULL)
6947 option_state_dereference(&reply.opt_state, MDL);
6948 if (reply.packet != NULL)
6949 packet_dereference(&reply.packet, MDL);
6950 if (reply.client_id.data != NULL)
6951 data_string_forget(&reply.client_id, MDL);
6952}
6953
6954/*!
6955 *
6956 * \brief Checks if the dhcp6.unicast option has been defined
6957 *
6958 * Scans the option space for the presence of the dhcp6.unicast option. The
6959 * function attempts to map the inbound packet to a shared network first
6960 * by an ip address specified via an D6O_IA_XX option and if that fails then
6961 * by the packet's source information (e.g. relay link, link, or interace).
6962 * Once the packet is mapped to a shared network, the function executes all
6963 * statements from the network's group outward into a local option cache.
6964 * The option cache is then scanned for the presence of unicast option. If
6965 * the packet cannot be mapped to a shared network, the function returns
6966 * ISC_FALSE.
6967 * \param packet inbound packet from the client
6968 *
6969 * \return ISC_TRUE if the dhcp6.unicast option is defined, false otherwise.
6970 *
6971 */
6972isc_boolean_t
6973is_unicast_option_defined(struct packet *packet) {
6974 isc_boolean_t is_defined = ISC_FALSE;
6975 struct option_state *opt_state = NULL;
6976 struct option_cache *oc = NULL;
6977 struct shared_network *shared = NULL;
6978
6979 if (!option_state_allocate(&opt_state, MDL)) {
6980 log_fatal("is_unicast_option_defined:"
6981 "No memory for option state.");
6982 }
6983
6984 /* We try to map the packet to a network first by an IA_XX value.
6985 * If that fails, we try by packet source. */
6986 if (((shared_network_from_requested_addr(&shared, packet)
6987 != ISC_R_SUCCESS) &&
6988 (shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS))
6989 || (shared == NULL)) {
6990 /* @todo what would this really mean? I think wrong network
6991 * logic will catch it */
6992 log_error("is_unicast_option_defined:"
6993 "cannot attribute packet to a network.");
6994 return (ISC_FALSE);
6995 }
6996
6997 /* Now that we've mapped it to a network, execute statments to that
6998 * scope, looking for the unicast option. We don't care about the
6999 * value of the option, only whether or not it is defined. */
7000 execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL, opt_state,
7001 &global_scope, shared->group, NULL, NULL);
7002
7003 oc = lookup_option(&dhcpv6_universe, opt_state, D6O_UNICAST);
7004 is_defined = (oc != NULL ? ISC_TRUE : ISC_FALSE);
7005 log_debug("is_unicast_option_defined: option found : %d", is_defined);
7006
7007 if (shared != NULL) {
7008 shared_network_dereference(&shared, MDL);
7009 }
7010
7011 if (opt_state != NULL) {
7012 option_state_dereference(&opt_state, MDL);
7013 }
7014
7015 return (is_defined);
7016}
7017
7018/*!
7019 *
7020 * \brief Maps a packet to a shared network based on the requested IP address
7021 *
7022 * The function attempts to find a subnet that matches the first requested IP
7023 * address contained within the given packet. Note that it looks first for
7024 * D6O_IA_NAs, then D6O_IA_PDs and lastly D6O_IA_TAs. If a matching network is
7025 * found, a reference to it is returned in the parameter, shared.
7026 *
7027 * \param shared shared_network pointer which will receive the matching network
7028 * \param packet inbound packet from the client
7029 *
7030 * \return ISC_R_SUCCESS if the packet can be mapped to a shared_network.
7031 *
7032 */
7033static isc_result_t
7034shared_network_from_requested_addr (struct shared_network **shared,
7035 struct packet* packet) {
7036 struct iaddr iaddr;
7037 struct subnet* subnet = NULL;
7038 isc_result_t status = ISC_R_FAILURE;
7039
7040 /* Try to match first IA_ address or prefix we find to a subnet. In
7041 * theory all IA_ values in a given request are supposed to be in the
7042 * same subnet so we only need to try one right? */
7043 if ((get_first_ia_addr_val(packet, D6O_IA_NA, &iaddr) != ISC_R_SUCCESS)
7044 && (get_first_ia_addr_val(packet, D6O_IA_PD, &iaddr)
7045 != ISC_R_SUCCESS)
7046 && (get_first_ia_addr_val(packet, D6O_IA_TA, &iaddr)
7047 != ISC_R_SUCCESS)) {
7048 /* we found nothing to match against */
7049 log_debug("share_network_from_request_addr: nothing to match");
7050 return (ISC_R_FAILURE);
7051 }
7052
7053 if (!find_subnet(&subnet, iaddr, MDL)) {
7054 log_debug("shared_network_from_requested_addr:"
7055 "No subnet found for addr %s.", piaddr(iaddr));
7056 } else {
7057 status = shared_network_reference(shared,
7058 subnet->shared_network, MDL);
7059 subnet_dereference(&subnet, MDL);
7060 log_debug("shared_network_from_requested_addr:"
7061 " found shared network %s for address %s.",
7062 ((*shared)->name ? (*shared)->name : "unnamed"),
7063 piaddr(iaddr));
7064 return (status);
7065 }
7066
7067 return (ISC_R_FAILURE);
7068}
7069
7070/*!
7071 *
7072 * \brief Retrieves the first IP address from a given packet of a given type
7073 *
7074 * Search a packet for options of a given type (D6O_IA_AN, D6O_IA_PD, or
7075 * D6O_IA_TA) for the first non-blank IA_XX value and return its IP address
7076 * component.
7077 *
7078 * \param packet packet received from the client
7079 * \param addr_type the address option type (D6O_IA_NA , D6O_IA_PD, or
7080 * D6O_IP_TA) to look for within the packet.
7081 * \param iaddr pointer to the iaddr structure which will receive the extracted
7082 * address.
7083 *
7084 * \return ISC_R_SUCCESS if an address was succesfully extracted, ISC_R_FALURE
7085 * otherwise.
7086 *
7087 */
7088static isc_result_t
7089get_first_ia_addr_val (struct packet* packet, int addr_type,
7090 struct iaddr* iaddr) {
7091 struct option_cache *ia;
7092 struct option_cache *oc = NULL;
7093 struct data_string cli_enc_opt_data;
7094 struct option_state *cli_enc_opt_state;
7095 int addr_opt_offset;
7096 int addr_opt;
7097 int addr_opt_data_len;
7098 int ip_addr_offset;
7099
7100 isc_result_t status = ISC_R_FAILURE;
7101 memset(iaddr, 0, sizeof(struct iaddr));
7102
7103 /* Set up address type specifics */
7104 switch (addr_type) {
7105 case D6O_IA_NA:
7106 addr_opt_offset = IA_NA_OFFSET;
7107 addr_opt = D6O_IAADDR;
7108 addr_opt_data_len = 24;
7109 ip_addr_offset = 0;
7110 break;
7111 case D6O_IA_TA:
7112 addr_opt_offset = IA_TA_OFFSET;
7113 addr_opt = D6O_IAADDR;
7114 addr_opt_data_len = 24;
7115 ip_addr_offset = 0;
7116 break;
7117 case D6O_IA_PD:
7118 addr_opt_offset = IA_PD_OFFSET;
7119 addr_opt = D6O_IAPREFIX;
7120 addr_opt_data_len = 25;
7121 ip_addr_offset = 9;
7122 break;
7123 default:
7124 /* shouldn't be here */
7125 log_error ("get_first_ia_addr_val: invalid opt type %d",
7126 addr_type);
7127 return (ISC_R_FAILURE);
7128 }
7129
7130 /* Find the first, non-blank IA_XX value within an D6O_IA_XX option. */
7131 for (ia = lookup_option(&dhcpv6_universe, packet->options, addr_type);
7132 ia != NULL && oc == NULL; ia = ia->next) {
b31fe1d5
TM
7133 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
7134 &cli_enc_opt_data,
7135 packet, ia, addr_opt_offset)) {
7136 log_debug ("get_first_ia_addr_val:"
7137 " couldn't unroll enclosing option");
7138 return (ISC_R_FAILURE);
7139 }
7140
b31fe1d5
TM
7141 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
7142 addr_opt);
7143 if (oc == NULL) {
7144 /* no address given for this IA, ignore */
7145 option_state_dereference(&cli_enc_opt_state, MDL);
7146 data_string_forget(&cli_enc_opt_data, MDL);
7147 }
7148 }
7149
7150 /* If we found a non-blank IA_XX then extract its ip address. */
7151 if (oc != NULL) {
7152 struct data_string iaddr_str;
7153
7154 memset(&iaddr_str, 0, sizeof(iaddr_str));
7155 if (!evaluate_option_cache(&iaddr_str, packet, NULL, NULL,
7156 packet->options, NULL, &global_scope,
7157 oc, MDL)) {
7158 log_error("get_first_ia_addr_val: "
7159 "error evaluating IA_XX option.");
7160 } else {
7161 if (iaddr_str.len != addr_opt_data_len) {
7162 log_error("shared_network_from_requested_addr:"
7163 " invalid length %d, expected %d",
7164 iaddr_str.len, addr_opt_data_len);
7165 } else {
7166 iaddr->len = 16;
7167 memcpy (iaddr->iabuf,
7168 iaddr_str.data + ip_addr_offset, 16);
7169 status = ISC_R_SUCCESS;
7170 }
7171 data_string_forget(&iaddr_str, MDL);
7172 }
7173
7174 option_state_dereference(&cli_enc_opt_state, MDL);
7175 data_string_forget(&cli_enc_opt_data, MDL);
7176 }
7177
7178 return (status);
7179}
7180
fe5b0fdd 7181#endif /* DHCPv6 */