]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/dhcpv6.c
Code cleanup to remove warnings from "gcc -Wall".
[thirdparty/dhcp.git] / server / dhcpv6.c
CommitLineData
98bd7ca0 1/*
706792c9 2 * Copyright (C) 2006-2007 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
17#include "dhcpd.h"
18
fe5b0fdd
DH
19#ifdef DHCPv6
20
98bd7ca0
DH
21/*
22 * We use print_hex_1() to output DUID values. We could actually output
23 * the DUID with more information... MAC address if using type 1 or 3,
24 * and so on. However, RFC 3315 contains Grave Warnings against actually
25 * attempting to understand a DUID.
26 */
27
28/*
29 * TODO: gettext() or other method of localization for the messages
30 * for status codes (and probably for log formats eventually)
31 * TODO: refactoring (simplify, simplify, simplify)
32 * TODO: support multiple shared_networks on each interface (this
33 * will allow the server to issue multiple IPv6 addresses to
34 * a single interface)
35 */
36
37/*
38 * Prototypes local to this file.
39 */
40static void build_dhcpv6_reply(struct data_string *, struct packet *);
41
42/*
43 * DUID time starts 2000-01-01.
44 * This constant is the number of seconds since 1970-01-01,
45 * when the Unix epoch began.
46 */
47#define DUID_TIME_EPOCH 946684800
48
49/*
50 * This function returns the time since DUID time start for the
51 * given time_t value.
52 */
53static u_int32_t
54duid_time(time_t when) {
55 /*
56 * This time is modulo 2^32.
57 */
58 while ((when - DUID_TIME_EPOCH) > 4294967295u) {
59 /* use 2^31 to avoid spurious compiler warnings */
60 when -= 2147483648u;
61 when -= 2147483648u;
62 }
63
64 return when - DUID_TIME_EPOCH;
65}
66
67
68/*
69 * Server DUID.
70 *
71 * This must remain the same for the lifetime of this server, because
72 * clients return the server DUID that we sent them in Request packets.
73 *
74 * We pick the server DUID like this:
75 *
76 * 1. Check dhcpd.conf - any value the administrator has configured
77 * overrides any possible values.
78 * 2. Check the leases.txt - we want to use the previous value if
79 * possible.
80 * 3. Check if dhcpd.conf specifies a type of server DUID to use,
81 * and generate that type.
82 * 4. Generate a type 1 (time + hardware address) DUID.
83 */
84static struct data_string server_duid;
85
86/*
87 * Check if the server_duid has been set.
88 */
89isc_boolean_t
90server_duid_isset(void) {
91 return (server_duid.data != NULL);
92}
93
94/*
95 * Return the server_duid.
96 */
97void
98copy_server_duid(struct data_string *ds, const char *file, int line) {
99 data_string_copy(ds, &server_duid, file, line);
100}
101
102/*
103 * Set the server DUID to a specified value. This is used when
104 * the server DUID is stored in persistent memory (basically the
105 * leases.txt file).
106 */
107void
108set_server_duid(struct data_string *new_duid) {
109 /* INSIST(new_duid != NULL); */
110 /* INSIST(new_duid->data != NULL); */
111
112 if (server_duid_isset()) {
113 data_string_forget(&server_duid, MDL);
114 }
115 data_string_copy(&server_duid, new_duid, MDL);
116}
117
118
119/*
120 * Set the server DUID based on the D6O_SERVERID option. This handles
121 * the case where the administrator explicitly put it in the dhcpd.conf
122 * file.
123 */
124isc_result_t
125set_server_duid_from_option(void) {
126 struct option_state *opt_state;
127 struct option_cache *oc;
128 struct data_string option_duid;
129 isc_result_t ret_val;
130
131 opt_state = NULL;
132 if (!option_state_allocate(&opt_state, MDL)) {
133 log_fatal("No memory for server DUID.");
134 }
135
136 execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
137 opt_state, &global_scope, root_group, NULL);
138
139 oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
140 if (oc == NULL) {
141 ret_val = ISC_R_NOTFOUND;
142 } else {
143 memset(&option_duid, 0, sizeof(option_duid));
144 if (!evaluate_option_cache(&option_duid, NULL, NULL, NULL,
145 opt_state, NULL, &global_scope,
146 oc, MDL)) {
147 ret_val = ISC_R_UNEXPECTED;
148 } else {
149 set_server_duid(&option_duid);
150 data_string_forget(&option_duid, MDL);
151 ret_val = ISC_R_SUCCESS;
152 }
153 }
154
155 option_state_dereference(&opt_state, MDL);
156
157 return ret_val;
158}
159
160/*
161 * DUID layout, as defined in RFC 3315, section 9.
162 *
163 * We support type 1 (hardware address plus time) and type 3 (hardware
164 * address).
165 *
166 * We can support type 2 for specific vendors in the future, if they
167 * publish the specification. And of course there may be additional
168 * types later.
169 */
170static int server_duid_type = DUID_LLT;
171
172/*
173 * Set the DUID type.
174 */
175void
176set_server_duid_type(int type) {
177 server_duid_type = type;
178}
179
180/*
181 * Generate a new server DUID. This is done if there was no DUID in
182 * the leases.txt or in the dhcpd.conf file.
183 */
184isc_result_t
185generate_new_server_duid(void) {
186 struct interface_info *p;
187 u_int32_t time_val;
188 struct data_string generated_duid;
189
190 /*
191 * Verify we have a type that we support.
192 */
193 if ((server_duid_type != DUID_LL) && (server_duid_type != DUID_LLT)) {
194 log_error("Invalid DUID type %d specified, "
195 "only LL and LLT types supported", server_duid_type);
196 return ISC_R_INVALIDARG;
197 }
198
199 /*
200 * Find an interface with a hardware address.
201 * Any will do. :)
202 */
203 for (p = interfaces; p != NULL; p = p->next) {
204 if (p->hw_address.hlen > 0) {
205 break;
206 }
207 }
208 if (p == NULL) {
209 return ISC_R_UNEXPECTED;
210 }
211
212 /*
213 * Build our DUID.
214 */
215 memset(&generated_duid, 0, sizeof(generated_duid));
216 if (server_duid_type == DUID_LLT) {
217 time_val = duid_time(time(NULL));
218 generated_duid.len = 8 + p->hw_address.hlen - 1;
219 if (!buffer_allocate(&generated_duid.buffer,
220 generated_duid.len, MDL)) {
221 log_fatal("No memory for server DUID.");
222 }
223 generated_duid.data = generated_duid.buffer->data;
224 putUShort(generated_duid.buffer->data, DUID_LLT);
225 putUShort(generated_duid.buffer->data + 2,
226 p->hw_address.hbuf[0]);
227 putULong(generated_duid.buffer->data + 4, time_val);
228 memcpy(generated_duid.buffer->data + 8,
229 p->hw_address.hbuf+1, p->hw_address.hlen-1);
230 } else if (server_duid_type == DUID_LL) {
231 generated_duid.len = 4 + p->hw_address.hlen - 1;
232 if (!buffer_allocate(&generated_duid.buffer,
233 generated_duid.len, MDL)) {
234 log_fatal("No memory for server DUID.");
235 }
236 generated_duid.data = generated_duid.buffer->data;
237 putUShort(generated_duid.buffer->data, DUID_LL);
238 putUShort(generated_duid.buffer->data + 2,
239 p->hw_address.hbuf[0]);
240 memcpy(generated_duid.buffer->data +4,
241 p->hw_address.hbuf+1, p->hw_address.hlen-1);
242 } else {
243 log_fatal("Unsupported server DUID type %d.", server_duid_type);
244 }
245
246 set_server_duid(&generated_duid);
247 data_string_forget(&generated_duid, MDL);
248
249 return ISC_R_SUCCESS;
250}
251
252/*
253 * Get the client identifier from the packet.
254 */
255isc_result_t
256get_client_id(struct packet *packet, struct data_string *client_id) {
257 struct option_cache *oc;
258
259 /*
260 * Verify our client_id structure is empty.
261 */
262 if ((client_id->data != NULL) || (client_id->len != 0)) {
263 return ISC_R_INVALIDARG;
264 }
265
266 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
267 if (oc == NULL) {
268 return ISC_R_NOTFOUND;
269 }
270
271 if (!evaluate_option_cache(client_id, packet, NULL, NULL,
272 packet->options, NULL,
273 &global_scope, oc, MDL)) {
274 return ISC_R_FAILURE;
275 }
276
277 return ISC_R_SUCCESS;
278}
279
280/*
281 * Message validation, defined in RFC 3315, sections 15.2, 15.5, 15.7:
282 *
283 * Servers MUST discard any Solicit messages that do not include a
284 * Client Identifier option or that do include a Server Identifier
285 * option.
286 */
287int
288valid_client_msg(struct packet *packet, struct data_string *client_id) {
289 int ret_val;
290 struct option_cache *oc;
291 struct data_string data;
292
293 ret_val = 0;
294 memset(client_id, 0, sizeof(*client_id));
295 memset(&data, 0, sizeof(data));
296
297 switch (get_client_id(packet, client_id)) {
298 case ISC_R_SUCCESS:
299 break;
300 case ISC_R_NOTFOUND:
301 log_debug("Discarding %s from %s; "
302 "client identifier missing",
303 dhcpv6_type_names[packet->dhcpv6_msg_type],
304 piaddr(packet->client_addr));
305 goto exit;
306 default:
307 log_error("Error processing %s from %s; "
308 "unable to evaluate Client Identifier",
309 dhcpv6_type_names[packet->dhcpv6_msg_type],
310 piaddr(packet->client_addr));
311 goto exit;
312 }
313
314 /*
315 * Required by RFC 3315, section 15.
316 */
317 if (packet->unicast) {
318 log_debug("Discarding %s from %s; packet sent unicast "
319 "(CLIENTID %s, SERVERID %s)",
320 dhcpv6_type_names[packet->dhcpv6_msg_type],
321 piaddr(packet->client_addr),
322 print_hex_1(client_id->len, client_id->data, 60),
323 print_hex_2(data.len, data.data, 60));
324 goto exit;
325 }
326
327
328 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
329 if (oc != NULL) {
330 if (evaluate_option_cache(&data, packet, NULL, NULL,
331 packet->options, NULL,
332 &global_scope, oc, MDL)) {
333 log_debug("Discarding %s from %s; "
334 "server identifier found "
335 "(CLIENTID %s, SERVERID %s)",
336 dhcpv6_type_names[packet->dhcpv6_msg_type],
337 piaddr(packet->client_addr),
338 print_hex_1(client_id->len,
339 client_id->data, 60),
340 print_hex_2(data.len,
341 data.data, 60));
342 } else {
343 log_debug("Discarding %s from %s; "
344 "server identifier found "
345 "(CLIENTID %s)",
346 dhcpv6_type_names[packet->dhcpv6_msg_type],
347 print_hex_1(client_id->len,
348 client_id->data, 60),
349 piaddr(packet->client_addr));
350 }
351 goto exit;
352 }
353
354 /* looks good */
355 ret_val = 1;
356
357exit:
358 if (data.len > 0) {
359 data_string_forget(&data, MDL);
360 }
361 if (!ret_val) {
362 if (client_id->len > 0) {
363 data_string_forget(client_id, MDL);
364 }
365 }
366 return ret_val;
367}
368
369/*
370 * Response validation, defined in RFC 3315, sections 15.4, 15.6, 15.8,
371 * 15.9 (slightly different wording, but same meaning):
372 *
373 * Servers MUST discard any received Request message that meet any of
374 * the following conditions:
375 *
376 * - the message does not include a Server Identifier option.
377 * - the contents of the Server Identifier option do not match the
378 * server's DUID.
379 * - the message does not include a Client Identifier option.
380 */
381int
382valid_client_resp(struct packet *packet,
383 struct data_string *client_id,
384 struct data_string *server_id) {
385 int ret_val;
386 struct option_cache *oc;
387
388 /* INSIST((duid.data != NULL) && (duid.len > 0)); */
389
390 ret_val = 0;
391 memset(client_id, 0, sizeof(*client_id));
392 memset(server_id, 0, sizeof(*server_id));
393
394 switch (get_client_id(packet, client_id)) {
395 case ISC_R_SUCCESS:
396 break;
397 case ISC_R_NOTFOUND:
398 log_debug("Discarding %s from %s; "
399 "client identifier missing",
400 dhcpv6_type_names[packet->dhcpv6_msg_type],
401 piaddr(packet->client_addr));
402 goto exit;
403 default:
404 log_error("Error processing %s from %s; "
405 "unable to evaluate Client Identifier",
406 dhcpv6_type_names[packet->dhcpv6_msg_type],
407 piaddr(packet->client_addr));
408 goto exit;
409 }
410
411 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
412 if (oc == NULL) {
413 log_debug("Discarding %s from %s: "
414 "server identifier missing (CLIENTID %s)",
415 dhcpv6_type_names[packet->dhcpv6_msg_type],
416 piaddr(packet->client_addr),
417 print_hex_1(client_id->len, client_id->data, 60));
418 goto exit;
419 }
420 if (!evaluate_option_cache(server_id, packet, NULL, NULL,
421 packet->options, NULL,
422 &global_scope, oc, MDL)) {
423 log_error("Error processing %s from %s; "
424 "unable to evaluate Server Identifier (CLIENTID %s)",
425 dhcpv6_type_names[packet->dhcpv6_msg_type],
426 piaddr(packet->client_addr),
427 print_hex_1(client_id->len, client_id->data, 60));
428 goto exit;
429 }
430 if ((server_duid.len != server_id->len) ||
431 (memcmp(server_duid.data, server_id->data, server_duid.len) != 0)) {
432 log_debug("Discarding %s from %s; "
433 "not our server identifier "
434 "(CLIENTID %s, SERVERID %s, server DUID %s)",
435 dhcpv6_type_names[packet->dhcpv6_msg_type],
436 piaddr(packet->client_addr),
437 print_hex_1(client_id->len, client_id->data, 60),
438 print_hex_2(server_id->len, server_id->data, 60),
439 print_hex_3(server_duid.len, server_duid.data, 60));
440 goto exit;
441 }
442
443 /* looks good */
444 ret_val = 1;
445
446exit:
447 if (!ret_val) {
448 if (server_id->len > 0) {
449 data_string_forget(server_id, MDL);
450 }
451 if (client_id->len > 0) {
452 data_string_forget(client_id, MDL);
453 }
454 }
455 return ret_val;
456}
457
458/*
459 * Information request validation, defined in RFC 3315, section 15.12:
460 *
461 * Servers MUST discard any received Information-request message that
462 * meets any of the following conditions:
463 *
464 * - The message includes a Server Identifier option and the DUID in
465 * the option does not match the server's DUID.
466 *
467 * - The message includes an IA option.
468 */
469int
470valid_client_info_req(struct packet *packet, struct data_string *server_id) {
471 int ret_val;
472 struct option_cache *oc;
473
474 /* INSIST((duid.data != NULL) && (duid.len > 0)); */
475
476 ret_val = 0;
477 memset(server_id, 0, sizeof(*server_id));
478
479 /*
480 * Required by RFC 3315, section 15.
481 */
482 if (packet->unicast) {
483 log_debug("Discarding %s from %s; "
484 "IA_NA option present",
485 dhcpv6_type_names[packet->dhcpv6_msg_type],
486 piaddr(packet->client_addr));
487 goto exit;
488 }
489
490 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
491 if (oc != NULL) {
492 log_debug("Discarding %s from %s; "
493 "IA_NA option present",
494 dhcpv6_type_names[packet->dhcpv6_msg_type],
495 piaddr(packet->client_addr));
496 goto exit;
497 }
498 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
499 if (oc != NULL) {
500 log_debug("Discarding %s from %s; "
501 "IA_TA option present",
502 dhcpv6_type_names[packet->dhcpv6_msg_type],
503 piaddr(packet->client_addr));
504 goto exit;
505 }
506
507 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
508 if (oc != NULL) {
509 if (!evaluate_option_cache(server_id, packet, NULL, NULL,
510 packet->options, NULL,
511 &global_scope, oc, MDL)) {
512 log_error("Error processing %s from %s; "
513 "unable to evaluate Server Identifier",
514 dhcpv6_type_names[packet->dhcpv6_msg_type],
515 piaddr(packet->client_addr));
516 goto exit;
517 }
518 if ((server_duid.len != server_id->len) ||
519 (memcmp(server_duid.data, server_id->data,
520 server_duid.len) != 0)) {
521 log_debug("Discarding %s from %s; "
522 "not our server identifier "
523 "(SERVERID %s, server DUID %s)",
524 dhcpv6_type_names[packet->dhcpv6_msg_type],
525 piaddr(packet->client_addr),
526 print_hex_1(server_id->len,
527 server_id->data, 60),
528 print_hex_2(server_duid.len,
529 server_duid.data, 60));
530 goto exit;
531 }
532 }
533
534 /* looks good */
535 ret_val = 1;
536
537exit:
538 if (!ret_val) {
539 if (server_id->len > 0) {
540 data_string_forget(server_id, MDL);
541 }
542 }
543 return ret_val;
544}
545
546/*
547 * Options that we want to send, in addition to what was requested
548 * via the ORO.
549 */
550static const int required_opts[] = {
551 D6O_CLIENTID,
552 D6O_SERVERID,
553 D6O_STATUS_CODE,
554 0
555};
556static const int required_opts_solicit[] = {
557 D6O_CLIENTID,
558 D6O_SERVERID,
559 D6O_IA_NA,
560 D6O_IA_TA,
561 D6O_RAPID_COMMIT,
562 D6O_STATUS_CODE,
563 D6O_VENDOR_OPTS,
564 D6O_RECONF_ACCEPT,
565 0
566};
567static const int required_opts_IA_NA[] = {
568 D6O_IAADDR,
569 D6O_STATUS_CODE,
570 D6O_VENDOR_OPTS,
571 0
572};
573static const int required_opts_STATUS_CODE[] = {
574 D6O_STATUS_CODE,
575 0
576};
577
578/*
579 * Creates an option state and data string, based on the packet contents,
580 * and the specific option defined in the option cache.
581 */
582static int
583get_encapsulated_IA_state(struct option_state **enc_opt_state,
584 struct data_string *enc_opt_data,
585 struct packet *packet,
586 struct option_cache *oc) {
587
588 /*
589 * Get the raw data for the encapsulated options.
590 */
591 memset(enc_opt_data, 0, sizeof(*enc_opt_data));
592 if (!evaluate_option_cache(enc_opt_data, packet,
593 NULL, NULL, packet->options, NULL,
594 &global_scope, oc, MDL)) {
595 log_error("get_encapsulated_IA_state: "
596 "error evaluating raw option.");
597 return 0;
598 }
599 if (enc_opt_data->len < 12) {
600 log_error("get_encapsulated_IA_state: raw option too small.");
601 data_string_forget(enc_opt_data, MDL);
602 return 0;
603 }
604
605 /*
606 * Now create the option state structure, and pass it to the
607 * function that parses options.
608 */
609 *enc_opt_state = NULL;
610 if (!option_state_allocate(enc_opt_state, MDL)) {
611 log_error("get_encapsulated_IA_state: no memory for options.");
612 data_string_forget(enc_opt_data, MDL);
613 return 0;
614 }
615 if (!parse_option_buffer(*enc_opt_state,
616 enc_opt_data->data+12,
617 enc_opt_data->len-12,
618 &dhcpv6_universe)) {
619 log_error("get_encapsulated_IA_state: error parsing options.");
620 option_state_dereference(enc_opt_state, MDL);
621 data_string_forget(enc_opt_data, MDL);
622 return 0;
623 }
624
625 return 1;
626}
627
628static int
629set_status_code(u_int16_t status_code, const char *status_message,
630 struct option_state *opt_state) {
631 struct data_string d;
632 int ret_val;
633
634 memset(&d, 0, sizeof(d));
635 d.len = sizeof(status_code) + strlen(status_message);
636 if (!buffer_allocate(&d.buffer, d.len, MDL)) {
637 log_fatal("set_status_code: no memory for status code.");
638 }
639 d.data = d.buffer->data;
640 putUShort(d.buffer->data, status_code);
641 memcpy(d.buffer->data + sizeof(status_code),
642 status_message, d.len - sizeof(status_code));
643 if (!save_option_buffer(&dhcpv6_universe, opt_state,
28868515 644 d.buffer, (unsigned char *)d.data, d.len,
98bd7ca0
DH
645 D6O_STATUS_CODE, 0)) {
646 log_error("set_status_code: error saving status code.");
647 ret_val = 0;
648 } else {
649 ret_val = 1;
650 }
651 data_string_forget(&d, MDL);
652 return ret_val;
653}
654
655/*
656 * We have a set of operations we do to set up the reply packet, which
657 * is the same for many message types.
658 */
659static int
660start_reply(struct packet *packet,
661 const struct data_string *client_id,
662 const struct data_string *server_id,
663 struct option_state **opt_state,
664 struct dhcpv6_packet *reply) {
665 struct option_cache *oc;
666 struct data_string server_oro;
28868515 667 const unsigned char *server_id_data;
98bd7ca0
DH
668 int server_id_len;
669
670 reply->msg_type = DHCPV6_REPLY;
671
672 /*
673 * Use the client's transaction identifier for the reply.
674 */
675 memcpy(reply->transaction_id, packet->dhcpv6_transaction_id,
676 sizeof(reply->transaction_id));
677
678 /*
679 * Build our option state for reply.
680 */
681 *opt_state = NULL;
682 if (!option_state_allocate(opt_state, MDL)) {
683 log_error("start_reply: no memory for option_state.");
684 return 0;
685 }
686 execute_statements_in_scope(NULL, packet, NULL, NULL,
687 packet->options, *opt_state,
688 &global_scope, root_group, NULL);
689
690 /*
691 * RFC 3315, section 18.2 says we need server identifier and
692 * client identifier.
693 *
694 * If the server ID is defined via the configuration file, then
695 * it will already be present in the option state at this point,
696 * so we don't need to set it.
697 *
698 * If we have a server ID passed in from the caller,
699 * use that, otherwise use the global DUID.
700 */
701 oc = lookup_option(&dhcpv6_universe, *opt_state, D6O_SERVERID);
702 if (oc == NULL) {
703 if (server_id == NULL) {
28868515 704 server_id_data = server_duid.data;
98bd7ca0
DH
705 server_id_len = server_duid.len;
706 } else {
28868515 707 server_id_data = server_id->data;
98bd7ca0
DH
708 server_id_len = server_id->len;
709 }
710 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
28868515
SK
711 NULL, (unsigned char *)server_id_data,
712 server_id_len, D6O_SERVERID, 0)) {
98bd7ca0
DH
713 log_error("start_reply: "
714 "error saving server identifier.");
715 return 0;
716 }
717 }
718
719 if (client_id->buffer != NULL) {
720 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
721 client_id->buffer,
722 (unsigned char *)client_id->data,
723 client_id->len,
724 D6O_CLIENTID, 0)) {
725 log_error("start_reply: error saving "
726 "client identifier.");
727 return 0;
728 }
729 }
730
731 /*
732 * If the client accepts reconfiguration, let it know that we
733 * will send them.
734 *
735 * Note: we don't actually do this yet, but DOCSIS requires we
736 * claim to.
737 */
738 oc = lookup_option(&dhcpv6_universe, packet->options,
739 D6O_RECONF_ACCEPT);
740 if (oc != NULL) {
741 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
28868515
SK
742 NULL, (unsigned char *)"", 0,
743 D6O_RECONF_ACCEPT, 0)) {
98bd7ca0
DH
744 log_error("start_reply: "
745 "error saving RECONF_ACCEPT option.");
746 option_state_dereference(opt_state, MDL);
747 return 0;
748 }
749 }
750
751 /*
752 * Set the ORO for the main packet.
753 */
754 build_server_oro(&server_oro, *opt_state, MDL);
755 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
28868515
SK
756 server_oro.buffer,
757 (unsigned char *)server_oro.data,
98bd7ca0
DH
758 server_oro.len, D6O_ORO, 0)) {
759 log_error("start_reply: error saving server ORO.");
760 data_string_forget(&server_oro, MDL);
761 option_state_dereference(opt_state, MDL);
762 return 0;
763 }
764 data_string_forget(&server_oro, MDL);
765
766 return 1;
767}
768
769/*
770 * Try to get the IPv6 address the client asked for from the
771 * pool.
772 *
773 * addr is the result (should be a pointer to NULL on entry)
774 * pool is the pool to search in
775 * requested_addr is the address the client wants
776 */
777static isc_result_t
778try_client_v6_address(struct iaaddr **addr,
779 struct ipv6_pool *pool,
780 const struct data_string *requested_addr) {
781 struct in6_addr tmp_addr;
782 isc_result_t result;
98bd7ca0
DH
783
784 if (requested_addr->len < sizeof(tmp_addr)) {
785 return ISC_R_INVALIDARG;
786 }
787 memcpy(&tmp_addr, requested_addr->data, sizeof(tmp_addr));
788 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
789 return ISC_R_FAILURE;
790 }
791
792 if (!ipv6_addr_in_pool(&tmp_addr, pool)) {
793 return ISC_R_FAILURE;
794 }
795
796 if (lease6_exists(pool, &tmp_addr)) {
797 return ISC_R_ADDRINUSE;
798 }
799
800 result = iaaddr_allocate(addr, MDL);
801 if (result != ISC_R_SUCCESS) {
802 return result;
803 }
804 (*addr)->addr = tmp_addr;
805
806 result = add_lease6(pool, *addr, 0);
807 if (result != ISC_R_SUCCESS) {
808 iaaddr_dereference(addr, MDL);
809 }
810 return result;
811}
812
813/*
814 * Get an IPv6 address for the client.
815 *
816 * addr is the result (should be a pointer to NULL on entry)
817 * packet is the information about the packet from the client
818 * requested_iaaddr is a hint from the client
819 * client_id is the DUID for the client
820 */
821static isc_result_t
822pick_v6_address(struct iaaddr **addr,
823 struct ipv6_pool **pool,
824 struct packet *packet,
825 const struct data_string *requested_iaaddr,
826 const struct data_string *client_id) {
827 const struct packet *chk_packet;
828 const struct in6_addr *link_addr;
829 const struct in6_addr *first_link_addr;
830 struct iaddr tmp_addr;
831 struct subnet *subnet;
832 struct shared_network *shared_network;
833 struct ipv6_pool *p;
834 int i;
835 int start_pool;
28868515 836 unsigned int attempts;
98bd7ca0
DH
837
838 /*
839 * First, find the link address where the packet from the client
840 * first appeared.
841 */
842 first_link_addr = NULL;
843 chk_packet = packet->dhcpv6_container_packet;
844 while (chk_packet != NULL) {
845 link_addr = &chk_packet->dhcpv6_link_address;
846 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
847 !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
848 first_link_addr = link_addr;
849 }
850 chk_packet = chk_packet->dhcpv6_container_packet;
851 }
852
853 /*
854 * If there is a link address, find the subnet associated
855 * with that, and use that to get the appropriate
856 * shared_network.
857 */
858 if (first_link_addr != NULL) {
859 tmp_addr.len = sizeof(*first_link_addr);
860 memcpy(tmp_addr.iabuf,
861 first_link_addr, sizeof(*first_link_addr));
862 subnet = NULL;
863 if (!find_subnet(&subnet, tmp_addr, MDL)) {
864 log_debug("No subnet found for link-address %s.",
865 piaddr(tmp_addr));
866 return ISC_R_NOTFOUND;
867 }
868 shared_network = NULL;
869 shared_network_reference(&shared_network,
870 subnet->shared_network, MDL);
871 subnet_dereference(&subnet, MDL);
872 }
873
874 /*
875 * If there is no link address, we will use the interface
876 * that this packet came in on to pick the shared_network.
877 */
878 else {
879 shared_network = NULL;
880 shared_network_reference(&shared_network,
881 packet->interface->shared_network,
882 MDL);
883 }
884
885 /*
886 * No pools, we're done.
887 */
888 if (shared_network->ipv6_pools == NULL) {
889 shared_network_dereference(&shared_network, MDL);
890 return ISC_R_NORESOURCES;
891 }
892
893 /*
894 * If the client requested an address, try each subnet to see
895 * if the address is available in that subnet. We will try to
896 * respect the client's request if possible.
897 */
898 if ((requested_iaaddr != NULL) && (requested_iaaddr->len > 0)) {
899 for (i=0; shared_network->ipv6_pools[i] != NULL; i++) {
900 p = shared_network->ipv6_pools[i];
901 if (try_client_v6_address(addr, p, requested_iaaddr)
902 == ISC_R_SUCCESS) {
903 ipv6_pool_reference(pool, p, MDL);
904 shared_network_dereference(&shared_network,
905 MDL);
906 return ISC_R_SUCCESS;
907 }
908 }
909 }
910
911 /*
912 * Otherwise try to get a lease from the first subnet possible.
913 *
914 * We start looking at the last pool we allocated from, unless
915 * it had a collision trying to allocate an address. This will
916 * tend to move us into less-filled pools.
917 */
918 start_pool = shared_network->last_ipv6_pool;
919 i = start_pool;
920 do {
921
922 p = shared_network->ipv6_pools[i];
923 if (activate_lease6(p, addr, &attempts,
924 client_id, 0) == ISC_R_SUCCESS) {
925 ipv6_pool_reference(pool, p, MDL);
926
927 /*
928 * Record the pool used (or next one if there
929 * was a collision).
930 */
931 if (attempts > 1) {
932 i++;
933 if (shared_network->ipv6_pools[i] == NULL) {
934 i = 0;
935 }
936 }
937 shared_network->last_ipv6_pool = i;
938
939 shared_network_dereference(&shared_network, MDL);
940 return ISC_R_SUCCESS;
941 }
942
943 i++;
944 if (shared_network->ipv6_pools[i] == NULL) {
945 i = 0;
946 }
947 } while (i != start_pool);
948
949 /*
950 * If we failed to pick an IPv6 address from any of the subnets.
951 * Presumably that means we have no addresses for the client.
952 */
953 shared_network_dereference(&shared_network, MDL);
954 return ISC_R_NORESOURCES;
955}
956
957/* TODO: IA_TA */
958/* TODO: look at client hints for lease times */
959/* XXX: need to add IA_NA to our ORO? */
960static void
961lease_to_client(struct data_string *reply_ret,
962 struct packet *packet,
963 const struct data_string *client_id,
964 const struct data_string *server_id) {
965 struct option_cache *oc;
966 struct data_string packet_oro;
967 struct host_decl *packet_host;
968 int matched_packet_host;
969 struct option_cache *ia;
98bd7ca0
DH
970 char reply_data[65536];
971 struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
972 int reply_ofs = (int)((char *)reply->options - (char *)reply);
973 struct option_state *opt_state;
974 struct host_decl *host;
975 struct option_state *host_opt_state;
976 /* cli_enc_... variables come from the IA_NA/IA_TA options */
977 struct data_string cli_enc_opt_data;
978 struct option_state *cli_enc_opt_state;
979 u_int32_t preferred_lifetime;
980 u_int32_t valid_lifetime;
981 struct data_string iaaddr;
982 struct data_string fixed_addr;
983 struct data_string d;
984 u_int16_t len;
985 u_int32_t t1, t2;
986 struct host_decl *save_host;
987 char zeros[24];
988 struct ipv6_pool *pool;
989 struct iaaddr *lease;
990 struct group *group;
991 u_int32_t iaid;
992 struct ia_na *ia_na;
993 struct ia_na *existing_ia_na;
d9b43370 994 struct ia_na *old_ia_na;
98bd7ca0
DH
995 int i;
996
997 /*
998 * Initialize to empty values, in case we have to exit early.
999 */
1000 opt_state = NULL;
1001 memset(&packet_oro, 0, sizeof(packet_oro));
1002 memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
1003 cli_enc_opt_state = NULL;
1004 host_opt_state = NULL;
1005 memset(&fixed_addr, 0, sizeof(fixed_addr));
1006 memset(&iaaddr, 0, sizeof(iaaddr));
1007 ia_na = NULL;
1008 lease = NULL;
1009
1010 /*
1011 * Set up reply.
1012 */
1013 if (!start_reply(packet, client_id, NULL, &opt_state, reply)) {
1014 goto exit;
1015 }
1016
1017 /*
1018 * Get the ORO from the packet, if any.
1019 */
1020 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ORO);
1021 if (oc != NULL) {
1022 if (!evaluate_option_cache(&packet_oro, packet,
1023 NULL, NULL,
1024 packet->options, NULL,
1025 &global_scope, oc, MDL)) {
1026 log_error("lease_to_client: error evaluating ORO.");
1027 goto exit;
1028 }
1029 }
1030
1031 /*
1032 * A small bit of special handling for Solicit messages.
1033 *
1034 * We could move the logic into a flag, but for now just check
1035 * explicitly.
1036 */
1037 if (packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
1038
1039 reply->msg_type = DHCPV6_ADVERTISE;
1040
1041 /*
1042 * If:
1043 * - this message type supports rapid commit (Solicit), and
1044 * - the server is configured to supply a rapid commit, and
1045 * - the client requests a rapid commit,
1046 * Then we add a rapid commit option, and send Reply (instead
1047 * of an Advertise).
1048 */
1049 oc = lookup_option(&dhcpv6_universe,
1050 opt_state, D6O_RAPID_COMMIT);
1051 if (oc != NULL) {
1052 oc = lookup_option(&dhcpv6_universe,
1053 packet->options, D6O_RAPID_COMMIT);
1054 if (oc != NULL) {
1055 if (!save_option_buffer(&dhcpv6_universe,
28868515
SK
1056 opt_state, NULL,
1057 (unsigned char *)"", 0,
98bd7ca0
DH
1058 D6O_RAPID_COMMIT, 0)) {
1059 log_error("start_reply: error saving "
1060 "RAPID_COMMIT option.");
1061 goto exit;
1062 }
1063
1064 reply->msg_type = DHCPV6_REPLY;
1065 }
1066 }
1067
1068 }
1069
1070
1071
1072 /*
1073 * Find the host record that matches from the packet, if any.
1074 */
1075 packet_host = NULL;
1076 if (!find_hosts_by_option(&packet_host, packet, packet->options, MDL)) {
1077 packet_host = NULL;
1078 /*
1079 * If we don't have a match from the packet contents,
1080 * see if we can match by UID.
1081 */
1082 if (!find_hosts_by_uid(&packet_host,
1083 client_id->data, client_id->len, MDL)) {
1084 packet_host = NULL;
1085 }
1086 }
1087 matched_packet_host = 0;
1088
1089 /*
1090 * Add our options that are not associated with any IA_NA or IA_TA.
1091 */
1092 reply_ofs += store_options6(reply_data+reply_ofs,
1093 sizeof(reply_data)-reply_ofs,
1094 opt_state, packet,
1095 required_opts_solicit, &packet_oro);
1096
1097 /*
1098 * Now loop across each IA_NA that we have.
1099 */
1100 ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
1101 while (ia != NULL) {
1102 /*
1103 * T1 and T2, set to 0 means the client can choose.
1104 *
1105 * We will adjust this based on preferred and valid
1106 * times if we have an address.
1107 */
1108 t1 = 0;
1109 t2 = 0;
1110
1111 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
1112 &cli_enc_opt_data,
1113 packet, ia)) {
1114 goto exit;
1115 }
1116
1117 /*
1118 * Create an IA_NA structure.
1119 */
1120 iaid = getULong(cli_enc_opt_data.data);
1121 ia_na = NULL;
28868515 1122 if (ia_na_allocate(&ia_na, iaid, (char *)client_id->data,
98bd7ca0
DH
1123 client_id->len, MDL) != ISC_R_SUCCESS) {
1124 log_fatal("lease_to_client: no memory for ia_na.");
1125 }
1126
1127 /*
1128 * Create state for this IA_NA.
1129 */
1130 host_opt_state = NULL;
1131 if (!option_state_allocate(&host_opt_state, MDL)) {
1132 log_error("lease_to_client: out of memory "
1133 "allocating option_state.");
1134 goto exit;
1135 }
1136
1137 /*
1138 * See if this NA has an address. If so, we use it
1139 * when trying to find a matching host record.
1140 */
1141 memset(&iaaddr, 0, sizeof(iaaddr));
1142 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
1143 D6O_IAADDR);
1144 if (oc != NULL) {
1145 /*
1146 * TODO: Check that the address is on one of
1147 * the networks that we have, and issue
1148 * NotOnLink if not (for Solicit/Request),
1149 * or remember to set the address lifetime
1150 * to 0 (for Renew/Rebind).
1151 */
1152 if (!evaluate_option_cache(&iaaddr, packet,
1153 NULL, NULL,
1154 packet->options,
1155 NULL, &global_scope,
1156 oc, MDL)) {
1157 log_error("lease_to_client: "
1158 "error evaluating IAADDR.");
1159 goto exit;
1160 }
1161 /*
1162 * Clients may choose to send :: as an address,
1163 * with the idea to give hints about
1164 * preferred-lifetime or valid-lifetime.
1165 *
1166 * We ignore this.
1167 */
1168 memset(zeros, 0, sizeof(zeros));
1169 if ((iaaddr.len >= 24) &&
1170 !memcmp(iaaddr.data, zeros, 16)) {
1171 data_string_forget(&iaaddr, MDL);
1172 }
1173 }
1174
1175 /*
1176 * Now we need to figure out which host record matches
1177 * this IA_NA.
1178 *
1179 * We first try matching the encapsulated option state.
1180 * If nothing is there, then we will use the host entry
1181 * matched from the non-encapsulated option state, if
1182 * there was one.
1183 *
1184 * We will only use this host entry for one of the
1185 * IA_NA in the packet, to avoid having the same address
1186 * on multiple interfaces.
1187 */
1188 host = NULL;
1189 if (!find_hosts_by_option(&host, packet,
1190 cli_enc_opt_state, MDL)) {
1191 if ((packet_host != NULL) && !matched_packet_host) {
1192 matched_packet_host = 1;
1193 host = packet_host;
1194 } else {
1195 host = NULL;
1196 }
1197 }
1198
1199 if (iaaddr.len == 0) {
1200 /*
1201 * Client did not specify the IAADDR to use.
1202 *
1203 * If we are renewing, this is a problem. Set
1204 * to no host, and this will cause the appropriate
1205 * response to be sent.
1206 *
1207 * Otherwise, we simply find the first matching host.
1208 */
1209 if (packet->dhcpv6_msg_type == DHCPV6_RENEW) {
1210 host = NULL;
1211 } else {
1212 while ((host != NULL) &&
1213 (host->fixed_addr == NULL)) {
1214 host = host->n_ipaddr;
1215 }
1216 }
1217 } else {
1218 /*
1219 * Client wanted a specific IAADDR, so we will
1220 * only accept a host entry that matches.
1221 */
1222 save_host = host;
1223 for (; host != NULL; host = host->n_ipaddr) {
1224 if (host->fixed_addr == NULL) {
1225 continue;
1226 }
1227 if (!evaluate_option_cache(&fixed_addr, NULL,
1228 NULL, NULL, NULL,
1229 NULL, &global_scope,
1230 host->fixed_addr,
1231 MDL)) {
1232 log_error("lease_to_client: error "
1233 "evaluating host address.");
1234 goto exit;
1235 }
1236 if ((iaaddr.len >= 16) &&
1237 !memcmp(fixed_addr.data, iaaddr.data, 16)) {
1238 data_string_forget(&fixed_addr, MDL);
1239 break;
1240 }
1241 data_string_forget(&fixed_addr, MDL);
1242 }
1243 /*
1244 * If we got a Solicit and don't have a matching
1245 * host record, have gotten a bad hint.
1246 * Pick a host record.
1247 */
1248 if ((host == NULL) &&
1249 (packet->dhcpv6_msg_type == DHCPV6_SOLICIT)) {
1250 host = save_host;
1251 while ((host != NULL) &&
1252 (host->fixed_addr == NULL)) {
1253 host = host->n_ipaddr;
1254 }
1255 }
1256 }
1257
1258 /*
1259 * At this point, if we don't have a host entry,
1260 * try to find the appropriate pool for this IA.
1261 */
1262 group = NULL;
1263 lease = NULL;
1264 if (host != NULL) {
1265 group = host->group;
1266 } else if (num_pools > 0) {
1267 struct iaaddr *tmp;
1268 struct in6_addr *in6_addr;
1269
1270 /*
1271 * Find existing IA_NA.
1272 */
1273 existing_ia_na = NULL;
1274 if (ia_na_hash_lookup(&existing_ia_na, ia_active,
28868515
SK
1275 (unsigned char *)
1276 ia_na->iaid_duid.data,
98bd7ca0
DH
1277 ia_na->iaid_duid.len, MDL) == 0) {
1278 existing_ia_na = NULL;
1279 }
1280
1281 /*
1282 * If there are no addresses, we'll ignore this IA_NA.
1283 */
1284 if ((existing_ia_na != NULL) &&
1285 (existing_ia_na->num_iaaddr == 0)) {
1286 existing_ia_na = NULL;
1287 }
1288
1289 /*
1290 * If we have this IA_NA, then use that.
1291 */
1292 if ((iaaddr.len == 0) && (existing_ia_na != NULL)) {
1293 /*
1294 * If the client doesn't ask for a specific
1295 * address, we're cool.
1296 */
1297 tmp = existing_ia_na->iaaddr[0];
1298 pool = NULL;
1299 ipv6_pool_reference(&pool, tmp->ipv6_pool, MDL);
1300 iaaddr_reference(&lease, tmp, MDL);
1301 } else if (existing_ia_na != NULL) {
1302 /*
1303 * Make sure this address is in the IA_NA.
1304 */
1305 pool = NULL;
1306 for (i=0; i<existing_ia_na->num_iaaddr; i++) {
1307 tmp = existing_ia_na->iaaddr[i];
1308 in6_addr = &tmp->addr;
1309 if (memcmp(in6_addr,
1310 iaaddr.data, 16) == 0) {
1311 ipv6_pool_reference(&pool,
1312 tmp->ipv6_pool, MDL);
1313 iaaddr_reference(&lease,
1314 tmp, MDL);
1315 break;
1316 }
1317 }
1318
1319 /*
1320 * If we didn't find a pool it means that the
1321 * client sent an address we don't know about
1322 * and we'll consider it a non-match.
1323 */
1324 if (pool == NULL) {
1325 existing_ia_na = NULL;
1326 }
1327 }
1328
1329 /*
1330 * If we don't have a matching IA_NA for this
1331 * client, then we need to get a new address.
1332 */
1333 if (existing_ia_na == NULL) {
1334 pool = NULL;
1335 pick_v6_address(&lease, &pool, packet,
1336 &iaaddr, client_id);
1337 }
1338
1339 /*
1340 * If we got an address, get our group information
1341 * from the pool used.
1342 */
1343 if (pool != NULL) {
1344 group = pool->shared_network->group;
1345 }
1346 }
1347
1348 /*
1349 * Get the lease time from the group.
1350 */
1351 if (group != NULL) {
1352 /*
1353 * Execute statements for the host's group.
1354 */
1355 execute_statements_in_scope(NULL, packet, NULL, NULL,
1356 packet->options,
1357 host_opt_state,
1358 &global_scope,
1359 group, root_group);
1360 /*
1361 * Get our lease time. Note that "preferred lifetime"
1362 * and "valid lifetime" are defined in RFC 2462.
1363 */
1364 oc = lookup_option(&server_universe, opt_state,
1365 SV_DEFAULT_LEASE_TIME);
1366 valid_lifetime = DEFAULT_DEFAULT_LEASE_TIME;
1367 if (oc != NULL) {
1368 memset(&d, 0, sizeof(d));
1369 if (!evaluate_option_cache(&d, packet, NULL,
1370 NULL,
1371 packet->options,
1372 opt_state,
1373 &global_scope,
1374 oc, MDL)) {
1375 log_error("lease_to_client: error "
1376 "getting lease time, "
1377 "using default.");
1378 } else {
1379 /* INSIST(d.len == 4); */
1380 valid_lifetime = getULong(d.data);
1381 data_string_forget(&d, MDL);
1382 }
1383 }
1384
1385 /*
1386 * T1: RENEW time.
1387 * T2: REBIND time.
1388 * preferred: 'deprecate' address.
1389 * valid: address expires.
1390 *
1391 * Values are required for valid and preferred
1392 * lifetimes. T1 and T2, if zero, will allow
1393 * the client to select their own behaviour.
1394 */
1395 t1 = t2 = 0;
1396 /* XXX: This is more than a little weird. */
1397 oc = lookup_option(&dhcp_universe, opt_state,
1398 DHO_DHCP_RENEWAL_TIME);
1399 if (oc != NULL) {
1400 memset(&d, 0, sizeof(d));
1401 if (!evaluate_option_cache(&d, packet, NULL,
1402 NULL,
1403 packet->options,
1404 opt_state,
1405 &global_scope,
1406 oc, MDL)) {
1407 /* XXX: I think there are already log
1408 * lines by this point.
1409 */
1410 log_error("lease_to_client: error "
1411 "evaluating renew time, "
1412 "defaulting to 0");
1413 } else {
1414 t1 = getULong(d.data);
1415 data_string_forget(&d, MDL);
1416 }
1417 }
1418
1419 oc = lookup_option(&dhcp_universe, opt_state,
1420 DHO_DHCP_REBINDING_TIME);
1421 if (oc != NULL) {
1422 memset(&d, 0, sizeof(d));
1423 if (!evaluate_option_cache(&d, packet, NULL,
1424 NULL,
1425 packet->options,
1426 opt_state,
1427 &global_scope,
1428 oc, MDL)) {
1429 /* XXX: I think there are already log
1430 * lines by this point.
1431 */
1432 log_error("lease_to_client: error "
1433 "evaluating rebinding "
1434 "time, defaulting to 0");
1435 } else {
1436 t2 = getULong(d.data);
1437 data_string_forget(&d, MDL);
1438 }
1439 }
1440
1441 preferred_lifetime = t1 + t2;
1442
1443 if (preferred_lifetime == 0 ||
1444 preferred_lifetime >= valid_lifetime)
1445 preferred_lifetime = (valid_lifetime / 2) +
1446 (valid_lifetime / 4);
1447
1448 oc = lookup_option(&server_universe, opt_state,
1449 SV_PREFER_LIFETIME);
1450 if (oc != NULL) {
1451 memset(&d, 0, sizeof(d));
1452 if (!evaluate_option_cache(&d, packet, NULL,
1453 NULL,
1454 packet->options,
1455 opt_state,
1456 &global_scope,
1457 oc, MDL)) {
1458 /* XXX: I think there are already log
1459 * lines by this point.
1460 */
1461 log_error("lease_to_client: error "
1462 "evaluating preferred "
1463 "lifetime, defaulting to "
1464 "%d", preferred_lifetime);
1465 } else {
1466 preferred_lifetime = getULong(d.data);
1467 data_string_forget(&d, MDL);
1468 }
1469 }
1470 }
1471
1472 /*
1473 * Shift the lease to the right place, based on our timeout.
1474 */
1475 if (lease != NULL) {
1476 lease->valid_lifetime_end_time = valid_lifetime +
1477 cur_time;
1478 renew_lease6(pool, lease);
1479 }
1480
1481 /*
1482 * Get the address.
1483 */
1484 memset(&fixed_addr, 0, sizeof(fixed_addr));
1485 if (host != NULL) {
1486 if (!evaluate_option_cache(&fixed_addr, NULL, NULL,
1487 NULL, NULL, NULL,
1488 &global_scope,
1489 host->fixed_addr, MDL)) {
1490 log_error("lease_to_client: error "
1491 "evaluating host address.");
1492 goto exit;
1493 }
1494 if (fixed_addr.len != 16) {
1495 log_error("lease_to_client: invalid address "
1496 "length (%d)", fixed_addr.len);
1497 goto exit;
1498 }
1499 } else if (lease != NULL) {
1500 fixed_addr.len = 16;
1501 if (!buffer_allocate(&fixed_addr.buffer, 16, MDL)) {
1502 log_fatal("lease_to_client: no memory for "
1503 "address information.");
1504 }
1505 fixed_addr.data = fixed_addr.buffer->data;
1506 memcpy(fixed_addr.buffer->data, &lease->addr, 16);
1507 }
1508
1509 if (fixed_addr.len == 16) {
98bd7ca0
DH
1510 /*
1511 * Store the address.
1512 *
1513 * XXX: This should allow multiple addresses, rather
1514 * than only a single one!
1515 */
1516 memset(&d, 0, sizeof(d));
1517 d.len = 24; /* From RFC 3315, section 22.6 */
1518 if (!buffer_allocate(&d.buffer, d.len, MDL)) {
1519 log_fatal("lease_to_client: no memory for "
1520 "address information.");
1521 }
1522 d.data = d.buffer->data;
1523 memcpy(d.buffer->data, fixed_addr.data, 16);
1524 putULong(d.buffer->data+16, preferred_lifetime);
1525 putULong(d.buffer->data+20, valid_lifetime);
1526 data_string_forget(&fixed_addr, MDL);
1527 if (!save_option_buffer(&dhcpv6_universe,
1528 host_opt_state,
1529 d.buffer,
1530 d.buffer->data,
1531 d.len, D6O_IAADDR, 0)) {
1532 log_error("lease_to_client: error saving "
1533 "IAADDR.");
1534 data_string_forget(&d, MDL);
1535 goto exit;
1536 }
1537 data_string_forget(&d, MDL);
1538 }
1539
1540 if ((host != NULL) || (lease != NULL)) {
1541
1542 /*
1543 * Remember the client identifier so we can look
1544 * it up later.
1545 */
1546 if (host != NULL) {
28868515 1547 change_host_uid(host, (char *)client_id->data,
98bd7ca0
DH
1548 client_id->len);
1549 }
1550 /*
1551 * Otherwise save the IA_NA, for the same reason.
1552 */
1553 else if (packet->dhcpv6_msg_type != DHCPV6_SOLICIT) {
d9b43370
SK
1554 /*
1555 * Remove previous version of this IA_NA,
1556 * if one exists.
1557 */
1558 struct data_string *d = &ia_na->iaid_duid;
1559 old_ia_na = NULL;
1560 if (ia_na_hash_lookup(&old_ia_na, ia_active,
28868515 1561 (unsigned char *)d->data,
d9b43370
SK
1562 d->len, MDL)) {
1563 ia_na_hash_delete(ia_active,
28868515
SK
1564 (unsigned char *)
1565 d->data,
d9b43370
SK
1566 d->len, MDL);
1567 ia_na_dereference(&old_ia_na, MDL);
1568 }
1569
98bd7ca0
DH
1570 /*
1571 * ia_na_add_iaaddr() will reference the
1572 * lease, so we need to dereference the
1573 * previous reference to the lease if one
1574 * exists.
1575 */
1576 if (lease->ia_na != NULL) {
1577 ia_na_dereference(&lease->ia_na, MDL);
1578 }
1579 if (ia_na_add_iaaddr(ia_na, lease,
1580 MDL) != ISC_R_SUCCESS) {
1581 log_fatal("lease_to_client: out of "
1582 "memory adding IAADDR");
1583 }
1584 ia_na_hash_add(ia_active,
28868515
SK
1585 (unsigned char *)
1586 ia_na->iaid_duid.data,
98bd7ca0
DH
1587 ia_na->iaid_duid.len,
1588 ia_na, MDL);
1589 write_ia_na(ia_na);
d9b43370 1590 schedule_lease_timeout(lease->ipv6_pool);
98bd7ca0
DH
1591
1592 /* If this constitutes a binding, and we
1593 * are performing ddns updates, then give
1594 * ddns_updates() a chance to do its mojo.
1595 */
1596 if (((packet->dhcpv6_msg_type
1597 == DHCPV6_REQUEST) ||
1598 (packet->dhcpv6_msg_type
1599 == DHCPV6_RENEW) ||
1600 (packet->dhcpv6_msg_type
1601 == DHCPV6_REBIND)) &&
1602 (((oc = lookup_option(&server_universe,
1603 opt_state,
1604 SV_DDNS_UPDATES))
1605 == NULL) ||
1606 evaluate_boolean_option_cache(NULL,
1607 packet, NULL, NULL,
1608 packet->options, opt_state,
1609 &lease->scope, oc, MDL))) {
1610 ddns_updates(packet, NULL, NULL,
1611 lease, /* XXX */ NULL,
1612 opt_state);
1613 }
1614 }
1615
1616 } else {
1617
1618 /*
1619 * We send slightly different errors, depending on
1620 * whether the client is asking for a new address, or
1621 * attempting to renew an address it thinks it has.
1622 */
1623 if (packet->dhcpv6_msg_type == DHCPV6_REBIND) {
1624 if (iaaddr.len >= 24) {
1625 /*
1626 * If the we have a client address,
1627 * tell the client it is invalid.
1628 */
1629 memset(&d, 0, sizeof(d));
1630 d.len = 24;
1631 if (!buffer_allocate(&d.buffer,
1632 d.len, MDL)) {
1633 log_fatal("lease_to_client: "
1634 "no memory for "
1635 "address "
1636 "information.");
1637 }
1638 d.data = d.buffer->data;
1639 memcpy(d.buffer->data, iaaddr.data, 16);
1640 putULong(d.buffer->data+16, 0);
1641 putULong(d.buffer->data+20, 0);
1642 if (!save_option_buffer(
1643 &dhcpv6_universe,
1644 host_opt_state,
1645 d.buffer,
1646 d.buffer->data,
1647 d.len,
1648 D6O_IAADDR, 0)) {
1649 log_error("lease_to_client: "
1650 "error saving "
1651 "IAADDR.");
1652 data_string_forget(&d, MDL);
1653 goto exit;
1654 }
1655 data_string_forget(&d, MDL);
1656 } else {
1657 /*
1658 * Otherwise, this is an error.
1659 *
1660 * XXX: The other possibility is to
1661 * not say anything for this
1662 * IA, which might be more
1663 * correct. RFC 3315 does not
1664 * address this case.
1665 */
1666 if (!set_status_code(STATUS_UnspecFail,
1667 "Rebind requested without "
1668 "including an addresses.",
1669 host_opt_state)) {
1670 goto exit;
1671 }
1672 }
1673 } else if (packet->dhcpv6_msg_type == DHCPV6_RENEW) {
1674 if (!set_status_code(STATUS_NoBinding,
1675 "Address not bound "
1676 "to this interface.",
1677 host_opt_state)) {
1678 goto exit;
1679 }
1680 } else if ((iaaddr.len >= 24) &&
1681 (packet->dhcpv6_msg_type == DHCPV6_REQUEST)){
1682 if (!set_status_code(STATUS_NotOnLink,
1683 "Address not for "
1684 "use on this link.",
1685 host_opt_state)) {
1686 goto exit;
1687 }
1688 } else {
1689 if (!set_status_code(STATUS_NoAddrsAvail,
1690 "No addresses available "
1691 "for this interface.",
1692 host_opt_state)) {
1693 goto exit;
1694 }
1695 }
1696
1697 }
1698
1699 /*
1700 * Insure we have enough space
1701 */
1702 if (sizeof(reply_data) < (reply_ofs + 16)) {
1703 log_error("lease_to_client: "
1704 "out of space for reply packet.");
1705 goto exit;
1706 }
1707
1708 /*
1709 * Store the encapsulated option data for this IA_NA into
1710 * our reply packet.
1711 */
1712 len = store_options6(reply_data+reply_ofs+16,
1713 sizeof(reply_data)-reply_ofs-16,
1714 host_opt_state, packet,
1715 required_opts_IA_NA, NULL);
1716
1717 /*
1718 * Store the non-encapsulated option data for this IA_NA
1719 * into our reply packet. Defined in RFC 3315, section 22.4.
1720 */
1721 /* option number */
28868515 1722 putShort((unsigned char *)reply_data+reply_ofs, D6O_IA_NA);
98bd7ca0 1723 /* option length */
28868515 1724 putUShort((unsigned char *)reply_data+reply_ofs+2, len + 12);
98bd7ca0
DH
1725 /* IA_NA, copied from the client */
1726 memcpy(reply_data+reply_ofs+4, cli_enc_opt_data.data, 4);
1727 /* T1 and T2, set previously */
28868515
SK
1728 putULong((unsigned char *)reply_data+reply_ofs+8, t1);
1729 putULong((unsigned char *)reply_data+reply_ofs+12, t2);
98bd7ca0
DH
1730
1731 /*
1732 * Get ready for next IA_NA.
1733 */
1734 reply_ofs += (len + 16);
1735
1736 /*
1737 * Bit of cleanup.
1738 */
1739 if (lease != NULL) {
1740 iaaddr_dereference(&lease, MDL);
1741 }
1742 ia_na_dereference(&ia_na, MDL);
1743 if (iaaddr.data != NULL) {
1744 data_string_forget(&iaaddr, MDL);
1745 }
1746 option_state_dereference(&host_opt_state, MDL);
1747 option_state_dereference(&cli_enc_opt_state, MDL);
1748 data_string_forget(&cli_enc_opt_data, MDL);
1749 ia = ia->next;
1750 }
1751
1752 /*
1753 * Return our reply to the caller.
1754 */
1755 reply_ret->len = reply_ofs;
1756 reply_ret->buffer = NULL;
1757 if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
1758 log_fatal("No memory to store reply.");
1759 }
1760 reply_ret->data = reply_ret->buffer->data;
1761 memcpy(reply_ret->buffer->data, reply, reply_ofs);
1762
1763exit:
1764 if (lease != NULL) {
1765 iaaddr_dereference(&lease, MDL);
1766 }
1767 if (ia_na != NULL) {
1768 ia_na_dereference(&ia_na, MDL);
1769 }
1770 if (iaaddr.buffer != NULL) {
1771 data_string_forget(&iaaddr, MDL);
1772 }
1773 if (fixed_addr.buffer != NULL) {
1774 data_string_forget(&fixed_addr, MDL);
1775 }
1776 if (host_opt_state != NULL) {
1777 option_state_dereference(&host_opt_state, MDL);
1778 }
1779 if (cli_enc_opt_state != NULL) {
1780 option_state_dereference(&cli_enc_opt_state, MDL);
1781 }
1782 if (cli_enc_opt_data.buffer != NULL) {
1783 data_string_forget(&cli_enc_opt_data, MDL);
1784 }
1785 if (packet_oro.buffer != NULL) {
1786 data_string_forget(&packet_oro, MDL);
1787 }
1788 if (opt_state != NULL) {
1789 option_state_dereference(&opt_state, MDL);
1790 }
1791}
1792
1793/*
1794 * Solicit is how a client starts requesting addresses.
1795 *
1796 * If the client asks for rapid commit, and we support it, we will
1797 * allocate the addresses and reply.
1798 *
1799 * Otherwise we will send an advertise message.
1800 */
1801
1802/* TODO: discard unicast messages */
1803static void
1804dhcpv6_solicit(struct data_string *reply_ret, struct packet *packet) {
1805 struct data_string client_id;
98bd7ca0
DH
1806
1807 /*
1808 * Validate our input.
1809 */
1810 if (!valid_client_msg(packet, &client_id)) {
1811 return;
1812 }
1813
1814 lease_to_client(reply_ret, packet, &client_id, NULL);
1815
1816 /*
1817 * Clean up.
1818 */
1819 data_string_forget(&client_id, MDL);
1820}
1821
1822/*
1823 * Request is how a client actually requests addresses.
1824 *
1825 * Very similar to Solicit handling, except the server DUID is required.
1826 */
1827
1828/* TODO: discard unicast messages, unless we set unicast option */
1829static void
1830dhcpv6_request(struct data_string *reply_ret, struct packet *packet) {
1831 struct data_string client_id;
1832 struct data_string server_id;
1833
1834 /*
1835 * Validate our input.
1836 */
1837 if (!valid_client_resp(packet, &client_id, &server_id)) {
1838 return;
1839 }
1840
1841 /*
1842 * Issue our lease.
1843 */
1844 lease_to_client(reply_ret, packet, &client_id, &server_id);
1845
1846 /*
1847 * Cleanup.
1848 */
1849 data_string_forget(&client_id, MDL);
1850 data_string_forget(&server_id, MDL);
1851}
1852
1853/*
1854 * When a client thinks it might be on a new link, it sends a
1855 * Confirm message.
1856 */
1857
1858/* TODO: discard unicast messages, unless we set unicast option */
1859static void
1860dhcpv6_confirm(struct data_string *reply_ret, struct packet *packet) {
1861 struct data_string client_id;
1862 struct option_state *opt_state;
1863 char reply_data[65536];
1864 struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
1865 int reply_ofs = (int)((char *)reply->options - (char *)reply);
1866 struct option_cache *ia;
1867 struct option_cache *oc;
1868 /* cli_enc_... variables come from the IA_NA/IA_TA options */
1869 struct data_string cli_enc_opt_data;
1870 struct option_state *cli_enc_opt_state;
1871 struct data_string iaaddr;
1872 struct host_decl *host;
1873 int num_ia;
1874 int num_addr;
1875 struct data_string fixed_addr;
1876 struct data_string packet_oro;
1877
1878 /*
1879 * Validate the message.
1880 */
1881 if (!valid_client_msg(packet, &client_id)) {
1882 return;
1883 }
1884
1885 /*
1886 * Bit of variable initialization.
1887 */
1888 memset(&iaaddr, 0, sizeof(iaaddr));
1889 num_ia = 0;
1890 num_addr = 0;
1891 memset(&fixed_addr, 0, sizeof(fixed_addr));
1892 memset(&packet_oro, 0, sizeof(packet_oro));
1893
1894 /*
1895 * Set up reply.
1896 */
1897 if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
1898 goto exit;
1899 }
1900
1901 /*
1902 * Search each IA to make sure we know about it.
1903 */
1904 ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
1905 for (; ia != NULL; ia = ia->next) {
1906 num_ia++;
1907
1908 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
1909 &cli_enc_opt_data,
1910 packet, ia)) {
1911 goto exit;
1912 }
1913
1914 memset(&iaaddr, 0, sizeof(iaaddr));
1915 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
1916 D6O_IAADDR);
1917 if (oc == NULL) {
1918 /*
1919 * No address with this IA, check next.
1920 */
1921 continue;
1922 }
1923
1924 if (!evaluate_option_cache(&iaaddr, packet,
1925 NULL, NULL,
1926 packet->options,
1927 NULL, &global_scope,
1928 oc, MDL)) {
1929 log_error("dhcpv6_confirm: "
1930 "error evaluating IAADDR.");
1931 goto exit;
1932 }
1933
1934 host = NULL;
1935 if (!find_hosts_by_uid(&host,
1936 client_id.data, client_id.len, MDL)) {
1937 /*
1938 * RFC 3315, section 18.2.2 implies that when the
1939 * server doesn't know about the client it should
1940 * not send a reply.
1941 */
1942 goto exit;
1943 }
1944
1945 /*
1946 * Find the matching host entry, if any.
1947 */
1948 for (; host != NULL; host = host->n_ipaddr) {
1949 if (host->fixed_addr == NULL) {
1950 continue;
1951 }
1952 if (!evaluate_option_cache(&fixed_addr, NULL,
1953 NULL, NULL, NULL,
1954 NULL, &global_scope,
1955 host->fixed_addr,
1956 MDL)) {
1957 log_error("dhcpv6_confirm: error "
1958 "evaluating host address.");
1959 goto exit;
1960 }
1961 if ((iaaddr.len >= 16) &&
1962 !memcmp(fixed_addr.data, iaaddr.data, 16)) {
1963 data_string_forget(&fixed_addr, MDL);
1964 break;
1965 }
1966 data_string_forget(&fixed_addr, MDL);
1967 }
1968
1969 /*
1970 * No matching entry found, so this is a bad address.
1971 */
1972 if (host != NULL) {
1973 num_addr++;
1974 }
1975
1976 }
1977
1978 /*
1979 * If we have no addresses from the client, we don't send a reply.
1980 */
1981 if (num_addr == 0) {
1982 goto exit;
1983 }
1984
1985 /*
1986 * Set our status.
1987 */
1988 if (num_addr < num_ia) {
1989 if (!set_status_code(STATUS_NotOnLink,
1990 "Some of the addresses are not on link.",
1991 opt_state)) {
1992 goto exit;
1993 }
1994 } else {
1995 if (!set_status_code(STATUS_Success,
1996 "All addresses still on link.",
1997 opt_state)) {
1998 goto exit;
1999 }
2000 }
2001
2002 /*
2003 * Only one option: add it.
2004 */
2005 reply_ofs += store_options6(reply_data+reply_ofs,
2006 sizeof(reply_data)-reply_ofs,
2007 opt_state, packet,
2008 required_opts, &packet_oro);
2009
2010 /*
2011 * Return our reply to the caller.
2012 */
2013 reply_ret->len = reply_ofs;
2014 reply_ret->buffer = NULL;
2015 if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
2016 log_fatal("No memory to store reply.");
2017 }
2018 reply_ret->data = reply_ret->buffer->data;
2019 memcpy(reply_ret->buffer->data, reply, reply_ofs);
2020
2021exit:
2022 if (iaaddr.buffer != NULL) {
2023 data_string_forget(&iaaddr, MDL);
2024 }
2025 if (fixed_addr.buffer != NULL) {
2026 data_string_forget(&fixed_addr, MDL);
2027 }
2028 data_string_forget(&client_id, MDL);
2029}
2030
2031/*
2032 * Renew is when a client wants to extend its lease, at time T1.
2033 *
2034 * We handle this the same as if the client wants a new lease, except
2035 * for the error code of when addresses don't match.
2036 */
2037
2038/* TODO: discard unicast messages, unless we set unicast option */
2039static void
2040dhcpv6_renew(struct data_string *reply, struct packet *packet) {
2041 struct data_string client_id;
2042 struct data_string server_id;
2043
2044 /*
2045 * Validate the request.
2046 */
2047 if (!valid_client_resp(packet, &client_id, &server_id)) {
2048 return;
2049 }
2050
2051 /*
2052 * Renew our lease.
2053 */
2054 lease_to_client(reply, packet, &client_id, &server_id);
2055
2056 /*
2057 * Cleanup.
2058 */
2059 data_string_forget(&server_id, MDL);
2060 data_string_forget(&client_id, MDL);
2061}
2062
2063/*
2064 * Rebind is when a client wants to extend its lease, at time T2.
2065 *
2066 * We handle this the same as if the client wants a new lease, except
2067 * for the error code of when addresses don't match.
2068 */
2069
2070/* TODO: discard unicast messages, unless we set unicast option */
2071static void
2072dhcpv6_rebind(struct data_string *reply, struct packet *packet) {
2073 struct data_string client_id;
2074
2075 if (!valid_client_msg(packet, &client_id)) {
2076 return;
2077 }
2078
2079 lease_to_client(reply, packet, &client_id, NULL);
2080
2081 data_string_forget(&client_id, MDL);
2082}
2083
2084static void
2085ia_na_match_decline(const struct data_string *client_id,
2086 const struct data_string *iaaddr,
2087 struct iaaddr *lease) {
2088 char tmp_addr[INET6_ADDRSTRLEN];
2089
2090 log_error("Client %s reports address %s is "
2091 "already in use by another host!",
2092 print_hex_1(client_id->len, client_id->data, 60),
2093 inet_ntop(AF_INET6, iaaddr->data,
2094 tmp_addr, sizeof(tmp_addr)));
2095 if (lease != NULL) {
2096 decline_lease6(lease->ipv6_pool, lease);
2097 write_ia_na(lease->ia_na);
2098 }
2099}
2100
2101static void
2102ia_na_nomatch_decline(const struct data_string *client_id,
2103 const struct data_string *iaaddr,
2104 u_int32_t *ia_na_id,
2105 struct packet *packet,
2106 char *reply_data,
2107 int *reply_ofs,
2108 int reply_len) {
2109 char tmp_addr[INET6_ADDRSTRLEN];
2110 struct option_state *host_opt_state;
2111 int len;
2112
2113 log_info("Client %s declines address %s, which is not offered to it.",
2114 print_hex_1(client_id->len, client_id->data, 60),
2115 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
2116
2117 /*
2118 * Create state for this IA_NA.
2119 */
2120 host_opt_state = NULL;
2121 if (!option_state_allocate(&host_opt_state, MDL)) {
2122 log_error("ia_na_nomatch_decline: out of memory "
2123 "allocating option_state.");
2124 goto exit;
2125 }
2126
2127 if (!set_status_code(STATUS_NoBinding, "Decline for unknown address.",
2128 host_opt_state)) {
2129 goto exit;
2130 }
2131
2132 /*
2133 * Insure we have enough space
2134 */
2135 if (reply_len < (*reply_ofs + 16)) {
2136 log_error("ia_na_nomatch_decline: "
2137 "out of space for reply packet.");
2138 goto exit;
2139 }
2140
2141 /*
2142 * Put our status code into the reply packet.
2143 */
2144 len = store_options6(reply_data+(*reply_ofs)+16,
2145 reply_len-(*reply_ofs)-16,
2146 host_opt_state, packet,
2147 required_opts_STATUS_CODE, NULL);
2148
2149 /*
2150 * Store the non-encapsulated option data for this
2151 * IA_NA into our reply packet. Defined in RFC 3315,
2152 * section 22.4.
2153 */
2154 /* option number */
28868515 2155 putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
98bd7ca0 2156 /* option length */
28868515 2157 putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
98bd7ca0
DH
2158 /* IA_NA, copied from the client */
2159 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
2160 /* t1 and t2, odd that we need them, but here it is */
28868515
SK
2161 putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
2162 putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
98bd7ca0
DH
2163
2164 /*
2165 * Get ready for next IA_NA.
2166 */
2167 *reply_ofs += (len + 16);
2168
2169exit:
2170 option_state_dereference(&host_opt_state, MDL);
2171}
2172
2173static void
2174iterate_over_ia_na(struct data_string *reply_ret,
2175 struct packet *packet,
2176 const struct data_string *client_id,
2177 const struct data_string *server_id,
2178 char *packet_type,
2179 void (*ia_na_match)(),
2180 void (*ia_na_nomatch)()) {
2181 struct option_state *opt_state;
2182 struct host_decl *packet_host;
2183 struct option_cache *ia;
2184 struct option_cache *oc;
2185 /* cli_enc_... variables come from the IA_NA/IA_TA options */
2186 struct data_string cli_enc_opt_data;
2187 struct option_state *cli_enc_opt_state;
2188 struct host_decl *host;
2189 struct option_state *host_opt_state;
98bd7ca0
DH
2190 struct data_string iaaddr;
2191 struct data_string fixed_addr;
2192 int iaaddr_is_found;
2193 char reply_data[65536];
2194 struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
2195 int reply_ofs = (int)((char *)reply->options - (char *)reply);
2196 char status_msg[32];
2197 struct iaaddr *lease;
2198 struct ia_na *existing_ia_na;
2199 int i;
2200 struct data_string key;
2201 u_int32_t iaid;
2202
2203 /*
2204 * Initialize to empty values, in case we have to exit early.
2205 */
2206 opt_state = NULL;
2207 memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
2208 cli_enc_opt_state = NULL;
2209 memset(&iaaddr, 0, sizeof(iaaddr));
2210 memset(&fixed_addr, 0, sizeof(fixed_addr));
2211 host_opt_state = NULL;
2212 lease = NULL;
2213
2214 /*
2215 * Find the host record that matches from the packet, if any.
2216 */
2217 packet_host = NULL;
2218 if (!find_hosts_by_uid(&packet_host,
2219 client_id->data, client_id->len, MDL)) {
2220 packet_host = NULL;
2221 /*
2222 * Note: In general, we don't expect a client to provide
2223 * enough information to match by option for these
2224 * types of messages, but if we don't have a UID
2225 * match we can check anyway.
2226 */
2227 if (!find_hosts_by_option(&packet_host,
2228 packet, packet->options, MDL)) {
2229 packet_host = NULL;
2230 }
2231 }
2232
2233 /*
2234 * Set our reply information.
2235 */
2236 reply->msg_type = DHCPV6_REPLY;
2237 memcpy(reply->transaction_id, packet->dhcpv6_transaction_id,
2238 sizeof(reply->transaction_id));
2239
2240 /*
2241 * Build our option state for reply.
2242 */
2243 opt_state = NULL;
2244 if (!option_state_allocate(&opt_state, MDL)) {
2245 log_error("iterate_over_ia_na: no memory for option_state.");
2246 goto exit;
2247 }
2248 execute_statements_in_scope(NULL, packet, NULL, NULL,
2249 packet->options, opt_state,
2250 &global_scope, root_group, NULL);
2251
2252 /*
2253 * RFC 3315, section 18.2.7 tells us which options to include.
2254 */
2255 oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
2256 if (oc == NULL) {
28868515
SK
2257 if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
2258 (unsigned char *)server_duid.data,
98bd7ca0
DH
2259 server_duid.len, D6O_SERVERID, 0)) {
2260 log_error("iterate_over_ia_na: "
2261 "error saving server identifier.");
2262 goto exit;
2263 }
2264 }
2265
2266 if (!save_option_buffer(&dhcpv6_universe, opt_state,
2267 client_id->buffer,
2268 (unsigned char *)client_id->data,
2269 client_id->len,
2270 D6O_CLIENTID, 0)) {
2271 log_error("iterate_over_ia_na: "
2272 "error saving client identifier.");
2273 goto exit;
2274 }
2275
2276 snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type);
2277 if (!set_status_code(STATUS_Success, status_msg, opt_state)) {
2278 goto exit;
2279 }
2280
2281 /*
2282 * Add our options that are not associated with any IA_NA or IA_TA.
2283 */
2284 reply_ofs += store_options6(reply_data+reply_ofs,
2285 sizeof(reply_data)-reply_ofs,
2286 opt_state, packet,
2287 required_opts, NULL);
2288
2289 /*
2290 * Loop through the IA_NA reported by the client, and deal with
2291 * addresses reported as already in use.
2292 */
2293 for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
2294 ia != NULL; ia = ia->next) {
2295 iaaddr_is_found = 0;
2296
2297 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
2298 &cli_enc_opt_data,
2299 packet, ia)) {
2300 goto exit;
2301 }
2302
2303 iaid = getULong(cli_enc_opt_data.data);
2304
2305 /*
2306 * XXX: It is possible that we can get multiple addresses
2307 * sent by the client. We don't send multiple
2308 * addresses, so this indicates a client error.
2309 * We should check for multiple IAADDR options, log
2310 * if found, and set as an error.
2311 */
2312 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
2313 D6O_IAADDR);
2314 if (oc == NULL) {
2315 /* no address given for this IA, ignore */
2316 option_state_dereference(&cli_enc_opt_state, MDL);
2317 data_string_forget(&cli_enc_opt_data, MDL);
2318 continue;
2319 }
2320
2321 memset(&iaaddr, 0, sizeof(iaaddr));
2322 if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL,
2323 packet->options, NULL,
2324 &global_scope, oc, MDL)) {
2325 log_error("iterate_over_ia_na: "
2326 "error evaluating IAADDR.");
2327 goto exit;
2328 }
2329
2330 /*
2331 * Now we need to figure out which host record matches
2332 * this IA_NA and IAADDR.
2333 *
2334 * XXX: We don't currently track IA_NA separately, but
2335 * we will need to do this!
2336 */
2337 host = NULL;
2338 if (!find_hosts_by_option(&host, packet,
2339 cli_enc_opt_state, MDL)) {
2340 if (packet_host != NULL) {
2341 host = packet_host;
2342 } else {
2343 host = NULL;
2344 }
2345 }
2346 while (host != NULL) {
2347 if (host->fixed_addr != NULL) {
2348 if (!evaluate_option_cache(&fixed_addr, NULL,
2349 NULL, NULL, NULL,
2350 NULL, &global_scope,
2351 host->fixed_addr,
2352 MDL)) {
2353 log_error("iterate_over_ia_na: error "
2354 "evaluating host address.");
2355 goto exit;
2356 }
2357 if ((iaaddr.len >= 16) &&
2358 !memcmp(fixed_addr.data, iaaddr.data, 16)) {
2359 data_string_forget(&fixed_addr, MDL);
2360 break;
2361 }
2362 data_string_forget(&fixed_addr, MDL);
2363 }
2364 host = host->n_ipaddr;
2365 }
2366
2367 if ((host == NULL) && (iaaddr.len >= 24)) {
2368 /*
2369 * Find existing IA_NA.
2370 */
28868515
SK
2371 if (ia_na_make_key(&key, iaid,
2372 (char *)client_id->data,
98bd7ca0
DH
2373 client_id->len,
2374 MDL) != ISC_R_SUCCESS) {
2375 log_fatal("iterate_over_ia_na: no memory for "
2376 "key.");
2377 }
2378
2379 existing_ia_na = NULL;
2380 if (ia_na_hash_lookup(&existing_ia_na, ia_active,
28868515
SK
2381 (unsigned char *)key.data,
2382 key.len, MDL)) {
98bd7ca0
DH
2383 /*
2384 * Make sure this address is in the IA_NA.
2385 */
2386 for (i=0; i<existing_ia_na->num_iaaddr; i++) {
2387 struct iaaddr *tmp;
2388 struct in6_addr *in6_addr;
2389
2390 tmp = existing_ia_na->iaaddr[i];
2391 in6_addr = &tmp->addr;
2392 if (memcmp(in6_addr,
2393 iaaddr.data, 16) == 0) {
2394 iaaddr_reference(&lease,
2395 tmp, MDL);
2396 break;
2397 }
2398 }
2399 }
2400
2401 data_string_forget(&key, MDL);
2402 }
2403
2404 if ((host != NULL) || (lease != NULL)) {
2405 ia_na_match(client_id, &iaaddr, lease);
2406 } else {
2407 ia_na_nomatch(client_id, &iaaddr,
2408 (u_int32_t *)cli_enc_opt_data.data,
2409 packet, reply_data, &reply_ofs,
2410 sizeof(reply_data));
2411 }
2412
2413 if (lease != NULL) {
2414 iaaddr_dereference(&lease, MDL);
2415 }
2416
2417 data_string_forget(&iaaddr, MDL);
2418 option_state_dereference(&cli_enc_opt_state, MDL);
2419 data_string_forget(&cli_enc_opt_data, MDL);
2420 }
2421
2422 /*
2423 * Return our reply to the caller.
2424 */
2425 reply_ret->len = reply_ofs;
2426 reply_ret->buffer = NULL;
2427 if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
2428 log_fatal("No memory to store reply.");
2429 }
2430 reply_ret->data = reply_ret->buffer->data;
2431 memcpy(reply_ret->buffer->data, reply, reply_ofs);
2432
2433exit:
2434 if (lease != NULL) {
2435 iaaddr_dereference(&lease, MDL);
2436 }
2437 if (host_opt_state != NULL) {
2438 option_state_dereference(&host_opt_state, MDL);
2439 }
2440 if (fixed_addr.buffer != NULL) {
2441 data_string_forget(&fixed_addr, MDL);
2442 }
2443 if (iaaddr.buffer != NULL) {
2444 data_string_forget(&iaaddr, MDL);
2445 }
2446 if (cli_enc_opt_state != NULL) {
2447 option_state_dereference(&cli_enc_opt_state, MDL);
2448 }
2449 if (cli_enc_opt_data.buffer != NULL) {
2450 data_string_forget(&cli_enc_opt_data, MDL);
2451 }
2452 if (opt_state != NULL) {
2453 option_state_dereference(&opt_state, MDL);
2454 }
2455}
2456
2457/*
2458 * Decline means a client has detected that something else is using an
2459 * address we gave it.
2460 *
2461 * Since we're only dealing with fixed leases for now, there's not
2462 * much we can do, other that log the occurrance.
2463 *
2464 * When we start issuing addresses from pools, then we will have to
2465 * record our declined addresses and issue another. In general with
2466 * IPv6 there is no worry about DoS by clients exhausting space, but
2467 * we still need to be aware of this possibility.
2468 */
2469
2470/* TODO: discard unicast messages, unless we set unicast option */
2471/* TODO: IA_TA */
2472static void
2473dhcpv6_decline(struct data_string *reply, struct packet *packet) {
2474 struct data_string client_id;
2475 struct data_string server_id;
2476
2477 /*
2478 * Validate our input.
2479 */
2480 if (!valid_client_resp(packet, &client_id, &server_id)) {
2481 return;
2482 }
2483
2484 /*
2485 * And operate on each IA_NA in this packet.
2486 */
2487 iterate_over_ia_na(reply, packet, &client_id, &server_id, "Decline",
2488 ia_na_match_decline, ia_na_nomatch_decline);
2489}
2490
2491static void
2492ia_na_match_release(const struct data_string *client_id,
2493 const struct data_string *iaaddr,
2494 struct iaaddr *lease) {
2495 char tmp_addr[INET6_ADDRSTRLEN];
2496
2497 log_info("Client %s releases address %s",
2498 print_hex_1(client_id->len, client_id->data, 60),
2499 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
2500 if (lease != NULL) {
2501 release_lease6(lease->ipv6_pool, lease);
2502 write_ia_na(lease->ia_na);
2503 }
2504}
2505
2506static void
2507ia_na_nomatch_release(const struct data_string *client_id,
2508 const struct data_string *iaaddr,
2509 u_int32_t *ia_na_id,
2510 struct packet *packet,
2511 char *reply_data,
2512 int *reply_ofs,
2513 int reply_len) {
2514 char tmp_addr[INET6_ADDRSTRLEN];
2515 struct option_state *host_opt_state;
2516 int len;
2517
2518 log_info("Client %s releases address %s, which is not leased to it.",
2519 print_hex_1(client_id->len, client_id->data, 60),
2520 inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
2521
2522 /*
2523 * Create state for this IA_NA.
2524 */
2525 host_opt_state = NULL;
2526 if (!option_state_allocate(&host_opt_state, MDL)) {
2527 log_error("ia_na_match_release: out of memory "
2528 "allocating option_state.");
2529 goto exit;
2530 }
2531
2532 if (!set_status_code(STATUS_NoBinding,
2533 "Release for non-leased address.",
2534 host_opt_state)) {
2535 goto exit;
2536 }
2537
2538 /*
2539 * Insure we have enough space
2540 */
2541 if (reply_len < (*reply_ofs + 16)) {
2542 log_error("ia_na_match_release: "
2543 "out of space for reply packet.");
2544 goto exit;
2545 }
2546
2547 /*
2548 * Put our status code into the reply packet.
2549 */
2550 len = store_options6(reply_data+(*reply_ofs)+16,
2551 reply_len-(*reply_ofs)-16,
2552 host_opt_state, packet,
2553 required_opts_STATUS_CODE, NULL);
2554
2555 /*
2556 * Store the non-encapsulated option data for this
2557 * IA_NA into our reply packet. Defined in RFC 3315,
2558 * section 22.4.
2559 */
2560 /* option number */
28868515 2561 putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
98bd7ca0 2562 /* option length */
28868515 2563 putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
98bd7ca0
DH
2564 /* IA_NA, copied from the client */
2565 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
2566 /* t1 and t2, odd that we need them, but here it is */
28868515
SK
2567 putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
2568 putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
98bd7ca0
DH
2569
2570 /*
2571 * Get ready for next IA_NA.
2572 */
2573 *reply_ofs += (len + 16);
2574
2575exit:
2576 option_state_dereference(&host_opt_state, MDL);
2577}
2578
2579/*
2580 * Release means a client is done with the addresses.
2581 */
2582
2583/* TODO: discard unicast messages, unless we set unicast option */
2584static void
2585dhcpv6_release(struct data_string *reply, struct packet *packet) {
2586 struct data_string client_id;
2587 struct data_string server_id;
2588
2589 /*
2590 * Validate our input.
2591 */
2592 if (!valid_client_resp(packet, &client_id, &server_id)) {
2593 return;
2594 }
2595
2596 /*
2597 * And operate on each IA_NA in this packet.
2598 */
2599 iterate_over_ia_na(reply, packet, &client_id, &server_id, "Release",
2600 ia_na_match_release, ia_na_nomatch_release);
2601
2602 data_string_forget(&server_id, MDL);
2603 data_string_forget(&client_id, MDL);
2604}
2605
2606/*
2607 * Information-Request is used by clients who have obtained an address
2608 * from other means, but want configuration information from the server.
2609 */
2610
2611/* TODO: discard unicast messages, unless we set unicast option */
2612static void
2613dhcpv6_information_request(struct data_string *reply, struct packet *packet) {
2614 struct data_string client_id;
2615 struct data_string server_id;
2616
2617 /*
2618 * Validate our input.
2619 */
2620 if (!valid_client_info_req(packet, &server_id)) {
2621 return;
2622 }
2623
2624 /*
2625 * Get our client ID, if there is one.
2626 */
2627 memset(&client_id, 0, sizeof(client_id));
2628 if (get_client_id(packet, &client_id) != ISC_R_SUCCESS) {
2629 data_string_forget(&client_id, MDL);
2630 }
2631
2632 /*
2633 * Use the lease_to_client() function. This will work fine,
2634 * because the valid_client_info_req() insures that we
2635 * don't have any IA_NA or IA_TA that would cause us to
2636 * allocate addresses to the client.
2637 */
2638 lease_to_client(reply, packet, &client_id, &server_id);
2639
2640 /*
2641 * Cleanup.
2642 */
2643 if (client_id.data != NULL) {
2644 data_string_forget(&client_id, MDL);
2645 }
2646 data_string_forget(&server_id, MDL);
2647}
2648
2649/*
2650 * The Relay-forw message is sent by relays. It typically contains a
2651 * single option, which encapsulates an entire packet.
2652 *
2653 * We need to build an encapsulated reply.
2654 */
2655
2656/* XXX: this is very, very similar to do_packet6(), and should probably
2657 be combined in a clever way */
2658static void
2659dhcpv6_relay_forw(struct data_string *reply_ret, struct packet *packet) {
2660 struct dhcpv6_relay_packet reply;
2661 struct option_cache *oc;
2662 struct data_string enc_opt_data;
2663 struct packet *enc_packet;
2664 unsigned char msg_type;
2665 const struct dhcpv6_packet *msg;
2666 const struct dhcpv6_relay_packet *relay;
2667 struct data_string enc_reply;
2668 char link_addr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
2669 char peer_addr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
2670 struct data_string interface_id;
2671
2672 /*
2673 * Intialize variables for early exit.
2674 */
2675 memset(&enc_opt_data, 0, sizeof(enc_opt_data));
2676 enc_packet = NULL;
2677 memset(&enc_reply, 0, sizeof(enc_reply));
2678 memset(&interface_id, 0, sizeof(interface_id));
2679
2680 /*
2681 * Get our encapsulated relay message.
2682 */
2683 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_RELAY_MSG);
2684 if (oc == NULL) {
2685 inet_ntop(AF_INET6, &packet->dhcpv6_link_address,
2686 link_addr, sizeof(link_addr));
2687 inet_ntop(AF_INET6, &packet->dhcpv6_peer_address,
2688 peer_addr, sizeof(peer_addr));
2689 log_info("Relay-forward from %s with link address=%s and "
2690 "peer address=%s missing Relay Message option.",
2691 piaddr(packet->client_addr), link_addr, peer_addr);
2692 goto exit;
2693 }
2694
2695 memset(&enc_opt_data, 0, sizeof(enc_opt_data));
2696 if (!evaluate_option_cache(&enc_opt_data, NULL, NULL, NULL,
2697 NULL, NULL, &global_scope, oc, MDL)) {
2698 log_error("dhcpv6_forw_relay: error evaluating "
2699 "relayed message.");
2700 goto exit;
2701 }
2702
28868515 2703 if (!packet6_len_okay((char *)enc_opt_data.data, enc_opt_data.len)) {
98bd7ca0
DH
2704 log_error("dhcpv6_forw_relay: encapsulated packet too short.");
2705 goto exit;
2706 }
2707
2708 /*
2709 * Build a packet structure from this encapsulated packet.
2710 */
2711 enc_packet = NULL;
2712 if (!packet_allocate(&enc_packet, MDL)) {
2713 log_error("dhcpv6_forw_relay: "
2714 "no memory for encapsulated packet.");
2715 goto exit;
2716 }
2717
2718 if (!option_state_allocate(&enc_packet->options, MDL)) {
2719 log_error("dhcpv6_forw_relay: "
2720 "no memory for encapsulated packet's options.");
2721 goto exit;
2722 }
2723
2724 enc_packet->client_port = packet->client_port;
2725 enc_packet->client_addr = packet->client_addr;
2726 enc_packet->dhcpv6_container_packet = packet;
2727
2728 msg_type = enc_opt_data.data[0];
2729 if ((msg_type == DHCPV6_RELAY_FORW) ||
2730 (msg_type == DHCPV6_RELAY_REPL)) {
2731 relay = (struct dhcpv6_relay_packet *)enc_opt_data.data;
2732 enc_packet->dhcpv6_msg_type = relay->msg_type;
2733
2734 /* relay-specific data */
2735 enc_packet->dhcpv6_hop_count = relay->hop_count;
2736 memcpy(&enc_packet->dhcpv6_link_address,
2737 relay->link_address, sizeof(relay->link_address));
2738 memcpy(&enc_packet->dhcpv6_peer_address,
2739 relay->peer_address, sizeof(relay->peer_address));
2740
2741 if (!parse_option_buffer(enc_packet->options,
2742 relay->options,
2743 enc_opt_data.len-sizeof(*relay),
2744 &dhcpv6_universe)) {
2745 /* no logging here, as parse_option_buffer() logs all
2746 cases where it fails */
2747 goto exit;
2748 }
2749 } else {
2750 msg = (struct dhcpv6_packet *)enc_opt_data.data;
2751 enc_packet->dhcpv6_msg_type = msg->msg_type;
2752
2753 /* message-specific data */
2754 memcpy(enc_packet->dhcpv6_transaction_id,
2755 msg->transaction_id,
2756 sizeof(enc_packet->dhcpv6_transaction_id));
2757
2758 if (!parse_option_buffer(enc_packet->options,
2759 msg->options,
2760 enc_opt_data.len-sizeof(*msg),
2761 &dhcpv6_universe)) {
2762 /* no logging here, as parse_option_buffer() logs all
2763 cases where it fails */
2764 goto exit;
2765 }
2766 }
2767
2768 /*
2769 * This is recursive. It is possible to exceed maximum packet size.
2770 * XXX: This will cause the packet send to fail.
2771 */
2772 build_dhcpv6_reply(&enc_reply, enc_packet);
2773
2774 /*
2775 * If we got no encapsulated data, then it is discarded, and
2776 * our reply-forw is also discarded.
2777 */
2778 if (enc_reply.data == NULL) {
2779 goto exit;
2780 }
2781
2782 /*
2783 * Append the interface-id if present
2784 */
2785 oc = lookup_option(&dhcpv6_universe, packet->options, D6O_INTERFACE_ID);
2786 if (oc != NULL) {
2787 memset(&interface_id, 0, sizeof(interface_id));
2788 if (!evaluate_option_cache(&interface_id, NULL, NULL, NULL,
2789 NULL, NULL, &global_scope,
2790 oc, MDL)) {
2791 log_error("dhcpv6_forw_relay: error evaluating "
2792 "Interface ID.");
2793 goto exit;
2794 }
2795 }
2796
2797 /*
2798 * Packet header stuff all comes from the forward message.
2799 */
2800 reply.msg_type = DHCPV6_RELAY_REPL;
2801 reply.hop_count = packet->dhcpv6_hop_count;
2802 memcpy(reply.link_address, &packet->dhcpv6_link_address,
2803 sizeof(reply.link_address));
2804 memcpy(reply.peer_address, &packet->dhcpv6_peer_address,
2805 sizeof(reply.peer_address));
2806
2807 /*
2808 * Copy our encapsulated stuff for caller.
2809 */
2810 reply_ret->len = sizeof(reply) + 4 + enc_reply.len;
2811 if (interface_id.data != NULL) {
2812 reply_ret->len += 4 + interface_id.len;
2813 }
2814 /*
2815 * XXX: We should not allow this to happen, perhaps by letting
2816 * build_dhcp_reply() know our space remaining.
2817 */
2818 if (reply_ret->len >= 65536) {
2819 log_error("dhcpv6_forw_relay: RELAY-REPL too big (%d bytes)",
2820 reply_ret->len);
2821 goto exit;
2822 }
2823 reply_ret->buffer = NULL;
2824 if (!buffer_allocate(&reply_ret->buffer, reply_ret->len, MDL)) {
2825 log_fatal("No memory to store reply.");
2826 }
2827 reply_ret->data = reply_ret->buffer->data;
2828 memcpy(reply_ret->buffer->data, &reply, sizeof(reply));
2829 putShort(reply_ret->buffer->data+sizeof(reply), D6O_RELAY_MSG);
2830 putShort(reply_ret->buffer->data+sizeof(reply)+2, enc_reply.len);
2831 memcpy(reply_ret->buffer->data+sizeof(reply)+4,
2832 enc_reply.data, enc_reply.len);
2833 if (interface_id.data != NULL) {
2834 putShort(reply_ret->buffer->data+sizeof(reply)+4+enc_reply.len,
2835 D6O_INTERFACE_ID);
2836 putShort(reply_ret->buffer->data+sizeof(reply)+6+enc_reply.len,
2837 interface_id.len);
2838 memcpy(reply_ret->buffer->data+sizeof(reply)+8+enc_reply.len,
2839 interface_id.data, interface_id.len);
2840 }
2841
2842exit:
2843 if (interface_id.data != NULL) {
2844 data_string_forget(&interface_id, MDL);
2845 }
2846 if (enc_reply.data != NULL) {
2847 data_string_forget(&enc_reply, MDL);
2848 }
2849 if (enc_opt_data.data != NULL) {
2850 data_string_forget(&enc_opt_data, MDL);
2851 }
2852 if (enc_packet != NULL) {
2853 packet_dereference(&enc_packet, MDL);
2854 }
2855}
2856
2857static void
2858dhcpv6_discard(struct packet *packet) {
2859 /* INSIST(packet->msg_type > 0); */
2860 /* INSIST(packet->msg_type < dhcpv6_type_name_max); */
2861
2862 log_debug("Discarding %s from %s; message type not handled by server",
2863 dhcpv6_type_names[packet->dhcpv6_msg_type],
2864 piaddr(packet->client_addr));
2865}
2866
2867static void
2868build_dhcpv6_reply(struct data_string *reply, struct packet *packet) {
2869 memset(reply, 0, sizeof(*reply));
2870 switch (packet->dhcpv6_msg_type) {
2871 case DHCPV6_SOLICIT:
2872 dhcpv6_solicit(reply, packet);
2873 break;
2874 case DHCPV6_ADVERTISE:
2875 dhcpv6_discard(packet);
2876 break;
2877 case DHCPV6_REQUEST:
2878 dhcpv6_request(reply, packet);
2879 break;
2880 case DHCPV6_CONFIRM:
2881 dhcpv6_confirm(reply, packet);
2882 break;
2883 case DHCPV6_RENEW:
2884 dhcpv6_renew(reply, packet);
2885 break;
2886 case DHCPV6_REBIND:
2887 dhcpv6_rebind(reply, packet);
2888 break;
2889 case DHCPV6_REPLY:
2890 dhcpv6_discard(packet);
2891 break;
2892 case DHCPV6_RELEASE:
2893 dhcpv6_release(reply, packet);
2894 break;
2895 case DHCPV6_DECLINE:
2896 dhcpv6_decline(reply, packet);
2897 break;
2898 case DHCPV6_RECONFIGURE:
2899 dhcpv6_discard(packet);
2900 break;
2901 case DHCPV6_INFORMATION_REQUEST:
2902 dhcpv6_information_request(reply, packet);
2903 break;
2904 case DHCPV6_RELAY_FORW:
2905 dhcpv6_relay_forw(reply, packet);
2906 break;
2907 case DHCPV6_RELAY_REPL:
2908 dhcpv6_discard(packet);
2909 break;
2910 default:
2911 /* XXX: would be nice if we had "notice" level,
2912 as syslog, for this */
2913 log_info("Discarding unknown DHCPv6 message type %d "
2914 "from %s", packet->dhcpv6_msg_type,
2915 piaddr(packet->client_addr));
2916 }
2917}
2918
2919static void
2920log_packet_in(const struct packet *packet) {
2921 struct data_string s;
2922 u_int32_t tid;
2923 char tmp_addr[INET6_ADDRSTRLEN];
2924 const void *addr;
98bd7ca0
DH
2925
2926 memset(&s, 0, sizeof(s));
2927
2928 if (packet->dhcpv6_msg_type < dhcpv6_type_name_max) {
2929 data_string_sprintfa(&s, "%s message from %s port %d",
2930 dhcpv6_type_names[packet->dhcpv6_msg_type],
2931 piaddr(packet->client_addr),
2932 ntohs(packet->client_port));
2933 } else {
2934 data_string_sprintfa(&s,
2935 "Unknown message type %d from %s port %d",
2936 packet->dhcpv6_msg_type,
2937 piaddr(packet->client_addr),
2938 ntohs(packet->client_port));
2939 }
2940 if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) ||
2941 (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
2942 addr = &packet->dhcpv6_link_address;
2943 data_string_sprintfa(&s, ", link address %s",
2944 inet_ntop(AF_INET6, addr,
2945 tmp_addr, sizeof(tmp_addr)));
2946 addr = &packet->dhcpv6_peer_address;
2947 data_string_sprintfa(&s, ", peer address %s",
2948 inet_ntop(AF_INET6, addr,
2949 tmp_addr, sizeof(tmp_addr)));
2950 } else {
2951 tid = 0;
2952 memcpy(((char *)&tid)+1, packet->dhcpv6_transaction_id, 3);
2953 data_string_sprintfa(&s, ", transaction ID 0x%06X", tid);
2954
2955/*
2956 oc = lookup_option(&dhcpv6_universe, packet->options,
2957 D6O_CLIENTID);
2958 if (oc != NULL) {
2959 memset(&tmp_ds, 0, sizeof(tmp_ds_));
2960 if (!evaluate_option_cache(&tmp_ds, packet, NULL, NULL,
2961 packet->options, NULL,
2962 &global_scope, oc, MDL)) {
2963 log_error("Error evaluating Client Identifier");
2964 } else {
2965 data_strint_sprintf(&s, ", client ID %s",
2966
2967 data_string_forget(&tmp_ds, MDL);
2968 }
2969 }
2970*/
2971
2972 }
2973 log_info("%s", s.data);
2974
2975 data_string_forget(&s, MDL);
2976}
2977
2978void
2979dhcpv6(struct packet *packet) {
2980 struct data_string reply;
2981 struct sockaddr_in6 to_addr;
2982 int send_ret;
2983
2984 /*
2985 * Log a message that we received this packet.
2986 */
2987 log_packet_in(packet);
2988
2989 /*
2990 * Build our reply packet.
2991 */
2992 build_dhcpv6_reply(&reply, packet);
2993
2994 if (reply.data != NULL) {
2995 /*
2996 * Send our reply, if we have one.
2997 */
2998 memset(&to_addr, 0, sizeof(to_addr));
2999 to_addr.sin6_family = AF_INET6;
3000 if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) ||
3001 (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
3002 to_addr.sin6_port = local_port;
3003 } else {
3004 to_addr.sin6_port = remote_port;
3005 }
3006/* For testing, we reply to the sending port, so we don't need a root client */
3007 to_addr.sin6_port = packet->client_port;
3008 memcpy(&to_addr.sin6_addr, packet->client_addr.iabuf,
3009 sizeof(to_addr.sin6_addr));
3010
3011 log_info("Sending %s to %s port %d",
3012 dhcpv6_type_names[reply.data[0]],
3013 piaddr(packet->client_addr),
3014 ntohs(to_addr.sin6_port));
3015
3016 send_ret = send_packet6(packet->interface,
3017 reply.data, reply.len, &to_addr);
3018 if (send_ret != reply.len) {
3019 log_error("dhcpv6: send_packet6() sent %d of %d bytes",
3020 send_ret, reply.len);
3021 }
3022 data_string_forget(&reply, MDL);
3023 }
3024}
3025
fe5b0fdd
DH
3026#endif /* DHCPv6 */
3027