Annotation of embedaddon/dhcp/server/dhcpv6.c, revision 1.1.1.1
1.1 misho 1: /*
1.1.1.1 ! misho 2: * Copyright (C) 2006-2012 by Internet Systems Consortium, Inc. ("ISC")
1.1 misho 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];
1.1.1.1 ! misho 1094: if ((tmp_plen < 3) || (tmp_plen > 128) ||
! 1095: ((int)tmp_plen != pool->units)) {
1.1 misho 1096: return ISC_R_FAILURE;
1097: }
1098: memcpy(&tmp_pref, requested_pref->data + 1, sizeof(tmp_pref));
1099: if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
1100: return ISC_R_FAILURE;
1101: }
1102: ia.len = 16;
1103: memcpy(&ia.iabuf, &tmp_pref, 16);
1104: if (!is_cidr_mask_valid(&ia, (int) tmp_plen)) {
1105: return ISC_R_FAILURE;
1106: }
1107:
1.1.1.1 ! misho 1108: if (!ipv6_in_pool(&tmp_pref, pool)) {
! 1109: return ISC_R_ADDRNOTAVAIL;
1.1 misho 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: /*
1.1.1.1 ! misho 1209: *! \file server/dhcpv6.c
! 1210: *
! 1211: * \brief construct a reply containing information about a client's lease
! 1212: *
1.1 misho 1213: * lease_to_client() is called from several messages to construct a
1214: * reply that contains all that we know about the client's correct lease
1215: * (or projected lease).
1216: *
1217: * Solicit - "Soft" binding, ignore unknown addresses or bindings, just
1218: * send what we "may" give them on a request.
1219: *
1220: * Request - "Hard" binding, but ignore supplied addresses (just provide what
1221: * the client should really use).
1222: *
1223: * Renew - "Hard" binding, but client-supplied addresses are 'real'. Error
1224: * Rebind out any "wrong" addresses the client sends. This means we send
1225: * an empty IA_NA with a status code of NoBinding or NotOnLink or
1226: * possibly send the address with zeroed lifetimes.
1227: *
1228: * Information-Request - No binding.
1229: *
1230: * The basic structure is to traverse the client-supplied data first, and
1231: * validate and echo back any contents that can be. If the client-supplied
1232: * data does not error out (on renew/rebind as above), but we did not send
1233: * any addresses, attempt to allocate one.
1.1.1.1 ! misho 1234: *
! 1235: * At the end of the this function we call commit_leases_timed() to
! 1236: * fsync and rotate the file as necessary. commit_leases_timed() will
! 1237: * check that we have written at least one lease to the file and that
! 1238: * some time has passed before doing any fsync or file rewrite so we
! 1239: * don't bother tracking if we did a write_ia during this function.
1.1 misho 1240: */
1241: /* TODO: look at client hints for lease times */
1.1.1.1 ! misho 1242:
1.1 misho 1243: static void
1244: lease_to_client(struct data_string *reply_ret,
1245: struct packet *packet,
1246: const struct data_string *client_id,
1247: const struct data_string *server_id)
1248: {
1249: static struct reply_state reply;
1250: struct option_cache *oc;
1251: struct data_string packet_oro;
1.1.1.1 ! misho 1252: #if defined (RFC3315_PRE_ERRATA_2010_08)
! 1253: isc_boolean_t no_resources_avail = ISC_FALSE;
! 1254: #endif
! 1255:
! 1256: memset(&packet_oro, 0, sizeof(packet_oro));
1.1 misho 1257:
1258: /* Locate the client. */
1259: if (shared_network_from_packet6(&reply.shared,
1260: packet) != ISC_R_SUCCESS)
1261: goto exit;
1262:
1263: /*
1264: * Initialize the reply.
1265: */
1266: packet_reference(&reply.packet, packet, MDL);
1267: data_string_copy(&reply.client_id, client_id, MDL);
1268:
1269: if (!start_reply(packet, client_id, server_id, &reply.opt_state,
1270: &reply.buf.reply))
1271: goto exit;
1272:
1273: /* Set the write cursor to just past the reply header. */
1274: reply.cursor = REPLY_OPTIONS_INDEX;
1275:
1276: /*
1277: * Get the ORO from the packet, if any.
1278: */
1279: oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ORO);
1280: if (oc != NULL) {
1281: if (!evaluate_option_cache(&packet_oro, packet,
1282: NULL, NULL,
1283: packet->options, NULL,
1284: &global_scope, oc, MDL)) {
1285: log_error("lease_to_client: error evaluating ORO.");
1286: goto exit;
1287: }
1288: }
1289:
1290: /*
1291: * Find a host record that matches from the packet, if any, and is
1292: * valid for the shared network the client is on.
1293: */
1294: if (find_hosts_by_option(&reply.host, packet, packet->options, MDL)) {
1295: seek_shared_host(&reply.host, reply.shared);
1296: }
1297:
1298: if ((reply.host == NULL) &&
1299: find_hosts_by_uid(&reply.host, client_id->data, client_id->len,
1300: MDL)) {
1301: seek_shared_host(&reply.host, reply.shared);
1302: }
1303:
1304: /* Process the client supplied IA's onto the reply buffer. */
1305: reply.ia_count = 0;
1306: oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
1.1.1.1 ! misho 1307:
1.1 misho 1308: for (; oc != NULL ; oc = oc->next) {
1309: isc_result_t status;
1310:
1311: /* Start counting resources (addresses) offered. */
1312: reply.client_resources = 0;
1313: reply.resources_included = ISC_FALSE;
1314:
1315: status = reply_process_ia_na(&reply, oc);
1316:
1317: /*
1318: * We continue to try other IA's whether we can address
1319: * this one or not. Any other result is an immediate fail.
1320: */
1321: if ((status != ISC_R_SUCCESS) &&
1322: (status != ISC_R_NORESOURCES))
1323: goto exit;
1324:
1.1.1.1 ! misho 1325: #if defined (RFC3315_PRE_ERRATA_2010_08)
1.1 misho 1326: /*
1327: * If any address cannot be given to any IA, then set the
1328: * NoAddrsAvail status code.
1329: */
1330: if (reply.client_resources == 0)
1331: no_resources_avail = ISC_TRUE;
1.1.1.1 ! misho 1332: #endif
1.1 misho 1333: }
1334: oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
1335: for (; oc != NULL ; oc = oc->next) {
1336: isc_result_t status;
1337:
1338: /* Start counting resources (addresses) offered. */
1339: reply.client_resources = 0;
1340: reply.resources_included = ISC_FALSE;
1341:
1342: status = reply_process_ia_ta(&reply, oc);
1343:
1344: /*
1345: * We continue to try other IA's whether we can address
1346: * this one or not. Any other result is an immediate fail.
1347: */
1348: if ((status != ISC_R_SUCCESS) &&
1349: (status != ISC_R_NORESOURCES))
1350: goto exit;
1351:
1.1.1.1 ! misho 1352: #if defined (RFC3315_PRE_ERRATA_2010_08)
1.1 misho 1353: /*
1354: * If any address cannot be given to any IA, then set the
1355: * NoAddrsAvail status code.
1356: */
1357: if (reply.client_resources == 0)
1358: no_resources_avail = ISC_TRUE;
1.1.1.1 ! misho 1359: #endif
1.1 misho 1360: }
1361:
1362: /* Same for IA_PD's. */
1363: reply.pd_count = 0;
1364: oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
1365: for (; oc != NULL ; oc = oc->next) {
1366: isc_result_t status;
1367:
1368: /* Start counting resources (prefixes) offered. */
1369: reply.client_resources = 0;
1370: reply.resources_included = ISC_FALSE;
1371:
1372: status = reply_process_ia_pd(&reply, oc);
1373:
1374: /*
1375: * We continue to try other IA_PD's whether we can address
1376: * this one or not. Any other result is an immediate fail.
1377: */
1378: if ((status != ISC_R_SUCCESS) &&
1379: (status != ISC_R_NORESOURCES))
1380: goto exit;
1381: }
1382:
1383: /*
1384: * Make no reply if we gave no resources and is not
1385: * for Information-Request.
1386: */
1387: if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
1388: if (reply.packet->dhcpv6_msg_type !=
1389: DHCPV6_INFORMATION_REQUEST)
1390: goto exit;
1391:
1392: /*
1393: * Because we only execute statements on a per-IA basis,
1394: * we need to execute statements in any non-IA reply to
1395: * source configuration.
1396: */
1397: execute_statements_in_scope(NULL, reply.packet, NULL, NULL,
1398: reply.packet->options,
1399: reply.opt_state, &global_scope,
1400: reply.shared->group, root_group);
1401:
1402: /* Bring in any configuration from a host record. */
1403: if (reply.host != NULL)
1404: execute_statements_in_scope(NULL, reply.packet, NULL,
1405: NULL, reply.packet->options,
1406: reply.opt_state,
1407: &global_scope,
1408: reply.host->group,
1409: reply.shared->group);
1410: }
1411:
1412: /*
1413: * RFC3315 section 17.2.2 (Solicit):
1414: *
1415: * If the server will not assign any addresses to any IAs in a
1416: * subsequent Request from the client, the server MUST send an
1417: * Advertise message to the client that includes only a Status
1418: * Code option with code NoAddrsAvail and a status message for
1419: * the user, a Server Identifier option with the server's DUID,
1420: * and a Client Identifier option with the client's DUID.
1421: *
1422: * Section 18.2.1 (Request):
1423: *
1424: * If the server cannot assign any addresses to an IA in the
1425: * message from the client, the server MUST include the IA in
1426: * the Reply message with no addresses in the IA and a Status
1427: * Code option in the IA containing status code NoAddrsAvail.
1428: *
1429: * Section 18.1.8 (Client Behavior):
1430: *
1431: * Leave unchanged any information about addresses the client has
1432: * recorded in the IA but that were not included in the IA from
1433: * the server.
1434: * Sends a Renew/Rebind if the IA is not in the Reply message.
1435: */
1.1.1.1 ! misho 1436: #if defined (RFC3315_PRE_ERRATA_2010_08)
1.1 misho 1437: if (no_resources_avail && (reply.ia_count != 0) &&
1438: (reply.packet->dhcpv6_msg_type == DHCPV6_SOLICIT))
1439: {
1440: /* Set the NoAddrsAvail status code. */
1441: if (!set_status_code(STATUS_NoAddrsAvail,
1442: "No addresses available for this "
1443: "interface.", reply.opt_state)) {
1444: log_error("lease_to_client: Unable to set "
1445: "NoAddrsAvail status code.");
1446: goto exit;
1447: }
1448:
1449: /* Rewind the cursor to the start. */
1450: reply.cursor = REPLY_OPTIONS_INDEX;
1451:
1452: /*
1453: * Produce an advertise that includes only:
1454: *
1455: * Status code.
1456: * Server DUID.
1457: * Client DUID.
1458: */
1459: reply.buf.reply.msg_type = DHCPV6_ADVERTISE;
1460: reply.cursor += store_options6((char *)reply.buf.data +
1461: reply.cursor,
1462: sizeof(reply.buf) -
1463: reply.cursor,
1464: reply.opt_state, reply.packet,
1465: required_opts_NAA,
1466: NULL);
1467: } else {
1468: /*
1469: * Having stored the client's IA's, store any options that
1470: * will fit in the remaining space.
1471: */
1472: reply.cursor += store_options6((char *)reply.buf.data +
1473: reply.cursor,
1474: sizeof(reply.buf) -
1475: reply.cursor,
1476: reply.opt_state, reply.packet,
1477: required_opts_solicit,
1478: &packet_oro);
1479: }
1.1.1.1 ! misho 1480: #else /* defined (RFC3315_PRE_ERRATA_2010_08) */
! 1481: /*
! 1482: * Having stored the client's IA's, store any options that
! 1483: * will fit in the remaining space.
! 1484: */
! 1485: reply.cursor += store_options6((char *)reply.buf.data + reply.cursor,
! 1486: sizeof(reply.buf) - reply.cursor,
! 1487: reply.opt_state, reply.packet,
! 1488: required_opts_solicit,
! 1489: &packet_oro);
! 1490: #endif /* defined (RFC3315_PRE_ERRATA_2010_08) */
1.1 misho 1491:
1492: /* Return our reply to the caller. */
1493: reply_ret->len = reply.cursor;
1494: reply_ret->buffer = NULL;
1495: if (!buffer_allocate(&reply_ret->buffer, reply.cursor, MDL)) {
1496: log_fatal("No memory to store Reply.");
1497: }
1498: memcpy(reply_ret->buffer->data, reply.buf.data, reply.cursor);
1499: reply_ret->data = reply_ret->buffer->data;
1500:
1.1.1.1 ! misho 1501: /* If appropriate commit and rotate the lease file */
! 1502: (void) commit_leases_timed();
! 1503:
1.1 misho 1504: exit:
1505: /* Cleanup. */
1506: if (reply.shared != NULL)
1507: shared_network_dereference(&reply.shared, MDL);
1508: if (reply.host != NULL)
1509: host_dereference(&reply.host, MDL);
1510: if (reply.opt_state != NULL)
1511: option_state_dereference(&reply.opt_state, MDL);
1512: if (reply.packet != NULL)
1513: packet_dereference(&reply.packet, MDL);
1514: if (reply.client_id.data != NULL)
1515: data_string_forget(&reply.client_id, MDL);
1.1.1.1 ! misho 1516: if (packet_oro.buffer != NULL)
! 1517: data_string_forget(&packet_oro, MDL);
1.1 misho 1518: reply.renew = reply.rebind = reply.prefer = reply.valid = 0;
1519: reply.cursor = 0;
1520: }
1521:
1522: /* Process a client-supplied IA_NA. This may append options to the tail of
1523: * the reply packet being built in the reply_state structure.
1524: */
1525: static isc_result_t
1526: reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
1527: isc_result_t status = ISC_R_SUCCESS;
1528: u_int32_t iaid;
1529: unsigned ia_cursor;
1530: struct option_state *packet_ia;
1531: struct option_cache *oc;
1532: struct data_string ia_data, data;
1533:
1534: /* Initialize values that will get cleaned up on return. */
1535: packet_ia = NULL;
1536: memset(&ia_data, 0, sizeof(ia_data));
1537: memset(&data, 0, sizeof(data));
1538: /*
1539: * Note that find_client_address() may set reply->lease.
1540: */
1541:
1542: /* Make sure there is at least room for the header. */
1543: if ((reply->cursor + IA_NA_OFFSET + 4) > sizeof(reply->buf)) {
1544: log_error("reply_process_ia_na: Reply too long for IA.");
1545: return ISC_R_NOSPACE;
1546: }
1547:
1548:
1549: /* Fetch the IA_NA contents. */
1550: if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
1551: ia, IA_NA_OFFSET)) {
1552: log_error("reply_process_ia_na: error evaluating ia");
1553: status = ISC_R_FAILURE;
1554: goto cleanup;
1555: }
1556:
1557: /* Extract IA_NA header contents. */
1558: iaid = getULong(ia_data.data);
1559: reply->renew = getULong(ia_data.data + 4);
1560: reply->rebind = getULong(ia_data.data + 8);
1561:
1562: /* Create an IA_NA structure. */
1563: if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
1564: reply->client_id.len, MDL) != ISC_R_SUCCESS) {
1565: log_error("reply_process_ia_na: no memory for ia.");
1566: status = ISC_R_NOMEMORY;
1567: goto cleanup;
1568: }
1569: reply->ia->ia_type = D6O_IA_NA;
1570:
1571: /* Cache pre-existing IA, if any. */
1572: ia_hash_lookup(&reply->old_ia, ia_na_active,
1573: (unsigned char *)reply->ia->iaid_duid.data,
1574: reply->ia->iaid_duid.len, MDL);
1575:
1576: /*
1577: * Create an option cache to carry the IA_NA option contents, and
1578: * execute any user-supplied values into it.
1579: */
1580: if (!option_state_allocate(&reply->reply_ia, MDL)) {
1581: status = ISC_R_NOMEMORY;
1582: goto cleanup;
1583: }
1584:
1585: /* Check & cache the fixed host record. */
1586: if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
1587: struct iaddr tmp_addr;
1588:
1589: if (!evaluate_option_cache(&reply->fixed, NULL, NULL, NULL,
1590: NULL, NULL, &global_scope,
1591: reply->host->fixed_addr, MDL)) {
1592: log_error("reply_process_ia_na: unable to evaluate "
1593: "fixed address.");
1594: status = ISC_R_FAILURE;
1595: goto cleanup;
1596: }
1597:
1598: if (reply->fixed.len < 16) {
1599: log_error("reply_process_ia_na: invalid fixed address.");
1600: status = ISC_R_INVALIDARG;
1601: goto cleanup;
1602: }
1603:
1604: /* Find the static lease's subnet. */
1605: tmp_addr.len = 16;
1606: memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
1607:
1608: if (find_grouped_subnet(&reply->subnet, reply->shared,
1609: tmp_addr, MDL) == 0)
1610: log_fatal("Impossible condition at %s:%d.", MDL);
1611:
1612: reply->static_lease = ISC_TRUE;
1613: } else
1614: reply->static_lease = ISC_FALSE;
1615:
1616: /*
1617: * Save the cursor position at the start of the IA, so we can
1618: * set length and adjust t1/t2 values later. We write a temporary
1619: * header out now just in case we decide to adjust the packet
1620: * within sub-process functions.
1621: */
1622: ia_cursor = reply->cursor;
1623:
1624: /* Initialize the IA_NA header. First the code. */
1625: putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_NA);
1626: reply->cursor += 2;
1627:
1628: /* Then option length. */
1629: putUShort(reply->buf.data + reply->cursor, 0x0Cu);
1630: reply->cursor += 2;
1631:
1632: /* Then IA_NA header contents; IAID. */
1633: putULong(reply->buf.data + reply->cursor, iaid);
1634: reply->cursor += 4;
1635:
1636: /* We store the client's t1 for now, and may over-ride it later. */
1637: putULong(reply->buf.data + reply->cursor, reply->renew);
1638: reply->cursor += 4;
1639:
1640: /* We store the client's t2 for now, and may over-ride it later. */
1641: putULong(reply->buf.data + reply->cursor, reply->rebind);
1642: reply->cursor += 4;
1643:
1644: /*
1645: * For each address in this IA_NA, decide what to do about it.
1646: *
1647: * Guidelines:
1648: *
1649: * The client leaves unchanged any infomation about addresses
1650: * it has recorded but are not included ("cancel/break" below).
1651: * A not included IA ("cleanup" below) could give a Renew/Rebind.
1652: */
1653: oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
1654: reply->valid = reply->prefer = 0xffffffff;
1655: reply->client_valid = reply->client_prefer = 0;
1656: for (; oc != NULL ; oc = oc->next) {
1657: status = reply_process_addr(reply, oc);
1658:
1659: /*
1660: * Canceled means we did not allocate addresses to the
1661: * client, but we're "done" with this IA - we set a status
1662: * code. So transmit this reply, e.g., move on to the next
1663: * IA.
1664: */
1665: if (status == ISC_R_CANCELED)
1666: break;
1667:
1668: if ((status != ISC_R_SUCCESS) &&
1669: (status != ISC_R_ADDRINUSE) &&
1670: (status != ISC_R_ADDRNOTAVAIL))
1671: goto cleanup;
1672: }
1673:
1674: reply->ia_count++;
1675:
1676: /*
1677: * If we fell through the above and never gave the client
1678: * an address, give it one now.
1679: */
1680: if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
1681: status = find_client_address(reply);
1682:
1683: if (status == ISC_R_NORESOURCES) {
1684: switch (reply->packet->dhcpv6_msg_type) {
1685: case DHCPV6_SOLICIT:
1686: /*
1687: * No address for any IA is handled
1688: * by the caller.
1689: */
1690: /* FALL THROUGH */
1691:
1692: case DHCPV6_REQUEST:
1693: /* Section 18.2.1 (Request):
1694: *
1695: * If the server cannot assign any addresses to
1696: * an IA in the message from the client, the
1697: * server MUST include the IA in the Reply
1698: * message with no addresses in the IA and a
1699: * Status Code option in the IA containing
1700: * status code NoAddrsAvail.
1701: */
1702: option_state_dereference(&reply->reply_ia, MDL);
1703: if (!option_state_allocate(&reply->reply_ia,
1704: MDL))
1705: {
1706: log_error("reply_process_ia_na: No "
1707: "memory for option state "
1708: "wipe.");
1709: status = ISC_R_NOMEMORY;
1710: goto cleanup;
1711: }
1712:
1713: if (!set_status_code(STATUS_NoAddrsAvail,
1714: "No addresses available "
1715: "for this interface.",
1716: reply->reply_ia)) {
1717: log_error("reply_process_ia_na: Unable "
1718: "to set NoAddrsAvail status "
1719: "code.");
1720: status = ISC_R_FAILURE;
1721: goto cleanup;
1722: }
1723:
1724: status = ISC_R_SUCCESS;
1725: break;
1726:
1727: default:
1728: /*
1729: * RFC 3315 does not tell us to emit a status
1730: * code in this condition, or anything else.
1731: *
1732: * If we included non-allocated addresses
1733: * (zeroed lifetimes) in an IA, then the client
1734: * will deconfigure them.
1735: *
1736: * So we want to include the IA even if we
1737: * can't give it a new address if it includes
1738: * zeroed lifetime addresses.
1739: *
1740: * We don't want to include the IA if we
1741: * provide zero addresses including zeroed
1742: * lifetimes.
1743: */
1744: if (reply->resources_included)
1745: status = ISC_R_SUCCESS;
1746: else
1747: goto cleanup;
1748: break;
1749: }
1750: }
1751:
1752: if (status != ISC_R_SUCCESS)
1753: goto cleanup;
1754: }
1755:
1756: reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
1757: sizeof(reply->buf) - reply->cursor,
1758: reply->reply_ia, reply->packet,
1759: required_opts_IA, NULL);
1760:
1761: /* Reset the length of this IA to match what was just written. */
1762: putUShort(reply->buf.data + ia_cursor + 2,
1763: reply->cursor - (ia_cursor + 4));
1764:
1765: /*
1766: * T1/T2 time selection is kind of weird. We actually use DHCP
1767: * (v4) scoped options as handy existing places where these might
1768: * be configured by an administrator. A value of zero tells the
1769: * client it may choose its own renewal time.
1770: */
1771: reply->renew = 0;
1772: oc = lookup_option(&dhcp_universe, reply->opt_state,
1773: DHO_DHCP_RENEWAL_TIME);
1774: if (oc != NULL) {
1775: if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
1776: reply->packet->options,
1777: reply->opt_state, &global_scope,
1778: oc, MDL) ||
1779: (data.len != 4)) {
1780: log_error("Invalid renewal time.");
1781: } else {
1782: reply->renew = getULong(data.data);
1783: }
1784:
1785: if (data.data != NULL)
1786: data_string_forget(&data, MDL);
1787: }
1788: putULong(reply->buf.data + ia_cursor + 8, reply->renew);
1789:
1790: /* Now T2. */
1791: reply->rebind = 0;
1792: oc = lookup_option(&dhcp_universe, reply->opt_state,
1793: DHO_DHCP_REBINDING_TIME);
1794: if (oc != NULL) {
1795: if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
1796: reply->packet->options,
1797: reply->opt_state, &global_scope,
1798: oc, MDL) ||
1799: (data.len != 4)) {
1800: log_error("Invalid rebinding time.");
1801: } else {
1802: reply->rebind = getULong(data.data);
1803: }
1804:
1805: if (data.data != NULL)
1806: data_string_forget(&data, MDL);
1807: }
1808: putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
1809:
1810: /*
1811: * If this is not a 'soft' binding, consume the new changes into
1812: * the database (if any have been attached to the ia_na).
1813: *
1814: * Loop through the assigned dynamic addresses, referencing the
1815: * leases onto this IA_NA rather than any old ones, and updating
1816: * pool timers for each (if any).
1817: */
1818: if ((status != ISC_R_CANCELED) && !reply->static_lease &&
1819: (reply->buf.reply.msg_type == DHCPV6_REPLY) &&
1820: (reply->ia->num_iasubopt != 0)) {
1821: struct iasubopt *tmp;
1822: struct data_string *ia_id;
1823: int i;
1824:
1825: for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
1826: tmp = reply->ia->iasubopt[i];
1827:
1828: if (tmp->ia != NULL)
1829: ia_dereference(&tmp->ia, MDL);
1830: ia_reference(&tmp->ia, reply->ia, MDL);
1831:
1832: /* Commit 'hard' bindings. */
1833: renew_lease6(tmp->ipv6_pool, tmp);
1834: schedule_lease_timeout(tmp->ipv6_pool);
1835:
1836: /*
1837: * Perform ddns updates.
1838: */
1839: oc = lookup_option(&server_universe, reply->opt_state,
1840: SV_DDNS_UPDATES);
1841: if ((oc == NULL) ||
1842: evaluate_boolean_option_cache(NULL, reply->packet,
1843: NULL, NULL,
1844: reply->packet->options,
1845: reply->opt_state,
1846: &tmp->scope,
1847: oc, MDL)) {
1848: ddns_updates(reply->packet, NULL, NULL,
1849: tmp, NULL, reply->opt_state);
1850: }
1851: }
1852:
1853: /* Remove any old ia from the hash. */
1854: if (reply->old_ia != NULL) {
1855: ia_id = &reply->old_ia->iaid_duid;
1856: ia_hash_delete(ia_na_active,
1857: (unsigned char *)ia_id->data,
1858: ia_id->len, MDL);
1859: ia_dereference(&reply->old_ia, MDL);
1860: }
1861:
1862: /* Put new ia into the hash. */
1863: reply->ia->cltt = cur_time;
1864: ia_id = &reply->ia->iaid_duid;
1865: ia_hash_add(ia_na_active, (unsigned char *)ia_id->data,
1866: ia_id->len, reply->ia, MDL);
1867:
1868: write_ia(reply->ia);
1869: }
1870:
1871: cleanup:
1872: if (packet_ia != NULL)
1873: option_state_dereference(&packet_ia, MDL);
1874: if (reply->reply_ia != NULL)
1875: option_state_dereference(&reply->reply_ia, MDL);
1876: if (ia_data.data != NULL)
1877: data_string_forget(&ia_data, MDL);
1878: if (data.data != NULL)
1879: data_string_forget(&data, MDL);
1880: if (reply->ia != NULL)
1881: ia_dereference(&reply->ia, MDL);
1882: if (reply->old_ia != NULL)
1883: ia_dereference(&reply->old_ia, MDL);
1884: if (reply->lease != NULL)
1885: iasubopt_dereference(&reply->lease, MDL);
1886: if (reply->fixed.data != NULL)
1887: data_string_forget(&reply->fixed, MDL);
1888: if (reply->subnet != NULL)
1889: subnet_dereference(&reply->subnet, MDL);
1890:
1891: /*
1892: * ISC_R_CANCELED is a status code used by the addr processing to
1893: * indicate we're replying with a status code. This is still a
1894: * success at higher layers.
1895: */
1896: return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
1897: }
1898:
1899: /*
1900: * Process an IAADDR within a given IA_xA, storing any IAADDR reply contents
1901: * into the reply's current ia-scoped option cache. Returns ISC_R_CANCELED
1902: * in the event we are replying with a status code and do not wish to process
1903: * more IAADDRs within this IA.
1904: */
1905: static isc_result_t
1906: reply_process_addr(struct reply_state *reply, struct option_cache *addr) {
1907: u_int32_t pref_life, valid_life;
1908: struct binding_scope **scope;
1909: struct group *group;
1910: struct subnet *subnet;
1911: struct iaddr tmp_addr;
1912: struct option_cache *oc;
1913: struct data_string iaaddr, data;
1914: isc_result_t status = ISC_R_SUCCESS;
1915:
1916: /* Initializes values that will be cleaned up. */
1917: memset(&iaaddr, 0, sizeof(iaaddr));
1918: memset(&data, 0, sizeof(data));
1919: /* Note that reply->lease may be set by address_is_owned() */
1920:
1921: /*
1922: * There is no point trying to process an incoming address if there
1923: * is no room for an outgoing address.
1924: */
1925: if ((reply->cursor + 28) > sizeof(reply->buf)) {
1926: log_error("reply_process_addr: Out of room for address.");
1927: return ISC_R_NOSPACE;
1928: }
1929:
1930: /* Extract this IAADDR option. */
1931: if (!evaluate_option_cache(&iaaddr, reply->packet, NULL, NULL,
1932: reply->packet->options, NULL, &global_scope,
1933: addr, MDL) ||
1934: (iaaddr.len < IAADDR_OFFSET)) {
1935: log_error("reply_process_addr: error evaluating IAADDR.");
1936: status = ISC_R_FAILURE;
1937: goto cleanup;
1938: }
1939:
1940: /* The first 16 bytes are the IPv6 address. */
1941: pref_life = getULong(iaaddr.data + 16);
1942: valid_life = getULong(iaaddr.data + 20);
1943:
1944: if ((reply->client_valid == 0) ||
1945: (reply->client_valid > valid_life))
1946: reply->client_valid = valid_life;
1947:
1948: if ((reply->client_prefer == 0) ||
1949: (reply->client_prefer > pref_life))
1950: reply->client_prefer = pref_life;
1951:
1952: /*
1953: * Clients may choose to send :: as an address, with the idea to give
1954: * hints about preferred-lifetime or valid-lifetime.
1955: */
1956: tmp_addr.len = 16;
1957: memset(tmp_addr.iabuf, 0, 16);
1958: if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
1959: /* Status remains success; we just ignore this one. */
1960: goto cleanup;
1961: }
1962:
1963: /* tmp_addr len remains 16 */
1964: memcpy(tmp_addr.iabuf, iaaddr.data, 16);
1965:
1966: /*
1967: * Verify that this address is on the client's network.
1968: */
1969: for (subnet = reply->shared->subnets ; subnet != NULL ;
1970: subnet = subnet->next_sibling) {
1971: if (addr_eq(subnet_number(tmp_addr, subnet->netmask),
1972: subnet->net))
1973: break;
1974: }
1975:
1976: /* Address not found on shared network. */
1977: if (subnet == NULL) {
1978: /* Ignore this address on 'soft' bindings. */
1979: if (reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
1980: /* disable rapid commit */
1981: reply->buf.reply.msg_type = DHCPV6_ADVERTISE;
1982: delete_option(&dhcpv6_universe,
1983: reply->opt_state,
1984: D6O_RAPID_COMMIT);
1985: /* status remains success */
1986: goto cleanup;
1987: }
1988:
1989: /*
1990: * RFC3315 section 18.2.1:
1991: *
1992: * If the server finds that the prefix on one or more IP
1993: * addresses in any IA in the message from the client is not
1994: * appropriate for the link to which the client is connected,
1995: * the server MUST return the IA to the client with a Status
1996: * Code option with the value NotOnLink.
1997: */
1998: if (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) {
1999: /* Rewind the IA_NA to empty. */
2000: option_state_dereference(&reply->reply_ia, MDL);
2001: if (!option_state_allocate(&reply->reply_ia, MDL)) {
2002: log_error("reply_process_addr: No memory for "
2003: "option state wipe.");
2004: status = ISC_R_NOMEMORY;
2005: goto cleanup;
2006: }
2007:
2008: /* Append a NotOnLink status code. */
2009: if (!set_status_code(STATUS_NotOnLink,
2010: "Address not for use on this "
2011: "link.", reply->reply_ia)) {
2012: log_error("reply_process_addr: Failure "
2013: "setting status code.");
2014: status = ISC_R_FAILURE;
2015: goto cleanup;
2016: }
2017:
2018: /* Fin (no more IAADDRs). */
2019: status = ISC_R_CANCELED;
2020: goto cleanup;
2021: }
2022:
2023: /*
2024: * RFC3315 sections 18.2.3 and 18.2.4 have identical language:
2025: *
2026: * If the server finds that any of the addresses are not
2027: * appropriate for the link to which the client is attached,
2028: * the server returns the address to the client with lifetimes
2029: * of 0.
2030: */
2031: if ((reply->packet->dhcpv6_msg_type != DHCPV6_RENEW) &&
2032: (reply->packet->dhcpv6_msg_type != DHCPV6_REBIND)) {
2033: log_error("It is impossible to lease a client that is "
2034: "not sending a solicit, request, renew, or "
2035: "rebind.");
2036: status = ISC_R_FAILURE;
2037: goto cleanup;
2038: }
2039:
2040: reply->send_prefer = reply->send_valid = 0;
2041: goto send_addr;
2042: }
2043:
2044: /* Verify the address belongs to the client. */
2045: if (!address_is_owned(reply, &tmp_addr)) {
2046: /*
2047: * For solicit and request, any addresses included are
2048: * 'requested' addresses. For rebind, we actually have
2049: * no direction on what to do from 3315 section 18.2.4!
2050: * So I think the best bet is to try and give it out, and if
2051: * we can't, zero lifetimes.
2052: */
2053: if ((reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) ||
2054: (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) ||
2055: (reply->packet->dhcpv6_msg_type == DHCPV6_REBIND)) {
2056: status = reply_process_try_addr(reply, &tmp_addr);
2057:
2058: /*
2059: * If the address is in use, or isn't in any dynamic
2060: * range, continue as normal. If any other error was
2061: * found, error out.
2062: */
2063: if ((status != ISC_R_SUCCESS) &&
2064: (status != ISC_R_ADDRINUSE) &&
2065: (status != ISC_R_ADDRNOTAVAIL))
2066: goto cleanup;
2067:
2068: /*
2069: * If we didn't honor this lease, for solicit and
2070: * request we simply omit it from our answer. For
2071: * rebind, we send it with zeroed lifetimes.
2072: */
2073: if (reply->lease == NULL) {
2074: if (reply->packet->dhcpv6_msg_type ==
2075: DHCPV6_REBIND) {
2076: reply->send_prefer = 0;
2077: reply->send_valid = 0;
2078: goto send_addr;
2079: }
2080:
2081: /* status remains success - ignore */
2082: goto cleanup;
2083: }
2084: /*
2085: * RFC3315 section 18.2.3:
2086: *
2087: * If the server cannot find a client entry for the IA the
2088: * server returns the IA containing no addresses with a Status
2089: * Code option set to NoBinding in the Reply message.
2090: *
2091: * On mismatch we (ab)use this pretending we have not the IA
2092: * as soon as we have not an address.
2093: */
2094: } else if (reply->packet->dhcpv6_msg_type == DHCPV6_RENEW) {
2095: /* Rewind the IA_NA to empty. */
2096: option_state_dereference(&reply->reply_ia, MDL);
2097: if (!option_state_allocate(&reply->reply_ia, MDL)) {
2098: log_error("reply_process_addr: No memory for "
2099: "option state wipe.");
2100: status = ISC_R_NOMEMORY;
2101: goto cleanup;
2102: }
2103:
2104: /* Append a NoBinding status code. */
2105: if (!set_status_code(STATUS_NoBinding,
2106: "Address not bound to this "
2107: "interface.", reply->reply_ia)) {
2108: log_error("reply_process_addr: Unable to "
2109: "attach status code.");
2110: status = ISC_R_FAILURE;
2111: goto cleanup;
2112: }
2113:
2114: /* Fin (no more IAADDRs). */
2115: status = ISC_R_CANCELED;
2116: goto cleanup;
2117: } else {
2118: log_error("It is impossible to lease a client that is "
2119: "not sending a solicit, request, renew, or "
2120: "rebind message.");
2121: status = ISC_R_FAILURE;
2122: goto cleanup;
2123: }
2124: }
2125:
2126: if (reply->static_lease) {
2127: if (reply->host == NULL)
2128: log_fatal("Impossible condition at %s:%d.", MDL);
2129:
2130: scope = &global_scope;
2131: group = reply->subnet->group;
2132: } else {
2133: if (reply->lease == NULL)
2134: log_fatal("Impossible condition at %s:%d.", MDL);
2135:
2136: scope = &reply->lease->scope;
2137: group = reply->lease->ipv6_pool->subnet->group;
2138: }
2139:
2140: /*
2141: * If client_resources is nonzero, then the reply_process_is_addressed
2142: * function has executed configuration state into the reply option
2143: * cache. We will use that valid cache to derive configuration for
2144: * whether or not to engage in additional addresses, and similar.
2145: */
2146: if (reply->client_resources != 0) {
2147: unsigned limit = 1;
2148:
2149: /*
2150: * Does this client have "enough" addresses already? Default
2151: * to one. Everybody gets one, and one should be enough for
2152: * anybody.
2153: */
2154: oc = lookup_option(&server_universe, reply->opt_state,
2155: SV_LIMIT_ADDRS_PER_IA);
2156: if (oc != NULL) {
2157: if (!evaluate_option_cache(&data, reply->packet,
2158: NULL, NULL,
2159: reply->packet->options,
2160: reply->opt_state,
2161: scope, oc, MDL) ||
2162: (data.len != 4)) {
2163: log_error("reply_process_addr: unable to "
2164: "evaluate addrs-per-ia value.");
2165: status = ISC_R_FAILURE;
2166: goto cleanup;
2167: }
2168:
2169: limit = getULong(data.data);
2170: data_string_forget(&data, MDL);
2171: }
2172:
2173: /*
2174: * If we wish to limit the client to a certain number of
2175: * addresses, then omit the address from the reply.
2176: */
2177: if (reply->client_resources >= limit)
2178: goto cleanup;
2179: }
2180:
2181: status = reply_process_is_addressed(reply, scope, group);
2182: if (status != ISC_R_SUCCESS)
2183: goto cleanup;
2184:
2185: send_addr:
2186: status = reply_process_send_addr(reply, &tmp_addr);
2187:
2188: cleanup:
2189: if (iaaddr.data != NULL)
2190: data_string_forget(&iaaddr, MDL);
2191: if (data.data != NULL)
2192: data_string_forget(&data, MDL);
2193: if (reply->lease != NULL)
2194: iasubopt_dereference(&reply->lease, MDL);
2195:
2196: return status;
2197: }
2198:
2199: /*
2200: * Verify the address belongs to the client. If we've got a host
2201: * record with a fixed address, it has to be the assigned address
2202: * (fault out all else). Otherwise it's a dynamic address, so lookup
2203: * that address and make sure it belongs to this DUID:IAID pair.
2204: */
2205: static isc_boolean_t
2206: address_is_owned(struct reply_state *reply, struct iaddr *addr) {
2207: int i;
2208:
2209: /*
2210: * This faults out addresses that don't match fixed addresses.
2211: */
2212: if (reply->static_lease) {
2213: if (reply->fixed.data == NULL)
2214: log_fatal("Impossible condition at %s:%d.", MDL);
2215:
2216: if (memcmp(addr->iabuf, reply->fixed.data, 16) == 0)
1.1.1.1 ! misho 2217: return (ISC_TRUE);
1.1 misho 2218:
1.1.1.1 ! misho 2219: return (ISC_FALSE);
1.1 misho 2220: }
2221:
2222: if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
1.1.1.1 ! misho 2223: return (ISC_FALSE);
1.1 misho 2224:
2225: for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2226: struct iasubopt *tmp;
2227:
2228: tmp = reply->old_ia->iasubopt[i];
2229:
2230: if (memcmp(addr->iabuf, &tmp->addr, 16) == 0) {
1.1.1.1 ! misho 2231: if (lease6_usable(tmp) == ISC_FALSE) {
! 2232: return (ISC_FALSE);
! 2233: }
1.1 misho 2234: iasubopt_reference(&reply->lease, tmp, MDL);
1.1.1.1 ! misho 2235: return (ISC_TRUE);
1.1 misho 2236: }
2237: }
2238:
1.1.1.1 ! misho 2239: return (ISC_FALSE);
1.1 misho 2240: }
2241:
2242: /* Process a client-supplied IA_TA. This may append options to the tail of
2243: * the reply packet being built in the reply_state structure.
2244: */
2245: static isc_result_t
2246: reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
2247: isc_result_t status = ISC_R_SUCCESS;
2248: u_int32_t iaid;
2249: unsigned ia_cursor;
2250: struct option_state *packet_ia;
2251: struct option_cache *oc;
2252: struct data_string ia_data, data;
2253: struct data_string iaaddr;
2254: u_int32_t pref_life, valid_life;
2255: struct iaddr tmp_addr;
2256:
2257: /* Initialize values that will get cleaned up on return. */
2258: packet_ia = NULL;
2259: memset(&ia_data, 0, sizeof(ia_data));
2260: memset(&data, 0, sizeof(data));
2261: memset(&iaaddr, 0, sizeof(iaaddr));
2262:
2263: /* Make sure there is at least room for the header. */
2264: if ((reply->cursor + IA_TA_OFFSET + 4) > sizeof(reply->buf)) {
2265: log_error("reply_process_ia_ta: Reply too long for IA.");
2266: return ISC_R_NOSPACE;
2267: }
2268:
2269:
2270: /* Fetch the IA_TA contents. */
2271: if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2272: ia, IA_TA_OFFSET)) {
2273: log_error("reply_process_ia_ta: error evaluating ia");
2274: status = ISC_R_FAILURE;
2275: goto cleanup;
2276: }
2277:
2278: /* Extract IA_TA header contents. */
2279: iaid = getULong(ia_data.data);
2280:
2281: /* Create an IA_TA structure. */
2282: if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
2283: reply->client_id.len, MDL) != ISC_R_SUCCESS) {
2284: log_error("reply_process_ia_ta: no memory for ia.");
2285: status = ISC_R_NOMEMORY;
2286: goto cleanup;
2287: }
2288: reply->ia->ia_type = D6O_IA_TA;
2289:
2290: /* Cache pre-existing IA, if any. */
2291: ia_hash_lookup(&reply->old_ia, ia_ta_active,
2292: (unsigned char *)reply->ia->iaid_duid.data,
2293: reply->ia->iaid_duid.len, MDL);
2294:
2295: /*
2296: * Create an option cache to carry the IA_TA option contents, and
2297: * execute any user-supplied values into it.
2298: */
2299: if (!option_state_allocate(&reply->reply_ia, MDL)) {
2300: status = ISC_R_NOMEMORY;
2301: goto cleanup;
2302: }
2303:
2304: /*
2305: * Temporary leases are dynamic by definition.
2306: */
2307: reply->static_lease = ISC_FALSE;
2308:
2309: /*
2310: * Save the cursor position at the start of the IA, so we can
2311: * set length later. We write a temporary
2312: * header out now just in case we decide to adjust the packet
2313: * within sub-process functions.
2314: */
2315: ia_cursor = reply->cursor;
2316:
2317: /* Initialize the IA_TA header. First the code. */
2318: putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_TA);
2319: reply->cursor += 2;
2320:
2321: /* Then option length. */
2322: putUShort(reply->buf.data + reply->cursor, 0x04u);
2323: reply->cursor += 2;
2324:
2325: /* Then IA_TA header contents; IAID. */
2326: putULong(reply->buf.data + reply->cursor, iaid);
2327: reply->cursor += 4;
2328:
2329: /*
2330: * Deal with an IAADDR for lifetimes.
2331: * For all or none, process IAADDRs as hints.
2332: */
2333: reply->valid = reply->prefer = 0xffffffff;
2334: reply->client_valid = reply->client_prefer = 0;
2335: oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
2336: for (; oc != NULL; oc = oc->next) {
2337: memset(&iaaddr, 0, sizeof(iaaddr));
2338: if (!evaluate_option_cache(&iaaddr, reply->packet,
2339: NULL, NULL,
2340: reply->packet->options, NULL,
2341: &global_scope, oc, MDL) ||
2342: (iaaddr.len < IAADDR_OFFSET)) {
2343: log_error("reply_process_ia_ta: error "
2344: "evaluating IAADDR.");
2345: status = ISC_R_FAILURE;
2346: goto cleanup;
2347: }
2348: /* The first 16 bytes are the IPv6 address. */
2349: pref_life = getULong(iaaddr.data + 16);
2350: valid_life = getULong(iaaddr.data + 20);
2351:
2352: if ((reply->client_valid == 0) ||
2353: (reply->client_valid > valid_life))
2354: reply->client_valid = valid_life;
2355:
2356: if ((reply->client_prefer == 0) ||
2357: (reply->client_prefer > pref_life))
2358: reply->client_prefer = pref_life;
2359:
2360: /* Nothing more if something has failed. */
2361: if (status == ISC_R_CANCELED)
2362: continue;
2363:
2364: tmp_addr.len = 16;
2365: memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2366: if (!temporary_is_available(reply, &tmp_addr))
2367: goto bad_temp;
2368: status = reply_process_is_addressed(reply,
2369: &reply->lease->scope,
2370: reply->shared->group);
2371: if (status != ISC_R_SUCCESS)
2372: goto bad_temp;
2373: status = reply_process_send_addr(reply, &tmp_addr);
2374: if (status != ISC_R_SUCCESS)
2375: goto bad_temp;
2376: if (reply->lease != NULL)
2377: iasubopt_dereference(&reply->lease, MDL);
2378: continue;
2379:
2380: bad_temp:
2381: /* Rewind the IA_TA to empty. */
2382: option_state_dereference(&reply->reply_ia, MDL);
2383: if (!option_state_allocate(&reply->reply_ia, MDL)) {
2384: status = ISC_R_NOMEMORY;
2385: goto cleanup;
2386: }
2387: status = ISC_R_CANCELED;
2388: reply->client_resources = 0;
2389: reply->resources_included = ISC_FALSE;
2390: if (reply->lease != NULL)
2391: iasubopt_dereference(&reply->lease, MDL);
2392: }
2393: reply->ia_count++;
2394:
2395: /*
2396: * Give the client temporary addresses.
2397: */
2398: if (reply->client_resources != 0)
2399: goto store;
2400: status = find_client_temporaries(reply);
2401: if (status == ISC_R_NORESOURCES) {
2402: switch (reply->packet->dhcpv6_msg_type) {
2403: case DHCPV6_SOLICIT:
2404: /*
2405: * No address for any IA is handled
2406: * by the caller.
2407: */
2408: /* FALL THROUGH */
2409:
2410: case DHCPV6_REQUEST:
2411: /* Section 18.2.1 (Request):
2412: *
2413: * If the server cannot assign any addresses to
2414: * an IA in the message from the client, the
2415: * server MUST include the IA in the Reply
2416: * message with no addresses in the IA and a
2417: * Status Code option in the IA containing
2418: * status code NoAddrsAvail.
2419: */
2420: option_state_dereference(&reply->reply_ia, MDL);
2421: if (!option_state_allocate(&reply->reply_ia, MDL)) {
2422: log_error("reply_process_ia_ta: No "
2423: "memory for option state wipe.");
2424: status = ISC_R_NOMEMORY;
2425: goto cleanup;
2426: }
2427:
2428: if (!set_status_code(STATUS_NoAddrsAvail,
2429: "No addresses available "
2430: "for this interface.",
2431: reply->reply_ia)) {
2432: log_error("reply_process_ia_ta: Unable "
2433: "to set NoAddrsAvail status code.");
2434: status = ISC_R_FAILURE;
2435: goto cleanup;
2436: }
2437:
2438: status = ISC_R_SUCCESS;
2439: break;
2440:
2441: default:
2442: /*
2443: * We don't want to include the IA if we
2444: * provide zero addresses including zeroed
2445: * lifetimes.
2446: */
2447: if (reply->resources_included)
2448: status = ISC_R_SUCCESS;
2449: else
2450: goto cleanup;
2451: break;
2452: }
2453: } else if (status != ISC_R_SUCCESS)
2454: goto cleanup;
2455:
2456: store:
2457: reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
2458: sizeof(reply->buf) - reply->cursor,
2459: reply->reply_ia, reply->packet,
2460: required_opts_IA, NULL);
2461:
2462: /* Reset the length of this IA to match what was just written. */
2463: putUShort(reply->buf.data + ia_cursor + 2,
2464: reply->cursor - (ia_cursor + 4));
2465:
2466: /*
2467: * Consume the new changes into the database (if any have been
2468: * attached to the ia_ta).
2469: *
2470: * Loop through the assigned dynamic addresses, referencing the
2471: * leases onto this IA_TA rather than any old ones, and updating
2472: * pool timers for each (if any).
2473: */
2474: if ((status != ISC_R_CANCELED) &&
2475: (reply->buf.reply.msg_type == DHCPV6_REPLY) &&
2476: (reply->ia->num_iasubopt != 0)) {
2477: struct iasubopt *tmp;
2478: struct data_string *ia_id;
2479: int i;
2480:
2481: for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2482: tmp = reply->ia->iasubopt[i];
2483:
2484: if (tmp->ia != NULL)
2485: ia_dereference(&tmp->ia, MDL);
2486: ia_reference(&tmp->ia, reply->ia, MDL);
2487:
2488: /* Commit 'hard' bindings. */
2489: renew_lease6(tmp->ipv6_pool, tmp);
2490: schedule_lease_timeout(tmp->ipv6_pool);
2491:
2492: /*
2493: * Perform ddns updates.
2494: */
2495: oc = lookup_option(&server_universe, reply->opt_state,
2496: SV_DDNS_UPDATES);
2497: if ((oc == NULL) ||
2498: evaluate_boolean_option_cache(NULL, reply->packet,
2499: NULL, NULL,
2500: reply->packet->options,
2501: reply->opt_state,
2502: &tmp->scope,
2503: oc, MDL)) {
2504: ddns_updates(reply->packet, NULL, NULL,
2505: tmp, NULL, reply->opt_state);
2506: }
2507: }
2508:
2509: /* Remove any old ia from the hash. */
2510: if (reply->old_ia != NULL) {
2511: ia_id = &reply->old_ia->iaid_duid;
2512: ia_hash_delete(ia_ta_active,
2513: (unsigned char *)ia_id->data,
2514: ia_id->len, MDL);
2515: ia_dereference(&reply->old_ia, MDL);
2516: }
2517:
2518: /* Put new ia into the hash. */
2519: reply->ia->cltt = cur_time;
2520: ia_id = &reply->ia->iaid_duid;
2521: ia_hash_add(ia_ta_active, (unsigned char *)ia_id->data,
2522: ia_id->len, reply->ia, MDL);
2523:
2524: write_ia(reply->ia);
2525: }
2526:
2527: cleanup:
2528: if (packet_ia != NULL)
2529: option_state_dereference(&packet_ia, MDL);
2530: if (iaaddr.data != NULL)
2531: data_string_forget(&iaaddr, MDL);
2532: if (reply->reply_ia != NULL)
2533: option_state_dereference(&reply->reply_ia, MDL);
2534: if (ia_data.data != NULL)
2535: data_string_forget(&ia_data, MDL);
2536: if (data.data != NULL)
2537: data_string_forget(&data, MDL);
2538: if (reply->ia != NULL)
2539: ia_dereference(&reply->ia, MDL);
2540: if (reply->old_ia != NULL)
2541: ia_dereference(&reply->old_ia, MDL);
2542: if (reply->lease != NULL)
2543: iasubopt_dereference(&reply->lease, MDL);
2544:
2545: /*
2546: * ISC_R_CANCELED is a status code used by the addr processing to
2547: * indicate we're replying with other addresses. This is still a
2548: * success at higher layers.
2549: */
2550: return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2551: }
2552:
2553: /*
2554: * Verify the temporary address is available.
2555: */
2556: static isc_boolean_t
2557: temporary_is_available(struct reply_state *reply, struct iaddr *addr) {
2558: struct in6_addr tmp_addr;
2559: struct subnet *subnet;
2560: struct ipv6_pool *pool;
2561: int i;
2562:
2563: memcpy(&tmp_addr, addr->iabuf, sizeof(tmp_addr));
2564: /*
2565: * Clients may choose to send :: as an address, with the idea to give
2566: * hints about preferred-lifetime or valid-lifetime.
2567: * So this is not a request for this address.
2568: */
2569: if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
2570: return ISC_FALSE;
2571:
2572: /*
2573: * Verify that this address is on the client's network.
2574: */
2575: for (subnet = reply->shared->subnets ; subnet != NULL ;
2576: subnet = subnet->next_sibling) {
2577: if (addr_eq(subnet_number(*addr, subnet->netmask),
2578: subnet->net))
2579: break;
2580: }
2581:
2582: /* Address not found on shared network. */
2583: if (subnet == NULL)
2584: return ISC_FALSE;
2585:
2586: /*
2587: * Check if this address is owned (must be before next step).
2588: */
2589: if (address_is_owned(reply, addr))
2590: return ISC_TRUE;
2591:
2592: /*
2593: * Verify that this address is in a temporary pool and try to get it.
2594: */
2595: if (reply->shared->ipv6_pools == NULL)
2596: return ISC_FALSE;
2597: for (i = 0 ; (pool = reply->shared->ipv6_pools[i]) != NULL ; i++) {
2598: if (pool->pool_type != D6O_IA_TA)
2599: continue;
2600: if (ipv6_in_pool(&tmp_addr, pool))
2601: break;
2602: }
2603: if (pool == NULL)
2604: return ISC_FALSE;
2605: if (lease6_exists(pool, &tmp_addr))
2606: return ISC_FALSE;
2607: if (iasubopt_allocate(&reply->lease, MDL) != ISC_R_SUCCESS)
2608: return ISC_FALSE;
2609: reply->lease->addr = tmp_addr;
2610: reply->lease->plen = 0;
2611: /* Default is soft binding for 2 minutes. */
2612: if (add_lease6(pool, reply->lease, cur_time + 120) != ISC_R_SUCCESS)
2613: return ISC_FALSE;
2614:
2615: return ISC_TRUE;
2616: }
2617:
2618: /*
2619: * Get a temporary address per prefix.
2620: */
2621: static isc_result_t
2622: find_client_temporaries(struct reply_state *reply) {
2623: struct shared_network *shared;
2624: int i;
2625: struct ipv6_pool *p;
2626: isc_result_t status;
2627: unsigned int attempts;
2628: struct iaddr send_addr;
2629:
2630: /*
2631: * No pools, we're done.
2632: */
2633: shared = reply->shared;
2634: if (shared->ipv6_pools == NULL) {
2635: log_debug("Unable to get client addresses: "
2636: "no IPv6 pools on this shared network");
2637: return ISC_R_NORESOURCES;
2638: }
2639:
2640: status = ISC_R_NORESOURCES;
2641: for (i = 0;; i++) {
2642: p = shared->ipv6_pools[i];
2643: if (p == NULL) {
2644: break;
2645: }
2646: if (p->pool_type != D6O_IA_TA) {
2647: continue;
2648: }
2649:
2650: /*
2651: * Get an address in this temporary pool.
2652: */
2653: status = create_lease6(p, &reply->lease, &attempts,
2654: &reply->client_id, cur_time + 120);
2655: if (status != ISC_R_SUCCESS) {
2656: log_debug("Unable to get a temporary address.");
2657: goto cleanup;
2658: }
2659:
2660: status = reply_process_is_addressed(reply,
2661: &reply->lease->scope,
2662: reply->lease->ipv6_pool->subnet->group);
2663: if (status != ISC_R_SUCCESS) {
2664: goto cleanup;
2665: }
2666: send_addr.len = 16;
2667: memcpy(send_addr.iabuf, &reply->lease->addr, 16);
2668: status = reply_process_send_addr(reply, &send_addr);
2669: if (status != ISC_R_SUCCESS) {
2670: goto cleanup;
2671: }
2672: if (reply->lease != NULL) {
2673: iasubopt_dereference(&reply->lease, MDL);
2674: }
2675: }
2676:
2677: cleanup:
2678: if (reply->lease != NULL) {
2679: iasubopt_dereference(&reply->lease, MDL);
2680: }
2681: return status;
2682: }
2683:
2684: /*
2685: * This function only returns failure on 'hard' failures. If it succeeds,
2686: * it will leave a lease structure behind.
2687: */
2688: static isc_result_t
2689: reply_process_try_addr(struct reply_state *reply, struct iaddr *addr) {
1.1.1.1 ! misho 2690: isc_result_t status = ISC_R_ADDRNOTAVAIL;
1.1 misho 2691: struct ipv6_pool *pool;
2692: int i;
2693: struct data_string data_addr;
2694:
2695: if ((reply == NULL) || (reply->shared == NULL) ||
1.1.1.1 ! misho 2696: (addr == NULL) || (reply->lease != NULL))
1.1 misho 2697: return ISC_R_INVALIDARG;
2698:
1.1.1.1 ! misho 2699: if (reply->shared->ipv6_pools == NULL)
! 2700: return (ISC_R_ADDRNOTAVAIL);
! 2701:
1.1 misho 2702: memset(&data_addr, 0, sizeof(data_addr));
2703: data_addr.len = addr->len;
2704: data_addr.data = addr->iabuf;
2705:
2706: for (i = 0 ; (pool = reply->shared->ipv6_pools[i]) != NULL ; i++) {
2707: if (pool->pool_type != D6O_IA_NA)
2708: continue;
2709: status = try_client_v6_address(&reply->lease, pool,
2710: &data_addr);
2711: if (status == ISC_R_SUCCESS)
2712: break;
2713: }
2714:
2715: /* Note that this is just pedantry. There is no allocation to free. */
2716: data_string_forget(&data_addr, MDL);
2717: /* Return just the most recent status... */
1.1.1.1 ! misho 2718: return (status);
1.1 misho 2719: }
2720:
2721: /* Look around for an address to give the client. First, look through the
2722: * old IA for addresses we can extend. Second, try to allocate a new address.
2723: * Finally, actually add that address into the current reply IA.
2724: */
2725: static isc_result_t
2726: find_client_address(struct reply_state *reply) {
2727: struct iaddr send_addr;
2728: isc_result_t status = ISC_R_NORESOURCES;
2729: struct iasubopt *lease, *best_lease = NULL;
2730: struct binding_scope **scope;
2731: struct group *group;
2732: int i;
2733:
2734: if (reply->static_lease) {
2735: if (reply->host == NULL)
2736: return ISC_R_INVALIDARG;
2737:
2738: send_addr.len = 16;
2739: memcpy(send_addr.iabuf, reply->fixed.data, 16);
2740:
2741: status = ISC_R_SUCCESS;
2742: scope = &global_scope;
2743: group = reply->subnet->group;
2744: goto send_addr;
2745: }
2746:
2747: if (reply->old_ia != NULL) {
2748: for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2749: struct shared_network *candidate_shared;
2750:
2751: lease = reply->old_ia->iasubopt[i];
2752: candidate_shared = lease->ipv6_pool->shared_network;
2753:
2754: /*
2755: * Look for the best lease on the client's shared
2756: * network.
2757: */
1.1.1.1 ! misho 2758: if ((candidate_shared == reply->shared) &&
! 2759: (lease6_usable(lease) == ISC_TRUE)) {
1.1 misho 2760: best_lease = lease_compare(lease, best_lease);
2761: }
2762: }
2763: }
2764:
2765: /* Try to pick a new address if we didn't find one, or if we found an
2766: * abandoned lease.
2767: */
2768: if ((best_lease == NULL) || (best_lease->state == FTS_ABANDONED)) {
2769: status = pick_v6_address(&reply->lease, reply->shared,
1.1.1.1 ! misho 2770: &reply->ia->iaid_duid);
1.1 misho 2771: } else if (best_lease != NULL) {
2772: iasubopt_reference(&reply->lease, best_lease, MDL);
2773: status = ISC_R_SUCCESS;
2774: }
2775:
2776: /* Pick the abandoned lease as a last resort. */
2777: if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
2778: /* I don't see how this is supposed to be done right now. */
2779: log_error("Reclaiming abandoned addresses is not yet "
2780: "supported. Treating this as an out of space "
2781: "condition.");
2782: /* iasubopt_reference(&reply->lease, best_lease, MDL); */
2783: }
2784:
2785: /* Give up now if we didn't find a lease. */
2786: if (status != ISC_R_SUCCESS)
2787: return status;
2788:
2789: if (reply->lease == NULL)
2790: log_fatal("Impossible condition at %s:%d.", MDL);
2791:
2792: /* Draw binding scopes from the lease's binding scope, and config
2793: * from the lease's containing subnet and higher. Note that it may
2794: * be desirable to place the group attachment directly in the pool.
2795: */
2796: scope = &reply->lease->scope;
2797: group = reply->lease->ipv6_pool->subnet->group;
2798:
2799: send_addr.len = 16;
2800: memcpy(send_addr.iabuf, &reply->lease->addr, 16);
2801:
2802: send_addr:
2803: status = reply_process_is_addressed(reply, scope, group);
2804: if (status != ISC_R_SUCCESS)
2805: return status;
2806:
2807: status = reply_process_send_addr(reply, &send_addr);
2808: return status;
2809: }
2810:
2811: /* Once an address is found for a client, perform several common functions;
2812: * Calculate and store valid and preferred lease times, draw client options
2813: * into the option state.
2814: */
2815: static isc_result_t
2816: reply_process_is_addressed(struct reply_state *reply,
2817: struct binding_scope **scope, struct group *group)
2818: {
2819: isc_result_t status = ISC_R_SUCCESS;
2820: struct data_string data;
2821: struct option_cache *oc;
2822:
2823: /* Initialize values we will cleanup. */
2824: memset(&data, 0, sizeof(data));
2825:
2826: /*
2827: * Bring configured options into the root packet level cache - start
2828: * with the lease's closest enclosing group (passed in by the caller
2829: * as 'group').
2830: */
2831: execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
2832: reply->packet->options, reply->opt_state,
2833: scope, group, root_group);
2834:
2835: /*
2836: * If there is a host record, over-ride with values configured there,
2837: * without re-evaluating configuration from the previously executed
2838: * group or its common enclosers.
2839: */
2840: if (reply->host != NULL)
2841: execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
2842: reply->packet->options,
2843: reply->opt_state, scope,
2844: reply->host->group, group);
2845:
2846: /* Determine valid lifetime. */
2847: if (reply->client_valid == 0)
2848: reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
2849: else
2850: reply->send_valid = reply->client_valid;
2851:
2852: oc = lookup_option(&server_universe, reply->opt_state,
2853: SV_DEFAULT_LEASE_TIME);
2854: if (oc != NULL) {
2855: if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
2856: reply->packet->options,
2857: reply->opt_state,
2858: scope, oc, MDL) ||
2859: (data.len != 4)) {
2860: log_error("reply_process_is_addressed: unable to "
2861: "evaluate default lease time");
2862: status = ISC_R_FAILURE;
2863: goto cleanup;
2864: }
2865:
2866: reply->send_valid = getULong(data.data);
2867: data_string_forget(&data, MDL);
2868: }
2869:
2870: if (reply->client_prefer == 0)
2871: reply->send_prefer = reply->send_valid;
2872: else
2873: reply->send_prefer = reply->client_prefer;
2874:
2875: if (reply->send_prefer >= reply->send_valid)
2876: reply->send_prefer = (reply->send_valid / 2) +
2877: (reply->send_valid / 8);
2878:
2879: oc = lookup_option(&server_universe, reply->opt_state,
2880: SV_PREFER_LIFETIME);
2881: if (oc != NULL) {
2882: if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
2883: reply->packet->options,
2884: reply->opt_state,
2885: scope, oc, MDL) ||
2886: (data.len != 4)) {
2887: log_error("reply_process_is_addressed: unable to "
2888: "evaluate preferred lease time");
2889: status = ISC_R_FAILURE;
2890: goto cleanup;
2891: }
2892:
2893: reply->send_prefer = getULong(data.data);
2894: data_string_forget(&data, MDL);
2895: }
2896:
2897: /* Note lowest values for later calculation of renew/rebind times. */
2898: if (reply->prefer > reply->send_prefer)
2899: reply->prefer = reply->send_prefer;
2900:
2901: if (reply->valid > reply->send_valid)
2902: reply->valid = reply->send_valid;
2903:
2904: #if 0
2905: /*
2906: * XXX: Old 4.0.0 alpha code would change the host {} record
2907: * XXX: uid upon lease assignment. This was intended to cover the
2908: * XXX: case where a client first identifies itself using vendor
2909: * XXX: options in a solicit, or request, but later neglects to include
2910: * XXX: these options in a Renew or Rebind. It is not clear that this
2911: * XXX: is required, and has some startling ramifications (such as
2912: * XXX: how to recover this dynamic host {} state across restarts).
2913: */
2914: if (reply->host != NULL)
2915: change_host_uid(host, reply->client_id->data,
2916: reply->client_id->len);
2917: #endif /* 0 */
2918:
2919: /* Perform dynamic lease related update work. */
2920: if (reply->lease != NULL) {
2921: /* Cached lifetimes */
2922: reply->lease->prefer = reply->send_prefer;
2923: reply->lease->valid = reply->send_valid;
2924:
2925: /* Advance (or rewind) the valid lifetime. */
2926: if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
2927: reply->lease->soft_lifetime_end_time =
2928: cur_time + reply->send_valid;
2929: /* Wait before renew! */
2930: }
2931:
2932: status = ia_add_iasubopt(reply->ia, reply->lease, MDL);
2933: if (status != ISC_R_SUCCESS) {
2934: log_fatal("reply_process_is_addressed: Unable to "
2935: "attach lease to new IA: %s",
2936: isc_result_totext(status));
2937: }
2938:
2939: /*
2940: * If this is a new lease, make sure it is attached somewhere.
2941: */
2942: if (reply->lease->ia == NULL) {
2943: ia_reference(&reply->lease->ia, reply->ia, MDL);
2944: }
2945: }
2946:
2947: /* Bring a copy of the relevant options into the IA scope. */
2948: execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
2949: reply->packet->options, reply->reply_ia,
2950: scope, group, root_group);
2951:
2952: /*
2953: * And bring in host record configuration, if any, but not to overlap
2954: * the previous group or its common enclosers.
2955: */
2956: if (reply->host != NULL)
2957: execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
2958: reply->packet->options,
2959: reply->reply_ia, scope,
2960: reply->host->group, group);
2961:
2962: cleanup:
2963: if (data.data != NULL)
2964: data_string_forget(&data, MDL);
2965:
2966: if (status == ISC_R_SUCCESS)
2967: reply->client_resources++;
2968:
2969: return status;
2970: }
2971:
2972: /* Simply send an IAADDR within the IA scope as described. */
2973: static isc_result_t
2974: reply_process_send_addr(struct reply_state *reply, struct iaddr *addr) {
2975: isc_result_t status = ISC_R_SUCCESS;
2976: struct data_string data;
2977:
2978: memset(&data, 0, sizeof(data));
2979:
2980: /* Now append the lease. */
2981: data.len = IAADDR_OFFSET;
2982: if (!buffer_allocate(&data.buffer, data.len, MDL)) {
2983: log_error("reply_process_send_addr: out of memory"
2984: "allocating new IAADDR buffer.");
2985: status = ISC_R_NOMEMORY;
2986: goto cleanup;
2987: }
2988: data.data = data.buffer->data;
2989:
2990: memcpy(data.buffer->data, addr->iabuf, 16);
2991: putULong(data.buffer->data + 16, reply->send_prefer);
2992: putULong(data.buffer->data + 20, reply->send_valid);
2993:
2994: if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
2995: data.buffer, data.buffer->data,
2996: data.len, D6O_IAADDR, 0)) {
2997: log_error("reply_process_send_addr: unable "
2998: "to save IAADDR option");
2999: status = ISC_R_FAILURE;
3000: goto cleanup;
3001: }
3002:
3003: reply->resources_included = ISC_TRUE;
3004:
3005: cleanup:
3006: if (data.data != NULL)
3007: data_string_forget(&data, MDL);
3008:
3009: return status;
3010: }
3011:
3012: /* Choose the better of two leases. */
3013: static struct iasubopt *
3014: lease_compare(struct iasubopt *alpha, struct iasubopt *beta) {
3015: if (alpha == NULL)
3016: return beta;
3017: if (beta == NULL)
3018: return alpha;
3019:
3020: switch(alpha->state) {
3021: case FTS_ACTIVE:
3022: switch(beta->state) {
3023: case FTS_ACTIVE:
3024: /* Choose the lease with the longest lifetime (most
3025: * likely the most recently allocated).
3026: */
3027: if (alpha->hard_lifetime_end_time <
3028: beta->hard_lifetime_end_time)
3029: return beta;
3030: else
3031: return alpha;
3032:
3033: case FTS_EXPIRED:
3034: case FTS_ABANDONED:
3035: return alpha;
3036:
3037: default:
3038: log_fatal("Impossible condition at %s:%d.", MDL);
3039: }
3040: break;
3041:
3042: case FTS_EXPIRED:
3043: switch (beta->state) {
3044: case FTS_ACTIVE:
3045: return beta;
3046:
3047: case FTS_EXPIRED:
3048: /* Choose the most recently expired lease. */
3049: if (alpha->hard_lifetime_end_time <
3050: beta->hard_lifetime_end_time)
3051: return beta;
3052: else if ((alpha->hard_lifetime_end_time ==
3053: beta->hard_lifetime_end_time) &&
3054: (alpha->soft_lifetime_end_time <
3055: beta->soft_lifetime_end_time))
3056: return beta;
3057: else
3058: return alpha;
3059:
3060: case FTS_ABANDONED:
3061: return alpha;
3062:
3063: default:
3064: log_fatal("Impossible condition at %s:%d.", MDL);
3065: }
3066: break;
3067:
3068: case FTS_ABANDONED:
3069: switch (beta->state) {
3070: case FTS_ACTIVE:
3071: case FTS_EXPIRED:
3072: return alpha;
3073:
3074: case FTS_ABANDONED:
3075: /* Choose the lease that was abandoned longest ago. */
3076: if (alpha->hard_lifetime_end_time <
3077: beta->hard_lifetime_end_time)
3078: return alpha;
3079:
3080: default:
3081: log_fatal("Impossible condition at %s:%d.", MDL);
3082: }
3083: break;
3084:
3085: default:
3086: log_fatal("Impossible condition at %s:%d.", MDL);
3087: }
3088:
3089: log_fatal("Triple impossible condition at %s:%d.", MDL);
3090: return NULL;
3091: }
3092:
3093: /* Process a client-supplied IA_PD. This may append options to the tail of
3094: * the reply packet being built in the reply_state structure.
3095: */
3096: static isc_result_t
3097: reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
3098: isc_result_t status = ISC_R_SUCCESS;
3099: u_int32_t iaid;
3100: unsigned ia_cursor;
3101: struct option_state *packet_ia;
3102: struct option_cache *oc;
3103: struct data_string ia_data, data;
3104:
3105: /* Initialize values that will get cleaned up on return. */
3106: packet_ia = NULL;
3107: memset(&ia_data, 0, sizeof(ia_data));
3108: memset(&data, 0, sizeof(data));
3109: /*
3110: * Note that find_client_prefix() may set reply->lease.
3111: */
3112:
3113: /* Make sure there is at least room for the header. */
3114: if ((reply->cursor + IA_PD_OFFSET + 4) > sizeof(reply->buf)) {
3115: log_error("reply_process_ia_pd: Reply too long for IA.");
3116: return ISC_R_NOSPACE;
3117: }
3118:
3119:
3120: /* Fetch the IA_PD contents. */
3121: if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
3122: ia, IA_PD_OFFSET)) {
3123: log_error("reply_process_ia_pd: error evaluating ia");
3124: status = ISC_R_FAILURE;
3125: goto cleanup;
3126: }
3127:
3128: /* Extract IA_PD header contents. */
3129: iaid = getULong(ia_data.data);
3130: reply->renew = getULong(ia_data.data + 4);
3131: reply->rebind = getULong(ia_data.data + 8);
3132:
3133: /* Create an IA_PD structure. */
3134: if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
3135: reply->client_id.len, MDL) != ISC_R_SUCCESS) {
3136: log_error("reply_process_ia_pd: no memory for ia.");
3137: status = ISC_R_NOMEMORY;
3138: goto cleanup;
3139: }
3140: reply->ia->ia_type = D6O_IA_PD;
3141:
3142: /* Cache pre-existing IA_PD, if any. */
3143: ia_hash_lookup(&reply->old_ia, ia_pd_active,
3144: (unsigned char *)reply->ia->iaid_duid.data,
3145: reply->ia->iaid_duid.len, MDL);
3146:
3147: /*
3148: * Create an option cache to carry the IA_PD option contents, and
3149: * execute any user-supplied values into it.
3150: */
3151: if (!option_state_allocate(&reply->reply_ia, MDL)) {
3152: status = ISC_R_NOMEMORY;
3153: goto cleanup;
3154: }
3155:
3156: /* Check & count the fixed prefix host records. */
3157: reply->static_prefixes = 0;
3158: if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
3159: struct iaddrcidrnetlist *fp;
3160:
3161: for (fp = reply->host->fixed_prefix; fp != NULL;
3162: fp = fp->next) {
3163: reply->static_prefixes += 1;
3164: }
3165: }
3166:
3167: /*
3168: * Save the cursor position at the start of the IA_PD, so we can
3169: * set length and adjust t1/t2 values later. We write a temporary
3170: * header out now just in case we decide to adjust the packet
3171: * within sub-process functions.
3172: */
3173: ia_cursor = reply->cursor;
3174:
3175: /* Initialize the IA_PD header. First the code. */
3176: putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_PD);
3177: reply->cursor += 2;
3178:
3179: /* Then option length. */
3180: putUShort(reply->buf.data + reply->cursor, 0x0Cu);
3181: reply->cursor += 2;
3182:
3183: /* Then IA_PD header contents; IAID. */
3184: putULong(reply->buf.data + reply->cursor, iaid);
3185: reply->cursor += 4;
3186:
3187: /* We store the client's t1 for now, and may over-ride it later. */
3188: putULong(reply->buf.data + reply->cursor, reply->renew);
3189: reply->cursor += 4;
3190:
3191: /* We store the client's t2 for now, and may over-ride it later. */
3192: putULong(reply->buf.data + reply->cursor, reply->rebind);
3193: reply->cursor += 4;
3194:
3195: /*
3196: * For each prefix in this IA_PD, decide what to do about it.
3197: */
3198: oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAPREFIX);
3199: reply->valid = reply->prefer = 0xffffffff;
3200: reply->client_valid = reply->client_prefer = 0;
3201: reply->preflen = -1;
3202: for (; oc != NULL ; oc = oc->next) {
3203: status = reply_process_prefix(reply, oc);
3204:
3205: /*
3206: * Canceled means we did not allocate prefixes to the
3207: * client, but we're "done" with this IA - we set a status
3208: * code. So transmit this reply, e.g., move on to the next
3209: * IA.
3210: */
3211: if (status == ISC_R_CANCELED)
3212: break;
3213:
1.1.1.1 ! misho 3214: if ((status != ISC_R_SUCCESS) &&
! 3215: (status != ISC_R_ADDRINUSE) &&
! 3216: (status != ISC_R_ADDRNOTAVAIL))
1.1 misho 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: renew_lease6(tmp->ipv6_pool, tmp);
3357: schedule_lease_timeout(tmp->ipv6_pool);
3358: }
3359:
3360: /* Remove any old ia from the hash. */
3361: if (reply->old_ia != NULL) {
3362: ia_id = &reply->old_ia->iaid_duid;
3363: ia_hash_delete(ia_pd_active,
3364: (unsigned char *)ia_id->data,
3365: ia_id->len, MDL);
3366: ia_dereference(&reply->old_ia, MDL);
3367: }
3368:
3369: /* Put new ia into the hash. */
3370: reply->ia->cltt = cur_time;
3371: ia_id = &reply->ia->iaid_duid;
3372: ia_hash_add(ia_pd_active, (unsigned char *)ia_id->data,
3373: ia_id->len, reply->ia, MDL);
3374:
3375: write_ia(reply->ia);
3376: }
3377:
3378: cleanup:
3379: if (packet_ia != NULL)
3380: option_state_dereference(&packet_ia, MDL);
3381: if (reply->reply_ia != NULL)
3382: option_state_dereference(&reply->reply_ia, MDL);
3383: if (ia_data.data != NULL)
3384: data_string_forget(&ia_data, MDL);
3385: if (data.data != NULL)
3386: data_string_forget(&data, MDL);
3387: if (reply->ia != NULL)
3388: ia_dereference(&reply->ia, MDL);
3389: if (reply->old_ia != NULL)
3390: ia_dereference(&reply->old_ia, MDL);
3391: if (reply->lease != NULL)
3392: iasubopt_dereference(&reply->lease, MDL);
3393:
3394: /*
3395: * ISC_R_CANCELED is a status code used by the prefix processing to
3396: * indicate we're replying with a status code. This is still a
3397: * success at higher layers.
3398: */
3399: return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
3400: }
3401:
3402: /*
3403: * Process an IAPREFIX within a given IA_PD, storing any IAPREFIX reply
3404: * contents into the reply's current ia_pd-scoped option cache. Returns
3405: * ISC_R_CANCELED in the event we are replying with a status code and do
3406: * not wish to process more IAPREFIXes within this IA_PD.
3407: */
3408: static isc_result_t
3409: reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
3410: u_int32_t pref_life, valid_life;
3411: struct binding_scope **scope;
3412: struct iaddrcidrnet tmp_pref;
3413: struct option_cache *oc;
3414: struct data_string iapref, data;
3415: isc_result_t status = ISC_R_SUCCESS;
3416:
3417: /* Initializes values that will be cleaned up. */
3418: memset(&iapref, 0, sizeof(iapref));
3419: memset(&data, 0, sizeof(data));
3420: /* Note that reply->lease may be set by prefix_is_owned() */
3421:
3422: /*
3423: * There is no point trying to process an incoming prefix if there
3424: * is no room for an outgoing prefix.
3425: */
3426: if ((reply->cursor + 29) > sizeof(reply->buf)) {
3427: log_error("reply_process_prefix: Out of room for prefix.");
3428: return ISC_R_NOSPACE;
3429: }
3430:
3431: /* Extract this IAPREFIX option. */
3432: if (!evaluate_option_cache(&iapref, reply->packet, NULL, NULL,
3433: reply->packet->options, NULL, &global_scope,
3434: pref, MDL) ||
3435: (iapref.len < IAPREFIX_OFFSET)) {
3436: log_error("reply_process_prefix: error evaluating IAPREFIX.");
3437: status = ISC_R_FAILURE;
3438: goto cleanup;
3439: }
3440:
3441: /*
3442: * Layout: preferred and valid lifetimes followed by the prefix
3443: * length and the IPv6 address.
3444: */
3445: pref_life = getULong(iapref.data);
3446: valid_life = getULong(iapref.data + 4);
3447:
3448: if ((reply->client_valid == 0) ||
3449: (reply->client_valid > valid_life))
3450: reply->client_valid = valid_life;
3451:
3452: if ((reply->client_prefer == 0) ||
3453: (reply->client_prefer > pref_life))
3454: reply->client_prefer = pref_life;
3455:
3456: /*
3457: * Clients may choose to send ::/0 as a prefix, with the idea to give
3458: * hints about preferred-lifetime or valid-lifetime.
3459: */
3460: tmp_pref.lo_addr.len = 16;
3461: memset(tmp_pref.lo_addr.iabuf, 0, 16);
3462: if ((iapref.data[8] == 0) &&
3463: (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
3464: /* Status remains success; we just ignore this one. */
3465: goto cleanup;
3466: }
3467:
3468: /*
3469: * Clients may choose to send ::/X as a prefix to specify a
3470: * preferred/requested prefix length. Note X is never zero here.
3471: */
3472: tmp_pref.bits = (int) iapref.data[8];
3473: if (reply->preflen < 0) {
3474: /* Cache the first preferred prefix length. */
3475: reply->preflen = tmp_pref.bits;
3476: }
3477: if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
3478: goto cleanup;
3479: }
3480:
3481: memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
3482:
3483: /* Verify the prefix belongs to the client. */
3484: if (!prefix_is_owned(reply, &tmp_pref)) {
3485: /* Same than for addresses. */
3486: if ((reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) ||
3487: (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) ||
3488: (reply->packet->dhcpv6_msg_type == DHCPV6_REBIND)) {
3489: status = reply_process_try_prefix(reply, &tmp_pref);
3490:
3491: /* Either error out or skip this prefix. */
1.1.1.1 ! misho 3492: if ((status != ISC_R_SUCCESS) &&
! 3493: (status != ISC_R_ADDRINUSE) &&
! 3494: (status != ISC_R_ADDRNOTAVAIL))
1.1 misho 3495: goto cleanup;
3496:
3497: if (reply->lease == NULL) {
3498: if (reply->packet->dhcpv6_msg_type ==
3499: DHCPV6_REBIND) {
3500: reply->send_prefer = 0;
3501: reply->send_valid = 0;
3502: goto send_pref;
3503: }
3504:
3505: /* status remains success - ignore */
3506: goto cleanup;
3507: }
3508: /*
3509: * RFC3633 section 18.2.3:
3510: *
3511: * If the delegating router cannot find a binding
3512: * for the requesting router's IA_PD the delegating
3513: * router returns the IA_PD containing no prefixes
3514: * with a Status Code option set to NoBinding in the
3515: * Reply message.
3516: *
3517: * On mismatch we (ab)use this pretending we have not the IA
3518: * as soon as we have not a prefix.
3519: */
3520: } else if (reply->packet->dhcpv6_msg_type == DHCPV6_RENEW) {
3521: /* Rewind the IA_PD to empty. */
3522: option_state_dereference(&reply->reply_ia, MDL);
3523: if (!option_state_allocate(&reply->reply_ia, MDL)) {
3524: log_error("reply_process_prefix: No memory "
3525: "for option state wipe.");
3526: status = ISC_R_NOMEMORY;
3527: goto cleanup;
3528: }
3529:
3530: /* Append a NoBinding status code. */
3531: if (!set_status_code(STATUS_NoBinding,
3532: "Prefix not bound to this "
3533: "interface.", reply->reply_ia)) {
3534: log_error("reply_process_prefix: Unable to "
3535: "attach status code.");
3536: status = ISC_R_FAILURE;
3537: goto cleanup;
3538: }
3539:
3540: /* Fin (no more IAPREFIXes). */
3541: status = ISC_R_CANCELED;
3542: goto cleanup;
3543: } else {
3544: log_error("It is impossible to lease a client that is "
3545: "not sending a solicit, request, renew, or "
3546: "rebind message.");
3547: status = ISC_R_FAILURE;
3548: goto cleanup;
3549: }
3550: }
3551:
3552: if (reply->static_prefixes > 0) {
3553: if (reply->host == NULL)
3554: log_fatal("Impossible condition at %s:%d.", MDL);
3555:
3556: scope = &global_scope;
3557: } else {
3558: if (reply->lease == NULL)
3559: log_fatal("Impossible condition at %s:%d.", MDL);
3560:
3561: scope = &reply->lease->scope;
3562: }
3563:
3564: /*
3565: * If client_resources is nonzero, then the reply_process_is_prefixed
3566: * function has executed configuration state into the reply option
3567: * cache. We will use that valid cache to derive configuration for
3568: * whether or not to engage in additional prefixes, and similar.
3569: */
3570: if (reply->client_resources != 0) {
3571: unsigned limit = 1;
3572:
3573: /*
3574: * Does this client have "enough" prefixes already? Default
3575: * to one. Everybody gets one, and one should be enough for
3576: * anybody.
3577: */
3578: oc = lookup_option(&server_universe, reply->opt_state,
3579: SV_LIMIT_PREFS_PER_IA);
3580: if (oc != NULL) {
3581: if (!evaluate_option_cache(&data, reply->packet,
3582: NULL, NULL,
3583: reply->packet->options,
3584: reply->opt_state,
3585: scope, oc, MDL) ||
3586: (data.len != 4)) {
3587: log_error("reply_process_prefix: unable to "
3588: "evaluate prefs-per-ia value.");
3589: status = ISC_R_FAILURE;
3590: goto cleanup;
3591: }
3592:
3593: limit = getULong(data.data);
3594: data_string_forget(&data, MDL);
3595: }
3596:
3597: /*
3598: * If we wish to limit the client to a certain number of
3599: * prefixes, then omit the prefix from the reply.
3600: */
3601: if (reply->client_resources >= limit)
3602: goto cleanup;
3603: }
3604:
3605: status = reply_process_is_prefixed(reply, scope, reply->shared->group);
3606: if (status != ISC_R_SUCCESS)
3607: goto cleanup;
3608:
3609: send_pref:
3610: status = reply_process_send_prefix(reply, &tmp_pref);
3611:
3612: cleanup:
3613: if (iapref.data != NULL)
3614: data_string_forget(&iapref, MDL);
3615: if (data.data != NULL)
3616: data_string_forget(&data, MDL);
3617: if (reply->lease != NULL)
3618: iasubopt_dereference(&reply->lease, MDL);
3619:
3620: return status;
3621: }
3622:
3623: /*
3624: * Verify the prefix belongs to the client. If we've got a host
3625: * record with fixed prefixes, it has to be an assigned prefix
3626: * (fault out all else). Otherwise it's a dynamic prefix, so lookup
3627: * that prefix and make sure it belongs to this DUID:IAID pair.
3628: */
3629: static isc_boolean_t
3630: prefix_is_owned(struct reply_state *reply, struct iaddrcidrnet *pref) {
3631: struct iaddrcidrnetlist *l;
3632: int i;
3633:
3634: /*
3635: * This faults out prefixes that don't match fixed prefixes.
3636: */
3637: if (reply->static_prefixes > 0) {
3638: for (l = reply->host->fixed_prefix; l != NULL; l = l->next) {
3639: if ((pref->bits == l->cidrnet.bits) &&
3640: (memcmp(pref->lo_addr.iabuf,
3641: l->cidrnet.lo_addr.iabuf, 16) == 0))
1.1.1.1 ! misho 3642: return (ISC_TRUE);
1.1 misho 3643: }
1.1.1.1 ! misho 3644: return (ISC_FALSE);
1.1 misho 3645: }
3646:
3647: if ((reply->old_ia == NULL) ||
3648: (reply->old_ia->num_iasubopt == 0))
1.1.1.1 ! misho 3649: return (ISC_FALSE);
1.1 misho 3650:
3651: for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
3652: struct iasubopt *tmp;
3653:
3654: tmp = reply->old_ia->iasubopt[i];
3655:
3656: if ((pref->bits == (int) tmp->plen) &&
1.1.1.1 ! misho 3657: (memcmp(pref->lo_addr.iabuf, &tmp->addr, 16) == 0)) {
! 3658: if (lease6_usable(tmp) == ISC_FALSE) {
! 3659: return (ISC_FALSE);
! 3660: }
1.1 misho 3661: iasubopt_reference(&reply->lease, tmp, MDL);
1.1.1.1 ! misho 3662: return (ISC_TRUE);
1.1 misho 3663: }
3664: }
3665:
1.1.1.1 ! misho 3666: return (ISC_FALSE);
1.1 misho 3667: }
3668:
3669: /*
3670: * This function only returns failure on 'hard' failures. If it succeeds,
3671: * it will leave a prefix structure behind.
3672: */
3673: static isc_result_t
3674: reply_process_try_prefix(struct reply_state *reply,
3675: struct iaddrcidrnet *pref) {
1.1.1.1 ! misho 3676: isc_result_t status = ISC_R_ADDRNOTAVAIL;
1.1 misho 3677: struct ipv6_pool *pool;
3678: int i;
3679: struct data_string data_pref;
3680:
3681: if ((reply == NULL) || (reply->shared == NULL) ||
1.1.1.1 ! misho 3682: (pref == NULL) || (reply->lease != NULL))
1.1 misho 3683: return ISC_R_INVALIDARG;
3684:
1.1.1.1 ! misho 3685: if (reply->shared->ipv6_pools == NULL)
! 3686: return (ISC_R_ADDRNOTAVAIL);
! 3687:
1.1 misho 3688: memset(&data_pref, 0, sizeof(data_pref));
3689: data_pref.len = 17;
3690: if (!buffer_allocate(&data_pref.buffer, data_pref.len, MDL)) {
3691: log_error("reply_process_try_prefix: out of memory.");
1.1.1.1 ! misho 3692: return (ISC_R_NOMEMORY);
1.1 misho 3693: }
3694: data_pref.data = data_pref.buffer->data;
3695: data_pref.buffer->data[0] = (u_int8_t) pref->bits;
3696: memcpy(data_pref.buffer->data + 1, pref->lo_addr.iabuf, 16);
3697:
3698: for (i = 0 ; (pool = reply->shared->ipv6_pools[i]) != NULL ; i++) {
3699: if (pool->pool_type != D6O_IA_PD)
3700: continue;
3701: status = try_client_v6_prefix(&reply->lease, pool,
3702: &data_pref);
3703: /* If we found it in this pool (either in use or available),
3704: there is no need to look further. */
3705: if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
3706: break;
3707: }
3708:
3709: data_string_forget(&data_pref, MDL);
3710: /* Return just the most recent status... */
1.1.1.1 ! misho 3711: return (status);
1.1 misho 3712: }
3713:
3714: /* Look around for a prefix to give the client. First, look through the old
3715: * IA_PD for prefixes we can extend. Second, try to allocate a new prefix.
3716: * Finally, actually add that prefix into the current reply IA_PD.
3717: */
3718: static isc_result_t
3719: find_client_prefix(struct reply_state *reply) {
3720: struct iaddrcidrnet send_pref;
3721: isc_result_t status = ISC_R_NORESOURCES;
3722: struct iasubopt *prefix, *best_prefix = NULL;
3723: struct binding_scope **scope;
3724: int i;
3725:
3726: if (reply->static_prefixes > 0) {
3727: struct iaddrcidrnetlist *l;
3728:
3729: if (reply->host == NULL)
3730: return ISC_R_INVALIDARG;
3731:
3732: for (l = reply->host->fixed_prefix; l != NULL; l = l->next) {
3733: if (l->cidrnet.bits == reply->preflen)
3734: break;
3735: }
3736: if (l == NULL) {
3737: /*
3738: * If no fixed prefix has the preferred length,
3739: * get the first one.
3740: */
3741: l = reply->host->fixed_prefix;
3742: }
3743: memcpy(&send_pref, &l->cidrnet, sizeof(send_pref));
3744:
3745: status = ISC_R_SUCCESS;
3746: scope = &global_scope;
3747: goto send_pref;
3748: }
3749:
3750: if (reply->old_ia != NULL) {
3751: for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
3752: struct shared_network *candidate_shared;
3753:
3754: prefix = reply->old_ia->iasubopt[i];
3755: candidate_shared = prefix->ipv6_pool->shared_network;
3756:
3757: /*
3758: * Consider this prefix if it is in a global pool or
3759: * if it is scoped in a pool under the client's shared
3760: * network.
3761: */
1.1.1.1 ! misho 3762: if (((candidate_shared == NULL) ||
! 3763: (candidate_shared == reply->shared)) &&
! 3764: (lease6_usable(prefix) == ISC_TRUE)) {
1.1 misho 3765: best_prefix = prefix_compare(reply, prefix,
3766: best_prefix);
3767: }
3768: }
3769: }
3770:
3771: /* Try to pick a new prefix if we didn't find one, or if we found an
3772: * abandoned prefix.
3773: */
3774: if ((best_prefix == NULL) || (best_prefix->state == FTS_ABANDONED)) {
3775: status = pick_v6_prefix(&reply->lease, reply->preflen,
3776: reply->shared, &reply->client_id);
3777: } else if (best_prefix != NULL) {
3778: iasubopt_reference(&reply->lease, best_prefix, MDL);
3779: status = ISC_R_SUCCESS;
3780: }
3781:
3782: /* Pick the abandoned prefix as a last resort. */
3783: if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
3784: /* I don't see how this is supposed to be done right now. */
3785: log_error("Reclaiming abandoned prefixes is not yet "
3786: "supported. Treating this as an out of space "
3787: "condition.");
3788: /* iasubopt_reference(&reply->lease, best_prefix, MDL); */
3789: }
3790:
3791: /* Give up now if we didn't find a prefix. */
3792: if (status != ISC_R_SUCCESS)
3793: return status;
3794:
3795: if (reply->lease == NULL)
3796: log_fatal("Impossible condition at %s:%d.", MDL);
3797:
3798: scope = &reply->lease->scope;
3799:
3800: send_pref.lo_addr.len = 16;
3801: memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
3802: send_pref.bits = (int) reply->lease->plen;
3803:
3804: send_pref:
3805: status = reply_process_is_prefixed(reply, scope, reply->shared->group);
3806: if (status != ISC_R_SUCCESS)
3807: return status;
3808:
3809: status = reply_process_send_prefix(reply, &send_pref);
3810: return status;
3811: }
3812:
3813: /* Once a prefix is found for a client, perform several common functions;
3814: * Calculate and store valid and preferred prefix times, draw client options
3815: * into the option state.
3816: */
3817: static isc_result_t
3818: reply_process_is_prefixed(struct reply_state *reply,
3819: struct binding_scope **scope, struct group *group)
3820: {
3821: isc_result_t status = ISC_R_SUCCESS;
3822: struct data_string data;
3823: struct option_cache *oc;
3824:
3825: /* Initialize values we will cleanup. */
3826: memset(&data, 0, sizeof(data));
3827:
3828: /*
3829: * Bring configured options into the root packet level cache - start
3830: * with the lease's closest enclosing group (passed in by the caller
3831: * as 'group').
3832: */
3833: execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3834: reply->packet->options, reply->opt_state,
3835: scope, group, root_group);
3836:
3837: /*
3838: * If there is a host record, over-ride with values configured there,
3839: * without re-evaluating configuration from the previously executed
3840: * group or its common enclosers.
3841: */
3842: if (reply->host != NULL)
3843: execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3844: reply->packet->options,
3845: reply->opt_state, scope,
3846: reply->host->group, group);
3847:
3848: /* Determine valid lifetime. */
3849: if (reply->client_valid == 0)
3850: reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
3851: else
3852: reply->send_valid = reply->client_valid;
3853:
3854: oc = lookup_option(&server_universe, reply->opt_state,
3855: SV_DEFAULT_LEASE_TIME);
3856: if (oc != NULL) {
3857: if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
3858: reply->packet->options,
3859: reply->opt_state,
3860: scope, oc, MDL) ||
3861: (data.len != 4)) {
3862: log_error("reply_process_is_prefixed: unable to "
3863: "evaluate default prefix time");
3864: status = ISC_R_FAILURE;
3865: goto cleanup;
3866: }
3867:
3868: reply->send_valid = getULong(data.data);
3869: data_string_forget(&data, MDL);
3870: }
3871:
3872: if (reply->client_prefer == 0)
3873: reply->send_prefer = reply->send_valid;
3874: else
3875: reply->send_prefer = reply->client_prefer;
3876:
3877: if (reply->send_prefer >= reply->send_valid)
3878: reply->send_prefer = (reply->send_valid / 2) +
3879: (reply->send_valid / 8);
3880:
3881: oc = lookup_option(&server_universe, reply->opt_state,
3882: SV_PREFER_LIFETIME);
3883: if (oc != NULL) {
3884: if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
3885: reply->packet->options,
3886: reply->opt_state,
3887: scope, oc, MDL) ||
3888: (data.len != 4)) {
3889: log_error("reply_process_is_prefixed: unable to "
3890: "evaluate preferred prefix time");
3891: status = ISC_R_FAILURE;
3892: goto cleanup;
3893: }
3894:
3895: reply->send_prefer = getULong(data.data);
3896: data_string_forget(&data, MDL);
3897: }
3898:
3899: /* Note lowest values for later calculation of renew/rebind times. */
3900: if (reply->prefer > reply->send_prefer)
3901: reply->prefer = reply->send_prefer;
3902:
3903: if (reply->valid > reply->send_valid)
3904: reply->valid = reply->send_valid;
3905:
3906: /* Perform dynamic prefix related update work. */
3907: if (reply->lease != NULL) {
3908: /* Cached lifetimes */
3909: reply->lease->prefer = reply->send_prefer;
3910: reply->lease->valid = reply->send_valid;
3911:
3912: /* Advance (or rewind) the valid lifetime. */
3913: if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
3914: reply->lease->soft_lifetime_end_time =
3915: cur_time + reply->send_valid;
3916: /* Wait before renew! */
3917: }
3918:
3919: status = ia_add_iasubopt(reply->ia, reply->lease, MDL);
3920: if (status != ISC_R_SUCCESS) {
3921: log_fatal("reply_process_is_prefixed: Unable to "
3922: "attach prefix to new IA_PD: %s",
3923: isc_result_totext(status));
3924: }
3925:
3926: /*
3927: * If this is a new prefix, make sure it is attached somewhere.
3928: */
3929: if (reply->lease->ia == NULL) {
3930: ia_reference(&reply->lease->ia, reply->ia, MDL);
3931: }
3932: }
3933:
3934: /* Bring a copy of the relevant options into the IA_PD scope. */
3935: execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3936: reply->packet->options, reply->reply_ia,
3937: scope, group, root_group);
3938:
3939: /*
3940: * And bring in host record configuration, if any, but not to overlap
3941: * the previous group or its common enclosers.
3942: */
3943: if (reply->host != NULL)
3944: execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
3945: reply->packet->options,
3946: reply->reply_ia, scope,
3947: reply->host->group, group);
3948:
3949: cleanup:
3950: if (data.data != NULL)
3951: data_string_forget(&data, MDL);
3952:
3953: if (status == ISC_R_SUCCESS)
3954: reply->client_resources++;
3955:
3956: return status;
3957: }
3958:
3959: /* Simply send an IAPREFIX within the IA_PD scope as described. */
3960: static isc_result_t
3961: reply_process_send_prefix(struct reply_state *reply,
3962: struct iaddrcidrnet *pref) {
3963: isc_result_t status = ISC_R_SUCCESS;
3964: struct data_string data;
3965:
3966: memset(&data, 0, sizeof(data));
3967:
3968: /* Now append the prefix. */
3969: data.len = IAPREFIX_OFFSET;
3970: if (!buffer_allocate(&data.buffer, data.len, MDL)) {
3971: log_error("reply_process_send_prefix: out of memory"
3972: "allocating new IAPREFIX buffer.");
3973: status = ISC_R_NOMEMORY;
3974: goto cleanup;
3975: }
3976: data.data = data.buffer->data;
3977:
3978: putULong(data.buffer->data, reply->send_prefer);
3979: putULong(data.buffer->data + 4, reply->send_valid);
3980: data.buffer->data[8] = pref->bits;
3981: memcpy(data.buffer->data + 9, pref->lo_addr.iabuf, 16);
3982:
3983: if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
3984: data.buffer, data.buffer->data,
3985: data.len, D6O_IAPREFIX, 0)) {
3986: log_error("reply_process_send_prefix: unable "
3987: "to save IAPREFIX option");
3988: status = ISC_R_FAILURE;
3989: goto cleanup;
3990: }
3991:
3992: reply->resources_included = ISC_TRUE;
3993:
3994: cleanup:
3995: if (data.data != NULL)
3996: data_string_forget(&data, MDL);
3997:
3998: return status;
3999: }
4000:
4001: /* Choose the better of two prefixes. */
4002: static struct iasubopt *
4003: prefix_compare(struct reply_state *reply,
4004: struct iasubopt *alpha, struct iasubopt *beta) {
4005: if (alpha == NULL)
4006: return beta;
4007: if (beta == NULL)
4008: return alpha;
4009:
4010: if (reply->preflen >= 0) {
4011: if ((alpha->plen == reply->preflen) &&
4012: (beta->plen != reply->preflen))
4013: return alpha;
4014: if ((beta->plen == reply->preflen) &&
4015: (alpha->plen != reply->preflen))
4016: return beta;
4017: }
4018:
4019: switch(alpha->state) {
4020: case FTS_ACTIVE:
4021: switch(beta->state) {
4022: case FTS_ACTIVE:
4023: /* Choose the prefix with the longest lifetime (most
4024: * likely the most recently allocated).
4025: */
4026: if (alpha->hard_lifetime_end_time <
4027: beta->hard_lifetime_end_time)
4028: return beta;
4029: else
4030: return alpha;
4031:
4032: case FTS_EXPIRED:
4033: case FTS_ABANDONED:
4034: return alpha;
4035:
4036: default:
4037: log_fatal("Impossible condition at %s:%d.", MDL);
4038: }
4039: break;
4040:
4041: case FTS_EXPIRED:
4042: switch (beta->state) {
4043: case FTS_ACTIVE:
4044: return beta;
4045:
4046: case FTS_EXPIRED:
4047: /* Choose the most recently expired prefix. */
4048: if (alpha->hard_lifetime_end_time <
4049: beta->hard_lifetime_end_time)
4050: return beta;
4051: else if ((alpha->hard_lifetime_end_time ==
4052: beta->hard_lifetime_end_time) &&
4053: (alpha->soft_lifetime_end_time <
4054: beta->soft_lifetime_end_time))
4055: return beta;
4056: else
4057: return alpha;
4058:
4059: case FTS_ABANDONED:
4060: return alpha;
4061:
4062: default:
4063: log_fatal("Impossible condition at %s:%d.", MDL);
4064: }
4065: break;
4066:
4067: case FTS_ABANDONED:
4068: switch (beta->state) {
4069: case FTS_ACTIVE:
4070: case FTS_EXPIRED:
4071: return alpha;
4072:
4073: case FTS_ABANDONED:
4074: /* Choose the prefix that was abandoned longest ago. */
4075: if (alpha->hard_lifetime_end_time <
4076: beta->hard_lifetime_end_time)
4077: return alpha;
4078:
4079: default:
4080: log_fatal("Impossible condition at %s:%d.", MDL);
4081: }
4082: break;
4083:
4084: default:
4085: log_fatal("Impossible condition at %s:%d.", MDL);
4086: }
4087:
4088: log_fatal("Triple impossible condition at %s:%d.", MDL);
4089: return NULL;
4090: }
4091:
4092: /*
4093: * Solicit is how a client starts requesting addresses.
4094: *
4095: * If the client asks for rapid commit, and we support it, we will
4096: * allocate the addresses and reply.
4097: *
4098: * Otherwise we will send an advertise message.
4099: */
4100:
4101: static void
4102: dhcpv6_solicit(struct data_string *reply_ret, struct packet *packet) {
4103: struct data_string client_id;
4104:
4105: /*
4106: * Validate our input.
4107: */
4108: if (!valid_client_msg(packet, &client_id)) {
4109: return;
4110: }
4111:
4112: lease_to_client(reply_ret, packet, &client_id, NULL);
4113:
4114: /*
4115: * Clean up.
4116: */
4117: data_string_forget(&client_id, MDL);
4118: }
4119:
4120: /*
4121: * Request is how a client actually requests addresses.
4122: *
4123: * Very similar to Solicit handling, except the server DUID is required.
4124: */
4125:
4126: /* TODO: reject unicast messages, unless we set unicast option */
4127: static void
4128: dhcpv6_request(struct data_string *reply_ret, struct packet *packet) {
4129: struct data_string client_id;
4130: struct data_string server_id;
4131:
4132: /*
4133: * Validate our input.
4134: */
4135: if (!valid_client_resp(packet, &client_id, &server_id)) {
4136: return;
4137: }
4138:
4139: /*
4140: * Issue our lease.
4141: */
4142: lease_to_client(reply_ret, packet, &client_id, &server_id);
4143:
4144: /*
4145: * Cleanup.
4146: */
4147: data_string_forget(&client_id, MDL);
4148: data_string_forget(&server_id, MDL);
4149: }
4150:
4151: /* Find a DHCPv6 packet's shared network from hints in the packet.
4152: */
4153: static isc_result_t
4154: shared_network_from_packet6(struct shared_network **shared,
4155: struct packet *packet)
4156: {
4157: const struct packet *chk_packet;
4158: const struct in6_addr *link_addr, *first_link_addr;
4159: struct iaddr tmp_addr;
4160: struct subnet *subnet;
4161: isc_result_t status;
4162:
4163: if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
4164: return ISC_R_INVALIDARG;
4165:
4166: /*
4167: * First, find the link address where the packet from the client
4168: * first appeared (if this packet was relayed).
4169: */
4170: first_link_addr = NULL;
4171: chk_packet = packet->dhcpv6_container_packet;
4172: while (chk_packet != NULL) {
4173: link_addr = &chk_packet->dhcpv6_link_address;
4174: if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
4175: !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
4176: first_link_addr = link_addr;
4177: break;
4178: }
4179: chk_packet = chk_packet->dhcpv6_container_packet;
4180: }
4181:
4182: /*
4183: * If there is a relayed link address, find the subnet associated
4184: * with that, and use that to get the appropriate
4185: * shared_network.
4186: */
4187: if (first_link_addr != NULL) {
4188: tmp_addr.len = sizeof(*first_link_addr);
4189: memcpy(tmp_addr.iabuf,
4190: first_link_addr, sizeof(*first_link_addr));
4191: subnet = NULL;
4192: if (!find_subnet(&subnet, tmp_addr, MDL)) {
4193: log_debug("No subnet found for link-address %s.",
4194: piaddr(tmp_addr));
4195: return ISC_R_NOTFOUND;
4196: }
4197: status = shared_network_reference(shared,
4198: subnet->shared_network, MDL);
4199: subnet_dereference(&subnet, MDL);
4200:
4201: /*
4202: * If there is no link address, we will use the interface
4203: * that this packet came in on to pick the shared_network.
4204: */
4205: } else if (packet->interface != NULL) {
4206: status = shared_network_reference(shared,
4207: packet->interface->shared_network,
4208: MDL);
4209: if (packet->dhcpv6_container_packet != NULL) {
4210: log_info("[L2 Relay] No link address in relay packet "
4211: "assuming L2 relay and using receiving "
4212: "interface");
4213: }
4214:
4215: } else {
4216: /*
4217: * We shouldn't be able to get here but if there is no link
4218: * address and no interface we don't know where to get the
4219: * pool from log an error and return an error.
4220: */
4221: log_error("No interface and no link address "
4222: "can't determine pool");
4223: status = ISC_R_INVALIDARG;
4224: }
4225:
4226: return status;
4227: }
4228:
4229: /*
4230: * When a client thinks it might be on a new link, it sends a
4231: * Confirm message.
4232: *
4233: * From RFC3315 section 18.2.2:
4234: *
4235: * When the server receives a Confirm message, the server determines
4236: * whether the addresses in the Confirm message are appropriate for the
4237: * link to which the client is attached. If all of the addresses in the
4238: * Confirm message pass this test, the server returns a status of
4239: * Success. If any of the addresses do not pass this test, the server
4240: * returns a status of NotOnLink. If the server is unable to perform
4241: * this test (for example, the server does not have information about
4242: * prefixes on the link to which the client is connected), or there were
4243: * no addresses in any of the IAs sent by the client, the server MUST
4244: * NOT send a reply to the client.
4245: */
4246:
4247: static void
4248: dhcpv6_confirm(struct data_string *reply_ret, struct packet *packet) {
4249: struct shared_network *shared;
4250: struct subnet *subnet;
4251: struct option_cache *ia, *ta, *oc;
4252: struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
4253: struct option_state *cli_enc_opt_state, *opt_state;
4254: struct iaddr cli_addr;
4255: int pass;
4256: isc_boolean_t inappropriate, has_addrs;
4257: char reply_data[65536];
4258: struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
4259: int reply_ofs = (int)(offsetof(struct dhcpv6_packet, options));
4260:
4261: /*
4262: * Basic client message validation.
4263: */
4264: memset(&client_id, 0, sizeof(client_id));
4265: if (!valid_client_msg(packet, &client_id)) {
4266: return;
4267: }
4268:
4269: /*
4270: * Do not process Confirms that do not have IA's we do not recognize.
4271: */
4272: ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
4273: ta = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
4274: if ((ia == NULL) && (ta == NULL))
4275: return;
4276:
4277: /*
4278: * IA_PD's are simply ignored.
4279: */
4280: delete_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
4281:
4282: /*
4283: * Bit of variable initialization.
4284: */
4285: opt_state = cli_enc_opt_state = NULL;
4286: memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
4287: memset(&iaaddr, 0, sizeof(iaaddr));
4288: memset(&packet_oro, 0, sizeof(packet_oro));
4289:
4290: /* Determine what shared network the client is connected to. We
4291: * must not respond if we don't have any information about the
4292: * network the client is on.
4293: */
4294: shared = NULL;
4295: if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
4296: (shared == NULL))
4297: goto exit;
4298:
4299: /* If there are no recorded subnets, then we have no
4300: * information about this subnet - ignore Confirms.
4301: */
4302: subnet = shared->subnets;
4303: if (subnet == NULL)
4304: goto exit;
4305:
4306: /* Are the addresses in all the IA's appropriate for that link? */
4307: has_addrs = inappropriate = ISC_FALSE;
4308: pass = D6O_IA_NA;
4309: while(!inappropriate) {
4310: /* If we've reached the end of the IA_NA pass, move to the
4311: * IA_TA pass.
4312: */
4313: if ((pass == D6O_IA_NA) && (ia == NULL)) {
4314: pass = D6O_IA_TA;
4315: ia = ta;
4316: }
4317:
4318: /* If we've reached the end of all passes, we're done. */
4319: if (ia == NULL)
4320: break;
4321:
4322: if (((pass == D6O_IA_NA) &&
4323: !get_encapsulated_IA_state(&cli_enc_opt_state,
4324: &cli_enc_opt_data,
4325: packet, ia, IA_NA_OFFSET)) ||
4326: ((pass == D6O_IA_TA) &&
4327: !get_encapsulated_IA_state(&cli_enc_opt_state,
4328: &cli_enc_opt_data,
4329: packet, ia, IA_TA_OFFSET))) {
4330: goto exit;
4331: }
4332:
4333: oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
4334: D6O_IAADDR);
4335:
4336: for ( ; oc != NULL ; oc = oc->next) {
4337: if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL,
4338: packet->options, NULL,
4339: &global_scope, oc, MDL) ||
4340: (iaaddr.len < IAADDR_OFFSET)) {
4341: log_error("dhcpv6_confirm: "
4342: "error evaluating IAADDR.");
4343: goto exit;
4344: }
4345:
4346: /* Copy out the IPv6 address for processing. */
4347: cli_addr.len = 16;
4348: memcpy(cli_addr.iabuf, iaaddr.data, 16);
4349:
4350: data_string_forget(&iaaddr, MDL);
4351:
4352: /* Record that we've processed at least one address. */
4353: has_addrs = ISC_TRUE;
4354:
4355: /* Find out if any subnets cover this address. */
4356: for (subnet = shared->subnets ; subnet != NULL ;
4357: subnet = subnet->next_sibling) {
4358: if (addr_eq(subnet_number(cli_addr,
4359: subnet->netmask),
4360: subnet->net))
4361: break;
4362: }
4363:
4364: /* If we reach the end of the subnet list, and no
4365: * subnet matches the client address, then it must
4366: * be inappropriate to the link (so far as our
4367: * configuration says). Once we've found one
4368: * inappropriate address, there is no reason to
4369: * continue searching.
4370: */
4371: if (subnet == NULL) {
4372: inappropriate = ISC_TRUE;
4373: break;
4374: }
4375: }
4376:
4377: option_state_dereference(&cli_enc_opt_state, MDL);
4378: data_string_forget(&cli_enc_opt_data, MDL);
4379:
4380: /* Advance to the next IA_*. */
4381: ia = ia->next;
4382: }
4383:
4384: /* If the client supplied no addresses, do not reply. */
4385: if (!has_addrs)
4386: goto exit;
4387:
4388: /*
4389: * Set up reply.
4390: */
4391: if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
4392: goto exit;
4393: }
4394:
4395: /*
4396: * Set our status.
4397: */
4398: if (inappropriate) {
4399: if (!set_status_code(STATUS_NotOnLink,
4400: "Some of the addresses are not on link.",
4401: opt_state)) {
4402: goto exit;
4403: }
4404: } else {
4405: if (!set_status_code(STATUS_Success,
4406: "All addresses still on link.",
4407: opt_state)) {
4408: goto exit;
4409: }
4410: }
4411:
4412: /*
4413: * Only one option: add it.
4414: */
4415: reply_ofs += store_options6(reply_data+reply_ofs,
4416: sizeof(reply_data)-reply_ofs,
4417: opt_state, packet,
4418: required_opts, &packet_oro);
4419:
4420: /*
4421: * Return our reply to the caller.
4422: */
4423: reply_ret->len = reply_ofs;
4424: reply_ret->buffer = NULL;
4425: if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
4426: log_fatal("No memory to store reply.");
4427: }
4428: reply_ret->data = reply_ret->buffer->data;
4429: memcpy(reply_ret->buffer->data, reply, reply_ofs);
4430:
4431: exit:
4432: /* Cleanup any stale data strings. */
4433: if (cli_enc_opt_data.buffer != NULL)
4434: data_string_forget(&cli_enc_opt_data, MDL);
4435: if (iaaddr.buffer != NULL)
4436: data_string_forget(&iaaddr, MDL);
4437: if (client_id.buffer != NULL)
4438: data_string_forget(&client_id, MDL);
4439: if (packet_oro.buffer != NULL)
4440: data_string_forget(&packet_oro, MDL);
4441:
4442: /* Release any stale option states. */
4443: if (cli_enc_opt_state != NULL)
4444: option_state_dereference(&cli_enc_opt_state, MDL);
4445: if (opt_state != NULL)
4446: option_state_dereference(&opt_state, MDL);
4447: }
4448:
4449: /*
4450: * Renew is when a client wants to extend its lease/prefix, at time T1.
4451: *
4452: * We handle this the same as if the client wants a new lease/prefix,
4453: * except for the error code of when addresses don't match.
4454: */
4455:
4456: /* TODO: reject unicast messages, unless we set unicast option */
4457: static void
4458: dhcpv6_renew(struct data_string *reply, struct packet *packet) {
4459: struct data_string client_id;
4460: struct data_string server_id;
4461:
4462: /*
4463: * Validate the request.
4464: */
4465: if (!valid_client_resp(packet, &client_id, &server_id)) {
4466: return;
4467: }
4468:
4469: /*
4470: * Renew our lease.
4471: */
4472: lease_to_client(reply, packet, &client_id, &server_id);
4473:
4474: /*
4475: * Cleanup.
4476: */
4477: data_string_forget(&server_id, MDL);
4478: data_string_forget(&client_id, MDL);
4479: }
4480:
4481: /*
4482: * Rebind is when a client wants to extend its lease, at time T2.
4483: *
4484: * We handle this the same as if the client wants a new lease, except
4485: * for the error code of when addresses don't match.
4486: */
4487:
4488: static void
4489: dhcpv6_rebind(struct data_string *reply, struct packet *packet) {
4490: struct data_string client_id;
4491:
4492: if (!valid_client_msg(packet, &client_id)) {
4493: return;
4494: }
4495:
4496: lease_to_client(reply, packet, &client_id, NULL);
4497:
4498: data_string_forget(&client_id, MDL);
4499: }
4500:
4501: static void
4502: ia_na_match_decline(const struct data_string *client_id,
4503: const struct data_string *iaaddr,
4504: struct iasubopt *lease)
4505: {
4506: char tmp_addr[INET6_ADDRSTRLEN];
4507:
4508: log_error("Client %s reports address %s is "
4509: "already in use by another host!",
4510: print_hex_1(client_id->len, client_id->data, 60),
4511: inet_ntop(AF_INET6, iaaddr->data,
4512: tmp_addr, sizeof(tmp_addr)));
4513: if (lease != NULL) {
4514: decline_lease6(lease->ipv6_pool, lease);
4515: lease->ia->cltt = cur_time;
4516: write_ia(lease->ia);
4517: }
4518: }
4519:
4520: static void
4521: ia_na_nomatch_decline(const struct data_string *client_id,
4522: const struct data_string *iaaddr,
4523: u_int32_t *ia_na_id,
4524: struct packet *packet,
4525: char *reply_data,
4526: int *reply_ofs,
4527: int reply_len)
4528: {
4529: char tmp_addr[INET6_ADDRSTRLEN];
4530: struct option_state *host_opt_state;
4531: int len;
4532:
4533: log_info("Client %s declines address %s, which is not offered to it.",
4534: print_hex_1(client_id->len, client_id->data, 60),
4535: inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
4536:
4537: /*
4538: * Create state for this IA_NA.
4539: */
4540: host_opt_state = NULL;
4541: if (!option_state_allocate(&host_opt_state, MDL)) {
4542: log_error("ia_na_nomatch_decline: out of memory "
4543: "allocating option_state.");
4544: goto exit;
4545: }
4546:
4547: if (!set_status_code(STATUS_NoBinding, "Decline for unknown address.",
4548: host_opt_state)) {
4549: goto exit;
4550: }
4551:
4552: /*
4553: * Insure we have enough space
4554: */
4555: if (reply_len < (*reply_ofs + 16)) {
4556: log_error("ia_na_nomatch_decline: "
4557: "out of space for reply packet.");
4558: goto exit;
4559: }
4560:
4561: /*
4562: * Put our status code into the reply packet.
4563: */
4564: len = store_options6(reply_data+(*reply_ofs)+16,
4565: reply_len-(*reply_ofs)-16,
4566: host_opt_state, packet,
4567: required_opts_STATUS_CODE, NULL);
4568:
4569: /*
4570: * Store the non-encapsulated option data for this
4571: * IA_NA into our reply packet. Defined in RFC 3315,
4572: * section 22.4.
4573: */
4574: /* option number */
4575: putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
4576: /* option length */
4577: putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
4578: /* IA_NA, copied from the client */
4579: memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
4580: /* t1 and t2, odd that we need them, but here it is */
4581: putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
4582: putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
4583:
4584: /*
4585: * Get ready for next IA_NA.
4586: */
4587: *reply_ofs += (len + 16);
4588:
4589: exit:
4590: option_state_dereference(&host_opt_state, MDL);
4591: }
4592:
4593: static void
4594: iterate_over_ia_na(struct data_string *reply_ret,
4595: struct packet *packet,
4596: const struct data_string *client_id,
4597: const struct data_string *server_id,
4598: const char *packet_type,
4599: void (*ia_na_match)(),
4600: void (*ia_na_nomatch)())
4601: {
4602: struct option_state *opt_state;
4603: struct host_decl *packet_host;
4604: struct option_cache *ia;
4605: struct option_cache *oc;
4606: /* cli_enc_... variables come from the IA_NA/IA_TA options */
4607: struct data_string cli_enc_opt_data;
4608: struct option_state *cli_enc_opt_state;
4609: struct host_decl *host;
4610: struct option_state *host_opt_state;
4611: struct data_string iaaddr;
4612: struct data_string fixed_addr;
4613: char reply_data[65536];
4614: struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
4615: int reply_ofs = (int)(offsetof(struct dhcpv6_packet, options));
4616: char status_msg[32];
4617: struct iasubopt *lease;
4618: struct ia_xx *existing_ia_na;
4619: int i;
4620: struct data_string key;
4621: u_int32_t iaid;
4622:
4623: /*
4624: * Initialize to empty values, in case we have to exit early.
4625: */
4626: opt_state = NULL;
4627: memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
4628: cli_enc_opt_state = NULL;
4629: memset(&iaaddr, 0, sizeof(iaaddr));
4630: memset(&fixed_addr, 0, sizeof(fixed_addr));
4631: host_opt_state = NULL;
4632: lease = NULL;
4633:
4634: /*
4635: * Find the host record that matches from the packet, if any.
4636: */
4637: packet_host = NULL;
4638: if (!find_hosts_by_uid(&packet_host,
4639: client_id->data, client_id->len, MDL)) {
4640: packet_host = NULL;
4641: /*
4642: * Note: In general, we don't expect a client to provide
4643: * enough information to match by option for these
4644: * types of messages, but if we don't have a UID
4645: * match we can check anyway.
4646: */
4647: if (!find_hosts_by_option(&packet_host,
4648: packet, packet->options, MDL)) {
4649: packet_host = NULL;
4650: }
4651: }
4652:
4653: /*
4654: * Set our reply information.
4655: */
4656: reply->msg_type = DHCPV6_REPLY;
4657: memcpy(reply->transaction_id, packet->dhcpv6_transaction_id,
4658: sizeof(reply->transaction_id));
4659:
4660: /*
4661: * Build our option state for reply.
4662: */
4663: opt_state = NULL;
4664: if (!option_state_allocate(&opt_state, MDL)) {
4665: log_error("iterate_over_ia_na: no memory for option_state.");
4666: goto exit;
4667: }
4668: execute_statements_in_scope(NULL, packet, NULL, NULL,
4669: packet->options, opt_state,
4670: &global_scope, root_group, NULL);
4671:
4672: /*
4673: * RFC 3315, section 18.2.7 tells us which options to include.
4674: */
4675: oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
4676: if (oc == NULL) {
4677: if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
4678: (unsigned char *)server_duid.data,
4679: server_duid.len, D6O_SERVERID, 0)) {
4680: log_error("iterate_over_ia_na: "
4681: "error saving server identifier.");
4682: goto exit;
4683: }
4684: }
4685:
4686: if (!save_option_buffer(&dhcpv6_universe, opt_state,
4687: client_id->buffer,
4688: (unsigned char *)client_id->data,
4689: client_id->len,
4690: D6O_CLIENTID, 0)) {
4691: log_error("iterate_over_ia_na: "
4692: "error saving client identifier.");
4693: goto exit;
4694: }
4695:
4696: snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type);
4697: if (!set_status_code(STATUS_Success, status_msg, opt_state)) {
4698: goto exit;
4699: }
4700:
4701: /*
4702: * Add our options that are not associated with any IA_NA or IA_TA.
4703: */
4704: reply_ofs += store_options6(reply_data+reply_ofs,
4705: sizeof(reply_data)-reply_ofs,
4706: opt_state, packet,
4707: required_opts, NULL);
4708:
4709: /*
4710: * Loop through the IA_NA reported by the client, and deal with
4711: * addresses reported as already in use.
4712: */
4713: for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
4714: ia != NULL; ia = ia->next) {
4715:
4716: if (!get_encapsulated_IA_state(&cli_enc_opt_state,
4717: &cli_enc_opt_data,
4718: packet, ia, IA_NA_OFFSET)) {
4719: goto exit;
4720: }
4721:
4722: iaid = getULong(cli_enc_opt_data.data);
4723:
4724: /*
4725: * XXX: It is possible that we can get multiple addresses
4726: * sent by the client. We don't send multiple
4727: * addresses, so this indicates a client error.
4728: * We should check for multiple IAADDR options, log
4729: * if found, and set as an error.
4730: */
4731: oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
4732: D6O_IAADDR);
4733: if (oc == NULL) {
4734: /* no address given for this IA, ignore */
4735: option_state_dereference(&cli_enc_opt_state, MDL);
4736: data_string_forget(&cli_enc_opt_data, MDL);
4737: continue;
4738: }
4739:
4740: memset(&iaaddr, 0, sizeof(iaaddr));
4741: if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL,
4742: packet->options, NULL,
4743: &global_scope, oc, MDL)) {
4744: log_error("iterate_over_ia_na: "
4745: "error evaluating IAADDR.");
4746: goto exit;
4747: }
4748:
4749: /*
4750: * Now we need to figure out which host record matches
4751: * this IA_NA and IAADDR.
4752: *
4753: * XXX: We don't currently track IA_NA separately, but
4754: * we will need to do this!
4755: */
4756: host = NULL;
4757: if (!find_hosts_by_option(&host, packet,
4758: cli_enc_opt_state, MDL)) {
4759: if (packet_host != NULL) {
4760: host = packet_host;
4761: } else {
4762: host = NULL;
4763: }
4764: }
4765: while (host != NULL) {
4766: if (host->fixed_addr != NULL) {
4767: if (!evaluate_option_cache(&fixed_addr, NULL,
4768: NULL, NULL, NULL,
4769: NULL, &global_scope,
4770: host->fixed_addr,
4771: MDL)) {
4772: log_error("iterate_over_ia_na: error "
4773: "evaluating host address.");
4774: goto exit;
4775: }
4776: if ((iaaddr.len >= 16) &&
4777: !memcmp(fixed_addr.data, iaaddr.data, 16)) {
4778: data_string_forget(&fixed_addr, MDL);
4779: break;
4780: }
4781: data_string_forget(&fixed_addr, MDL);
4782: }
4783: host = host->n_ipaddr;
4784: }
4785:
4786: if ((host == NULL) && (iaaddr.len >= IAADDR_OFFSET)) {
4787: /*
4788: * Find existing IA_NA.
4789: */
4790: if (ia_make_key(&key, iaid,
4791: (char *)client_id->data,
4792: client_id->len,
4793: MDL) != ISC_R_SUCCESS) {
4794: log_fatal("iterate_over_ia_na: no memory for "
4795: "key.");
4796: }
4797:
4798: existing_ia_na = NULL;
4799: if (ia_hash_lookup(&existing_ia_na, ia_na_active,
4800: (unsigned char *)key.data,
4801: key.len, MDL)) {
4802: /*
4803: * Make sure this address is in the IA_NA.
4804: */
4805: for (i=0; i<existing_ia_na->num_iasubopt; i++) {
4806: struct iasubopt *tmp;
4807: struct in6_addr *in6_addr;
4808:
4809: tmp = existing_ia_na->iasubopt[i];
4810: in6_addr = &tmp->addr;
4811: if (memcmp(in6_addr,
4812: iaaddr.data, 16) == 0) {
4813: iasubopt_reference(&lease,
4814: tmp, MDL);
4815: break;
4816: }
4817: }
4818: }
4819:
4820: data_string_forget(&key, MDL);
4821: }
4822:
4823: if ((host != NULL) || (lease != NULL)) {
4824: ia_na_match(client_id, &iaaddr, lease);
4825: } else {
4826: ia_na_nomatch(client_id, &iaaddr,
4827: (u_int32_t *)cli_enc_opt_data.data,
4828: packet, reply_data, &reply_ofs,
4829: sizeof(reply_data));
4830: }
4831:
4832: if (lease != NULL) {
4833: iasubopt_dereference(&lease, MDL);
4834: }
4835:
4836: data_string_forget(&iaaddr, MDL);
4837: option_state_dereference(&cli_enc_opt_state, MDL);
4838: data_string_forget(&cli_enc_opt_data, MDL);
4839: }
4840:
4841: /*
4842: * Return our reply to the caller.
4843: */
4844: reply_ret->len = reply_ofs;
4845: reply_ret->buffer = NULL;
4846: if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
4847: log_fatal("No memory to store reply.");
4848: }
4849: reply_ret->data = reply_ret->buffer->data;
4850: memcpy(reply_ret->buffer->data, reply, reply_ofs);
4851:
4852: exit:
4853: if (lease != NULL) {
4854: iasubopt_dereference(&lease, MDL);
4855: }
4856: if (host_opt_state != NULL) {
4857: option_state_dereference(&host_opt_state, MDL);
4858: }
4859: if (fixed_addr.buffer != NULL) {
4860: data_string_forget(&fixed_addr, MDL);
4861: }
4862: if (iaaddr.buffer != NULL) {
4863: data_string_forget(&iaaddr, MDL);
4864: }
4865: if (cli_enc_opt_state != NULL) {
4866: option_state_dereference(&cli_enc_opt_state, MDL);
4867: }
4868: if (cli_enc_opt_data.buffer != NULL) {
4869: data_string_forget(&cli_enc_opt_data, MDL);
4870: }
4871: if (opt_state != NULL) {
4872: option_state_dereference(&opt_state, MDL);
4873: }
4874: }
4875:
4876: /*
4877: * Decline means a client has detected that something else is using an
4878: * address we gave it.
4879: *
4880: * Since we're only dealing with fixed leases for now, there's not
4881: * much we can do, other that log the occurrence.
4882: *
4883: * When we start issuing addresses from pools, then we will have to
4884: * record our declined addresses and issue another. In general with
4885: * IPv6 there is no worry about DoS by clients exhausting space, but
4886: * we still need to be aware of this possibility.
4887: */
4888:
4889: /* TODO: reject unicast messages, unless we set unicast option */
4890: /* TODO: IA_TA */
4891: static void
4892: dhcpv6_decline(struct data_string *reply, struct packet *packet) {
4893: struct data_string client_id;
4894: struct data_string server_id;
4895:
4896: /*
4897: * Validate our input.
4898: */
4899: if (!valid_client_resp(packet, &client_id, &server_id)) {
4900: return;
4901: }
4902:
4903: /*
4904: * Undefined for IA_PD.
4905: */
4906: delete_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
4907:
4908: /*
4909: * And operate on each IA_NA in this packet.
4910: */
4911: iterate_over_ia_na(reply, packet, &client_id, &server_id, "Decline",
4912: ia_na_match_decline, ia_na_nomatch_decline);
4913:
4914: data_string_forget(&server_id, MDL);
4915: data_string_forget(&client_id, MDL);
4916: }
4917:
4918: static void
4919: ia_na_match_release(const struct data_string *client_id,
4920: const struct data_string *iaaddr,
4921: struct iasubopt *lease)
4922: {
4923: char tmp_addr[INET6_ADDRSTRLEN];
4924:
4925: log_info("Client %s releases address %s",
4926: print_hex_1(client_id->len, client_id->data, 60),
4927: inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
4928: if (lease != NULL) {
4929: release_lease6(lease->ipv6_pool, lease);
4930: lease->ia->cltt = cur_time;
4931: write_ia(lease->ia);
4932: }
4933: }
4934:
4935: static void
4936: ia_na_nomatch_release(const struct data_string *client_id,
4937: const struct data_string *iaaddr,
4938: u_int32_t *ia_na_id,
4939: struct packet *packet,
4940: char *reply_data,
4941: int *reply_ofs,
4942: int reply_len)
4943: {
4944: char tmp_addr[INET6_ADDRSTRLEN];
4945: struct option_state *host_opt_state;
4946: int len;
4947:
4948: log_info("Client %s releases address %s, which is not leased to it.",
4949: print_hex_1(client_id->len, client_id->data, 60),
4950: inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
4951:
4952: /*
4953: * Create state for this IA_NA.
4954: */
4955: host_opt_state = NULL;
4956: if (!option_state_allocate(&host_opt_state, MDL)) {
4957: log_error("ia_na_nomatch_release: out of memory "
4958: "allocating option_state.");
4959: goto exit;
4960: }
4961:
4962: if (!set_status_code(STATUS_NoBinding,
4963: "Release for non-leased address.",
4964: host_opt_state)) {
4965: goto exit;
4966: }
4967:
4968: /*
4969: * Insure we have enough space
4970: */
4971: if (reply_len < (*reply_ofs + 16)) {
4972: log_error("ia_na_nomatch_release: "
4973: "out of space for reply packet.");
4974: goto exit;
4975: }
4976:
4977: /*
4978: * Put our status code into the reply packet.
4979: */
4980: len = store_options6(reply_data+(*reply_ofs)+16,
4981: reply_len-(*reply_ofs)-16,
4982: host_opt_state, packet,
4983: required_opts_STATUS_CODE, NULL);
4984:
4985: /*
4986: * Store the non-encapsulated option data for this
4987: * IA_NA into our reply packet. Defined in RFC 3315,
4988: * section 22.4.
4989: */
4990: /* option number */
4991: putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
4992: /* option length */
4993: putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
4994: /* IA_NA, copied from the client */
4995: memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
4996: /* t1 and t2, odd that we need them, but here it is */
4997: putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
4998: putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
4999:
5000: /*
5001: * Get ready for next IA_NA.
5002: */
5003: *reply_ofs += (len + 16);
5004:
5005: exit:
5006: option_state_dereference(&host_opt_state, MDL);
5007: }
5008:
5009: static void
5010: ia_pd_match_release(const struct data_string *client_id,
5011: const struct data_string *iapref,
5012: struct iasubopt *prefix)
5013: {
5014: char tmp_addr[INET6_ADDRSTRLEN];
5015:
5016: log_info("Client %s releases prefix %s/%u",
5017: print_hex_1(client_id->len, client_id->data, 60),
5018: inet_ntop(AF_INET6, iapref->data + 9,
5019: tmp_addr, sizeof(tmp_addr)),
5020: (unsigned) getUChar(iapref->data + 8));
5021: if (prefix != NULL) {
5022: release_lease6(prefix->ipv6_pool, prefix);
5023: prefix->ia->cltt = cur_time;
5024: write_ia(prefix->ia);
5025: }
5026: }
5027:
5028: static void
5029: ia_pd_nomatch_release(const struct data_string *client_id,
5030: const struct data_string *iapref,
5031: u_int32_t *ia_pd_id,
5032: struct packet *packet,
5033: char *reply_data,
5034: int *reply_ofs,
5035: int reply_len)
5036: {
5037: char tmp_addr[INET6_ADDRSTRLEN];
5038: struct option_state *host_opt_state;
5039: int len;
5040:
5041: log_info("Client %s releases prefix %s/%u, which is not leased to it.",
5042: print_hex_1(client_id->len, client_id->data, 60),
5043: inet_ntop(AF_INET6, iapref->data + 9,
5044: tmp_addr, sizeof(tmp_addr)),
5045: (unsigned) getUChar(iapref->data + 8));
5046:
5047: /*
5048: * Create state for this IA_PD.
5049: */
5050: host_opt_state = NULL;
5051: if (!option_state_allocate(&host_opt_state, MDL)) {
5052: log_error("ia_pd_nomatch_release: out of memory "
5053: "allocating option_state.");
5054: goto exit;
5055: }
5056:
5057: if (!set_status_code(STATUS_NoBinding,
5058: "Release for non-leased prefix.",
5059: host_opt_state)) {
5060: goto exit;
5061: }
5062:
5063: /*
5064: * Insure we have enough space
5065: */
5066: if (reply_len < (*reply_ofs + 16)) {
5067: log_error("ia_pd_nomatch_release: "
5068: "out of space for reply packet.");
5069: goto exit;
5070: }
5071:
5072: /*
5073: * Put our status code into the reply packet.
5074: */
5075: len = store_options6(reply_data+(*reply_ofs)+16,
5076: reply_len-(*reply_ofs)-16,
5077: host_opt_state, packet,
5078: required_opts_STATUS_CODE, NULL);
5079:
5080: /*
5081: * Store the non-encapsulated option data for this
5082: * IA_PD into our reply packet. Defined in RFC 3315,
5083: * section 22.4.
5084: */
5085: /* option number */
5086: putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_PD);
5087: /* option length */
5088: putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5089: /* IA_PD, copied from the client */
5090: memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
5091: /* t1 and t2, odd that we need them, but here it is */
5092: putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
5093: putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
5094:
5095: /*
5096: * Get ready for next IA_PD.
5097: */
5098: *reply_ofs += (len + 16);
5099:
5100: exit:
5101: option_state_dereference(&host_opt_state, MDL);
5102: }
5103:
5104: static void
5105: iterate_over_ia_pd(struct data_string *reply_ret,
5106: struct packet *packet,
5107: const struct data_string *client_id,
5108: const struct data_string *server_id,
5109: const char *packet_type,
5110: void (*ia_pd_match)(),
5111: void (*ia_pd_nomatch)())
5112: {
5113: struct data_string reply_new;
5114: int reply_len;
5115: struct option_state *opt_state;
5116: struct host_decl *packet_host;
5117: struct option_cache *ia;
5118: struct option_cache *oc;
5119: /* cli_enc_... variables come from the IA_PD options */
5120: struct data_string cli_enc_opt_data;
5121: struct option_state *cli_enc_opt_state;
5122: struct host_decl *host;
5123: struct option_state *host_opt_state;
5124: struct data_string iaprefix;
5125: char reply_data[65536];
5126: int reply_ofs;
5127: struct iasubopt *prefix;
5128: struct ia_xx *existing_ia_pd;
5129: int i;
5130: struct data_string key;
5131: u_int32_t iaid;
5132:
5133: /*
5134: * Initialize to empty values, in case we have to exit early.
5135: */
5136: memset(&reply_new, 0, sizeof(reply_new));
5137: opt_state = NULL;
5138: memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
5139: cli_enc_opt_state = NULL;
5140: memset(&iaprefix, 0, sizeof(iaprefix));
5141: host_opt_state = NULL;
5142: prefix = NULL;
5143:
5144: /*
5145: * Compute the available length for the reply.
5146: */
5147: reply_len = sizeof(reply_data) - reply_ret->len;
5148: reply_ofs = 0;
5149:
5150: /*
5151: * Find the host record that matches from the packet, if any.
5152: */
5153: packet_host = NULL;
5154: if (!find_hosts_by_uid(&packet_host,
5155: client_id->data, client_id->len, MDL)) {
5156: packet_host = NULL;
5157: /*
5158: * Note: In general, we don't expect a client to provide
5159: * enough information to match by option for these
5160: * types of messages, but if we don't have a UID
5161: * match we can check anyway.
5162: */
5163: if (!find_hosts_by_option(&packet_host,
5164: packet, packet->options, MDL)) {
5165: packet_host = NULL;
5166: }
5167: }
5168:
5169: /*
5170: * Build our option state for reply.
5171: */
5172: opt_state = NULL;
5173: if (!option_state_allocate(&opt_state, MDL)) {
5174: log_error("iterate_over_ia_pd: no memory for option_state.");
5175: goto exit;
5176: }
5177: execute_statements_in_scope(NULL, packet, NULL, NULL,
5178: packet->options, opt_state,
5179: &global_scope, root_group, NULL);
5180:
5181: /*
5182: * Loop through the IA_PD reported by the client, and deal with
5183: * prefixes reported as already in use.
5184: */
5185: for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
5186: ia != NULL; ia = ia->next) {
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)) {
1.1.1.1 ! misho 5513: int relaylen = (int)(offsetof(struct dhcpv6_relay_packet, options));
1.1 misho 5514: relay = (struct dhcpv6_relay_packet *)enc_opt_data.data;
5515: enc_packet->dhcpv6_msg_type = relay->msg_type;
5516:
5517: /* relay-specific data */
5518: enc_packet->dhcpv6_hop_count = relay->hop_count;
5519: memcpy(&enc_packet->dhcpv6_link_address,
5520: relay->link_address, sizeof(relay->link_address));
5521: memcpy(&enc_packet->dhcpv6_peer_address,
5522: relay->peer_address, sizeof(relay->peer_address));
5523:
5524: if (!parse_option_buffer(enc_packet->options,
5525: relay->options,
1.1.1.1 ! misho 5526: enc_opt_data.len - relaylen,
1.1 misho 5527: &dhcpv6_universe)) {
5528: /* no logging here, as parse_option_buffer() logs all
5529: cases where it fails */
5530: goto exit;
5531: }
5532: } else {
1.1.1.1 ! misho 5533: int msglen = (int)(offsetof(struct dhcpv6_packet, options));
1.1 misho 5534: msg = (struct dhcpv6_packet *)enc_opt_data.data;
5535: enc_packet->dhcpv6_msg_type = msg->msg_type;
5536:
5537: /* message-specific data */
5538: memcpy(enc_packet->dhcpv6_transaction_id,
5539: msg->transaction_id,
5540: sizeof(enc_packet->dhcpv6_transaction_id));
5541:
5542: if (!parse_option_buffer(enc_packet->options,
5543: msg->options,
1.1.1.1 ! misho 5544: enc_opt_data.len - msglen,
1.1 misho 5545: &dhcpv6_universe)) {
5546: /* no logging here, as parse_option_buffer() logs all
5547: cases where it fails */
5548: goto exit;
5549: }
5550: }
5551:
5552: /*
5553: * This is recursive. It is possible to exceed maximum packet size.
5554: * XXX: This will cause the packet send to fail.
5555: */
5556: build_dhcpv6_reply(&enc_reply, enc_packet);
5557:
5558: /*
5559: * If we got no encapsulated data, then it is discarded, and
5560: * our reply-forw is also discarded.
5561: */
5562: if (enc_reply.data == NULL) {
5563: goto exit;
5564: }
5565:
5566: /*
5567: * Now we can use the reply_data buffer.
5568: * Packet header stuff all comes from the forward message.
5569: */
5570: reply = (struct dhcpv6_relay_packet *)reply_data;
5571: reply->msg_type = DHCPV6_RELAY_REPL;
5572: reply->hop_count = packet->dhcpv6_hop_count;
5573: memcpy(reply->link_address, &packet->dhcpv6_link_address,
5574: sizeof(reply->link_address));
5575: memcpy(reply->peer_address, &packet->dhcpv6_peer_address,
5576: sizeof(reply->peer_address));
5577: reply_ofs = (int)(offsetof(struct dhcpv6_relay_packet, options));
5578:
5579: /*
5580: * Get the reply option state.
5581: */
5582: opt_state = NULL;
5583: if (!option_state_allocate(&opt_state, MDL)) {
5584: log_error("dhcpv6_relay_forw: no memory for option state.");
5585: goto exit;
5586: }
5587:
5588: /*
5589: * Append the interface-id if present.
5590: */
5591: oc = lookup_option(&dhcpv6_universe, packet->options,
5592: D6O_INTERFACE_ID);
5593: if (oc != NULL) {
5594: if (!evaluate_option_cache(&a_opt, packet,
5595: NULL, NULL,
5596: packet->options, NULL,
5597: &global_scope, oc, MDL)) {
5598: log_error("dhcpv6_relay_forw: error evaluating "
5599: "Interface ID.");
5600: goto exit;
5601: }
5602: if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
5603: (unsigned char *)a_opt.data,
5604: a_opt.len,
5605: D6O_INTERFACE_ID, 0)) {
5606: log_error("dhcpv6_relay_forw: error saving "
5607: "Interface ID.");
5608: goto exit;
5609: }
5610: data_string_forget(&a_opt, MDL);
5611: }
5612:
5613: /*
5614: * Append our encapsulated stuff for caller.
5615: */
5616: if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
5617: (unsigned char *)enc_reply.data,
5618: enc_reply.len,
5619: D6O_RELAY_MSG, 0)) {
5620: log_error("dhcpv6_relay_forw: error saving Relay MSG.");
5621: goto exit;
5622: }
5623:
5624: /*
5625: * Get the ERO if any.
5626: */
5627: oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ERO);
5628: if (oc != NULL) {
5629: unsigned req;
5630: int i;
5631:
5632: if (!evaluate_option_cache(&packet_ero, packet,
5633: NULL, NULL,
5634: packet->options, NULL,
5635: &global_scope, oc, MDL) ||
5636: (packet_ero.len & 1)) {
5637: log_error("dhcpv6_relay_forw: error evaluating ERO.");
5638: goto exit;
5639: }
5640:
5641: /* Decode and apply the ERO. */
5642: for (i = 0; i < packet_ero.len; i += 2) {
5643: req = getUShort(packet_ero.data + i);
5644: /* Already in the reply? */
5645: oc = lookup_option(&dhcpv6_universe, opt_state, req);
5646: if (oc != NULL)
5647: continue;
5648: /* Get it from the packet if present. */
5649: oc = lookup_option(&dhcpv6_universe,
5650: packet->options,
5651: req);
5652: if (oc == NULL)
5653: continue;
5654: if (!evaluate_option_cache(&a_opt, packet,
5655: NULL, NULL,
5656: packet->options, NULL,
5657: &global_scope, oc, MDL)) {
5658: log_error("dhcpv6_relay_forw: error "
5659: "evaluating option %u.", req);
5660: goto exit;
5661: }
5662: if (!save_option_buffer(&dhcpv6_universe,
5663: opt_state,
5664: NULL,
5665: (unsigned char *)a_opt.data,
5666: a_opt.len,
5667: req,
5668: 0)) {
5669: log_error("dhcpv6_relay_forw: error saving "
5670: "option %u.", req);
5671: goto exit;
5672: }
5673: data_string_forget(&a_opt, MDL);
5674: }
5675: }
5676:
5677: reply_ofs += store_options6(reply_data + reply_ofs,
5678: sizeof(reply_data) - reply_ofs,
5679: opt_state, packet,
5680: required_opts_agent, &packet_ero);
5681:
5682: /*
5683: * Return our reply to the caller.
5684: */
5685: reply_ret->len = reply_ofs;
5686: reply_ret->buffer = NULL;
5687: if (!buffer_allocate(&reply_ret->buffer, reply_ret->len, MDL)) {
5688: log_fatal("No memory to store reply.");
5689: }
5690: reply_ret->data = reply_ret->buffer->data;
5691: memcpy(reply_ret->buffer->data, reply_data, reply_ofs);
5692:
5693: exit:
5694: if (opt_state != NULL)
5695: option_state_dereference(&opt_state, MDL);
5696: if (a_opt.data != NULL) {
5697: data_string_forget(&a_opt, MDL);
5698: }
5699: if (packet_ero.data != NULL) {
5700: data_string_forget(&packet_ero, MDL);
5701: }
5702: if (enc_reply.data != NULL) {
5703: data_string_forget(&enc_reply, MDL);
5704: }
5705: if (enc_opt_data.data != NULL) {
5706: data_string_forget(&enc_opt_data, MDL);
5707: }
5708: if (enc_packet != NULL) {
5709: packet_dereference(&enc_packet, MDL);
5710: }
5711: }
5712:
5713: static void
5714: dhcpv6_discard(struct packet *packet) {
5715: /* INSIST(packet->msg_type > 0); */
5716: /* INSIST(packet->msg_type < dhcpv6_type_name_max); */
5717:
5718: log_debug("Discarding %s from %s; message type not handled by server",
5719: dhcpv6_type_names[packet->dhcpv6_msg_type],
5720: piaddr(packet->client_addr));
5721: }
5722:
5723: static void
5724: build_dhcpv6_reply(struct data_string *reply, struct packet *packet) {
5725: memset(reply, 0, sizeof(*reply));
5726: switch (packet->dhcpv6_msg_type) {
5727: case DHCPV6_SOLICIT:
5728: dhcpv6_solicit(reply, packet);
5729: break;
5730: case DHCPV6_ADVERTISE:
5731: dhcpv6_discard(packet);
5732: break;
5733: case DHCPV6_REQUEST:
5734: dhcpv6_request(reply, packet);
5735: break;
5736: case DHCPV6_CONFIRM:
5737: dhcpv6_confirm(reply, packet);
5738: break;
5739: case DHCPV6_RENEW:
5740: dhcpv6_renew(reply, packet);
5741: break;
5742: case DHCPV6_REBIND:
5743: dhcpv6_rebind(reply, packet);
5744: break;
5745: case DHCPV6_REPLY:
5746: dhcpv6_discard(packet);
5747: break;
5748: case DHCPV6_RELEASE:
5749: dhcpv6_release(reply, packet);
5750: break;
5751: case DHCPV6_DECLINE:
5752: dhcpv6_decline(reply, packet);
5753: break;
5754: case DHCPV6_RECONFIGURE:
5755: dhcpv6_discard(packet);
5756: break;
5757: case DHCPV6_INFORMATION_REQUEST:
5758: dhcpv6_information_request(reply, packet);
5759: break;
5760: case DHCPV6_RELAY_FORW:
5761: dhcpv6_relay_forw(reply, packet);
5762: break;
5763: case DHCPV6_RELAY_REPL:
5764: dhcpv6_discard(packet);
5765: break;
5766: case DHCPV6_LEASEQUERY:
5767: dhcpv6_leasequery(reply, packet);
5768: break;
5769: case DHCPV6_LEASEQUERY_REPLY:
5770: dhcpv6_discard(packet);
5771: break;
5772: default:
5773: /* XXX: would be nice if we had "notice" level,
5774: as syslog, for this */
5775: log_info("Discarding unknown DHCPv6 message type %d "
5776: "from %s", packet->dhcpv6_msg_type,
5777: piaddr(packet->client_addr));
5778: }
5779: }
5780:
5781: static void
5782: log_packet_in(const struct packet *packet) {
5783: struct data_string s;
5784: u_int32_t tid;
5785: char tmp_addr[INET6_ADDRSTRLEN];
5786: const void *addr;
5787:
5788: memset(&s, 0, sizeof(s));
5789:
5790: if (packet->dhcpv6_msg_type < dhcpv6_type_name_max) {
5791: data_string_sprintfa(&s, "%s message from %s port %d",
5792: dhcpv6_type_names[packet->dhcpv6_msg_type],
5793: piaddr(packet->client_addr),
5794: ntohs(packet->client_port));
5795: } else {
5796: data_string_sprintfa(&s,
5797: "Unknown message type %d from %s port %d",
5798: packet->dhcpv6_msg_type,
5799: piaddr(packet->client_addr),
5800: ntohs(packet->client_port));
5801: }
5802: if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) ||
5803: (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
5804: addr = &packet->dhcpv6_link_address;
5805: data_string_sprintfa(&s, ", link address %s",
5806: inet_ntop(AF_INET6, addr,
5807: tmp_addr, sizeof(tmp_addr)));
5808: addr = &packet->dhcpv6_peer_address;
5809: data_string_sprintfa(&s, ", peer address %s",
5810: inet_ntop(AF_INET6, addr,
5811: tmp_addr, sizeof(tmp_addr)));
5812: } else {
5813: tid = 0;
5814: memcpy(((char *)&tid)+1, packet->dhcpv6_transaction_id, 3);
5815: data_string_sprintfa(&s, ", transaction ID 0x%06X", tid);
5816:
5817: /*
5818: oc = lookup_option(&dhcpv6_universe, packet->options,
5819: D6O_CLIENTID);
5820: if (oc != NULL) {
5821: memset(&tmp_ds, 0, sizeof(tmp_ds_));
5822: if (!evaluate_option_cache(&tmp_ds, packet, NULL, NULL,
5823: packet->options, NULL,
5824: &global_scope, oc, MDL)) {
5825: log_error("Error evaluating Client Identifier");
5826: } else {
5827: data_strint_sprintf(&s, ", client ID %s",
5828:
5829: data_string_forget(&tmp_ds, MDL);
5830: }
5831: }
5832: */
5833:
5834: }
5835: log_info("%s", s.data);
5836:
5837: data_string_forget(&s, MDL);
5838: }
5839:
5840: void
5841: dhcpv6(struct packet *packet) {
5842: struct data_string reply;
5843: struct sockaddr_in6 to_addr;
5844: int send_ret;
5845:
5846: /*
5847: * Log a message that we received this packet.
5848: */
5849: log_packet_in(packet);
5850:
5851: /*
5852: * Build our reply packet.
5853: */
5854: build_dhcpv6_reply(&reply, packet);
5855:
5856: if (reply.data != NULL) {
5857: /*
5858: * Send our reply, if we have one.
5859: */
5860: memset(&to_addr, 0, sizeof(to_addr));
5861: to_addr.sin6_family = AF_INET6;
5862: if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) ||
5863: (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
5864: to_addr.sin6_port = local_port;
5865: } else {
5866: to_addr.sin6_port = remote_port;
5867: }
5868:
5869: #if defined (REPLY_TO_SOURCE_PORT)
5870: /*
5871: * This appears to have been included for testing so we would
5872: * not need a root client, but was accidently left in the
5873: * final code. We continue to include it in case
5874: * some users have come to rely upon it, but leave
5875: * it off by default as it's a bad idea.
5876: */
5877: to_addr.sin6_port = packet->client_port;
5878: #endif
5879:
5880: memcpy(&to_addr.sin6_addr, packet->client_addr.iabuf,
5881: sizeof(to_addr.sin6_addr));
5882:
5883: log_info("Sending %s to %s port %d",
5884: dhcpv6_type_names[reply.data[0]],
5885: piaddr(packet->client_addr),
5886: ntohs(to_addr.sin6_port));
5887:
5888: send_ret = send_packet6(packet->interface,
5889: reply.data, reply.len, &to_addr);
5890: if (send_ret != reply.len) {
5891: log_error("dhcpv6: send_packet6() sent %d of %d bytes",
5892: send_ret, reply.len);
5893: }
5894: data_string_forget(&reply, MDL);
5895: }
5896: }
5897:
5898: static void
5899: seek_shared_host(struct host_decl **hp, struct shared_network *shared) {
5900: struct host_decl *nofixed = NULL;
5901: struct host_decl *seek, *hold = NULL;
5902:
5903: /*
5904: * Seek forward through fixed addresses for the right link.
5905: *
5906: * Note: how to do this for fixed prefixes???
5907: */
5908: host_reference(&hold, *hp, MDL);
5909: host_dereference(hp, MDL);
5910: seek = hold;
5911: while (seek != NULL) {
5912: if (seek->fixed_addr == NULL)
5913: nofixed = seek;
5914: else if (fixed_matches_shared(seek, shared))
5915: break;
5916:
5917: seek = seek->n_ipaddr;
5918: }
5919:
5920: if ((seek == NULL) && (nofixed != NULL))
5921: seek = nofixed;
5922:
5923: if (seek != NULL)
5924: host_reference(hp, seek, MDL);
5925: }
5926:
5927: static isc_boolean_t
5928: fixed_matches_shared(struct host_decl *host, struct shared_network *shared) {
5929: struct subnet *subnet;
5930: struct data_string addr;
5931: isc_boolean_t matched;
5932: struct iaddr fixed;
5933:
5934: if (host->fixed_addr == NULL)
5935: return ISC_FALSE;
5936:
5937: memset(&addr, 0, sizeof(addr));
5938: if (!evaluate_option_cache(&addr, NULL, NULL, NULL, NULL, NULL,
5939: &global_scope, host->fixed_addr, MDL))
5940: return ISC_FALSE;
5941:
5942: if (addr.len < 16) {
5943: data_string_forget(&addr, MDL);
5944: return ISC_FALSE;
5945: }
5946:
5947: fixed.len = 16;
5948: memcpy(fixed.iabuf, addr.data, 16);
5949:
5950: matched = ISC_FALSE;
5951: for (subnet = shared->subnets ; subnet != NULL ;
5952: subnet = subnet->next_sibling) {
5953: if (addr_eq(subnet_number(fixed, subnet->netmask),
5954: subnet->net)) {
5955: matched = ISC_TRUE;
5956: break;
5957: }
5958: }
5959:
5960: data_string_forget(&addr, MDL);
5961: return matched;
5962: }
5963:
5964: #endif /* DHCPv6 */
5965:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>