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