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