server/dhcpv6.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006-2013 by Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00019 #include "dhcpd.h"
00020 #include "trace.h"
00021 
00022 #ifdef DHCPv6
00023 
00024 /*
00025  * We use print_hex_1() to output DUID values. We could actually output 
00026  * the DUID with more information... MAC address if using type 1 or 3, 
00027  * and so on. However, RFC 3315 contains Grave Warnings against actually 
00028  * attempting to understand a DUID.
00029  */
00030 
00031 /* 
00032  * TODO: gettext() or other method of localization for the messages
00033  *       for status codes (and probably for log formats eventually)
00034  * TODO: refactoring (simplify, simplify, simplify)
00035  * TODO: support multiple shared_networks on each interface (this 
00036  *       will allow the server to issue multiple IPv6 addresses to 
00037  *       a single interface)
00038  */
00039 
00040 /*
00041  * DHCPv6 Reply workflow assist.  A Reply packet is built by various
00042  * different functions; this gives us one location where we keep state
00043  * regarding a reply.
00044  */
00045 struct reply_state {
00046         /* root level persistent state */
00047         struct shared_network *shared;
00048         struct host_decl *host;
00049         struct subnet *subnet; /* Used to match fixed-addrs to subnet scopes. */
00050         struct option_state *opt_state;
00051         struct packet *packet;
00052         struct data_string client_id;
00053 
00054         /* IA level persistent state */
00055         unsigned ia_count;
00056         unsigned pd_count;
00057         unsigned client_resources;
00058         isc_boolean_t resources_included;
00059         isc_boolean_t static_lease;
00060         unsigned static_prefixes;
00061         struct ia_xx *ia;
00062         struct ia_xx *old_ia;
00063         struct option_state *reply_ia;
00064         struct data_string fixed;
00065         struct iaddrcidrnet fixed_pref; /* static prefix for logging */
00066 
00067         /* IAADDR/PREFIX level persistent state */
00068         struct iasubopt *lease;
00069 
00070         /*
00071          * "t1", "t2", preferred, and valid lifetimes records for calculating
00072          * t1 and t2 (min/max).
00073          */
00074         u_int32_t renew, rebind, prefer, valid;
00075 
00076         /* Client-requested valid and preferred lifetimes. */
00077         u_int32_t client_valid, client_prefer;
00078 
00079         /* Chosen values to transmit for valid and preferred lifetimes. */
00080         u_int32_t send_valid, send_prefer;
00081 
00082         /* Preferred prefix length (-1 is any). */
00083         int preflen;
00084 
00085         /* Index into the data field that has been consumed. */
00086         unsigned cursor;
00087 
00088         /* Space for the on commit statements for a fixed host */
00089         struct on_star on_star;
00090 
00091         union reply_buffer {
00092                 unsigned char data[65536];
00093                 struct dhcpv6_packet reply;
00094         } buf;
00095 };
00096 
00097 /* 
00098  * Prototypes local to this file.
00099  */
00100 static int get_encapsulated_IA_state(struct option_state **enc_opt_state,
00101                                      struct data_string *enc_opt_data,
00102                                      struct packet *packet,
00103                                      struct option_cache *oc,
00104                                      int offset);
00105 static void build_dhcpv6_reply(struct data_string *, struct packet *);
00106 static isc_result_t shared_network_from_packet6(struct shared_network **shared,
00107                                                 struct packet *packet);
00108 static void seek_shared_host(struct host_decl **hp,
00109                              struct shared_network *shared);
00110 static isc_boolean_t fixed_matches_shared(struct host_decl *host,
00111                                           struct shared_network *shared);
00112 static isc_result_t reply_process_ia_na(struct reply_state *reply,
00113                                         struct option_cache *ia);
00114 static isc_result_t reply_process_ia_ta(struct reply_state *reply,
00115                                         struct option_cache *ia);
00116 static isc_result_t reply_process_addr(struct reply_state *reply,
00117                                        struct option_cache *addr);
00118 static isc_boolean_t address_is_owned(struct reply_state *reply,
00119                                       struct iaddr *addr);
00120 static isc_boolean_t temporary_is_available(struct reply_state *reply,
00121                                             struct iaddr *addr);
00122 static isc_result_t find_client_temporaries(struct reply_state *reply);
00123 static isc_result_t reply_process_try_addr(struct reply_state *reply,
00124                                            struct iaddr *addr);
00125 static isc_result_t find_client_address(struct reply_state *reply);
00126 static isc_result_t reply_process_is_addressed(struct reply_state *reply,
00127                                                struct binding_scope **scope,
00128                                                struct group *group);
00129 static isc_result_t reply_process_send_addr(struct reply_state *reply,
00130                                             struct iaddr *addr);
00131 static struct iasubopt *lease_compare(struct iasubopt *alpha,
00132                                       struct iasubopt *beta);
00133 static isc_result_t reply_process_ia_pd(struct reply_state *reply,
00134                                         struct option_cache *ia_pd);
00135 static isc_result_t reply_process_prefix(struct reply_state *reply,
00136                                          struct option_cache *pref);
00137 static isc_boolean_t prefix_is_owned(struct reply_state *reply,
00138                                      struct iaddrcidrnet *pref);
00139 static isc_result_t find_client_prefix(struct reply_state *reply);
00140 static isc_result_t reply_process_try_prefix(struct reply_state *reply,
00141                                              struct iaddrcidrnet *pref);
00142 static isc_result_t reply_process_is_prefixed(struct reply_state *reply,
00143                                               struct binding_scope **scope,
00144                                               struct group *group);
00145 static isc_result_t reply_process_send_prefix(struct reply_state *reply,
00146                                               struct iaddrcidrnet *pref);
00147 static struct iasubopt *prefix_compare(struct reply_state *reply,
00148                                        struct iasubopt *alpha,
00149                                        struct iasubopt *beta);
00150 static int find_hosts_by_duid_chaddr(struct host_decl **host,
00151                                      const struct data_string *client_id);
00152 /*
00153  * This function returns the time since DUID time start for the
00154  * given time_t value.
00155  */
00156 static u_int32_t
00157 duid_time(time_t when) {
00158         /*
00159          * This time is modulo 2^32.
00160          */
00161         while ((when - DUID_TIME_EPOCH) > 4294967295u) {
00162                 /* use 2^31 to avoid spurious compiler warnings */
00163                 when -= 2147483648u;
00164                 when -= 2147483648u;
00165         }
00166 
00167         return when - DUID_TIME_EPOCH;
00168 }
00169 
00170 
00171 /* 
00172  * Server DUID.
00173  *
00174  * This must remain the same for the lifetime of this server, because
00175  * clients return the server DUID that we sent them in Request packets.
00176  *
00177  * We pick the server DUID like this:
00178  *
00179  * 1. Check dhcpd.conf - any value the administrator has configured 
00180  *    overrides any possible values.
00181  * 2. Check the leases.txt - we want to use the previous value if 
00182  *    possible.
00183  * 3. Check if dhcpd.conf specifies a type of server DUID to use,
00184  *    and generate that type.
00185  * 4. Generate a type 1 (time + hardware address) DUID.
00186  */
00187 static struct data_string server_duid;
00188 
00189 /*
00190  * Check if the server_duid has been set.
00191  */
00192 isc_boolean_t
00193 server_duid_isset(void) {
00194         return (server_duid.data != NULL);
00195 }
00196 
00197 /*
00198  * Return the server_duid.
00199  */
00200 void
00201 copy_server_duid(struct data_string *ds, const char *file, int line) {
00202         data_string_copy(ds, &server_duid, file, line);
00203 }
00204 
00205 /*
00206  * Set the server DUID to a specified value. This is used when
00207  * the server DUID is stored in persistent memory (basically the
00208  * leases.txt file).
00209  */
00210 void
00211 set_server_duid(struct data_string *new_duid) {
00212         /* INSIST(new_duid != NULL); */
00213         /* INSIST(new_duid->data != NULL); */
00214 
00215         if (server_duid_isset()) {
00216                 data_string_forget(&server_duid, MDL);
00217         }
00218         data_string_copy(&server_duid, new_duid, MDL);
00219 }
00220 
00221 
00222 /*
00223  * Set the server DUID based on the D6O_SERVERID option. This handles
00224  * the case where the administrator explicitly put it in the dhcpd.conf 
00225  * file.
00226  */
00227 isc_result_t
00228 set_server_duid_from_option(void) {
00229         struct option_state *opt_state;
00230         struct option_cache *oc;
00231         struct data_string option_duid;
00232         isc_result_t ret_val;
00233 
00234         opt_state = NULL;
00235         if (!option_state_allocate(&opt_state, MDL)) {
00236                 log_fatal("No memory for server DUID.");
00237         }
00238 
00239         execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
00240                                     opt_state, &global_scope, root_group,
00241                                     NULL, NULL);
00242 
00243         oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
00244         if (oc == NULL) {
00245                 ret_val = ISC_R_NOTFOUND;
00246         } else {
00247                 memset(&option_duid, 0, sizeof(option_duid));
00248                 if (!evaluate_option_cache(&option_duid, NULL, NULL, NULL,
00249                                            opt_state, NULL, &global_scope,
00250                                            oc, MDL)) {
00251                         ret_val = ISC_R_UNEXPECTED;
00252                 } else {
00253                         set_server_duid(&option_duid);
00254                         data_string_forget(&option_duid, MDL);
00255                         ret_val = ISC_R_SUCCESS;
00256                 }
00257         }
00258 
00259         option_state_dereference(&opt_state, MDL);
00260 
00261         return ret_val;
00262 }
00263 
00264 /*
00265  * DUID layout, as defined in RFC 3315, section 9.
00266  * 
00267  * We support type 1 (hardware address plus time) and type 3 (hardware
00268  * address).
00269  *
00270  * We can support type 2 for specific vendors in the future, if they 
00271  * publish the specification. And of course there may be additional
00272  * types later.
00273  */
00274 static int server_duid_type = DUID_LLT;
00275 
00276 /* 
00277  * Set the DUID type.
00278  */
00279 void
00280 set_server_duid_type(int type) {
00281         server_duid_type = type;
00282 }
00283 
00284 /*
00285  * Generate a new server DUID. This is done if there was no DUID in 
00286  * the leases.txt or in the dhcpd.conf file.
00287  */
00288 isc_result_t
00289 generate_new_server_duid(void) {
00290         struct interface_info *p;
00291         u_int32_t time_val;
00292         struct data_string generated_duid;
00293 
00294         /*
00295          * Verify we have a type that we support.
00296          */
00297         if ((server_duid_type != DUID_LL) && (server_duid_type != DUID_LLT)) {
00298                 log_error("Invalid DUID type %d specified, "
00299                           "only LL and LLT types supported", server_duid_type);
00300                 return DHCP_R_INVALIDARG;
00301         }
00302 
00303         /*
00304          * Find an interface with a hardware address.
00305          * Any will do. :)
00306          */
00307         for (p = interfaces; p != NULL; p = p->next) {
00308                 if (p->hw_address.hlen > 0) {
00309                         break;
00310                 }
00311                 if (p->next == NULL && p->hw_address.hbuf[0] == HTYPE_RESERVED) {
00312                         log_error("Can not generate DUID from interfaces which do not have hardware addresses, please configure server-duid!");
00313                 }
00314         }
00315         if (p == NULL) {
00316                 return ISC_R_UNEXPECTED;
00317         }
00318 
00319         /*
00320          * Build our DUID.
00321          */
00322         memset(&generated_duid, 0, sizeof(generated_duid));
00323         if (server_duid_type == DUID_LLT) {
00324                 time_val = duid_time(time(NULL));
00325                 generated_duid.len = 8 + p->hw_address.hlen - 1;
00326                 if (!buffer_allocate(&generated_duid.buffer,
00327                                      generated_duid.len, MDL)) {
00328                         log_fatal("No memory for server DUID.");
00329                 }
00330                 generated_duid.data = generated_duid.buffer->data;
00331                 putUShort(generated_duid.buffer->data, DUID_LLT);
00332                 putUShort(generated_duid.buffer->data + 2,
00333                           p->hw_address.hbuf[0]);
00334                 putULong(generated_duid.buffer->data + 4, time_val);
00335                 memcpy(generated_duid.buffer->data + 8,
00336                        p->hw_address.hbuf+1, p->hw_address.hlen-1);
00337         } else if (server_duid_type == DUID_LL) {
00338                 generated_duid.len = 4 + p->hw_address.hlen - 1;
00339                 if (!buffer_allocate(&generated_duid.buffer,
00340                                      generated_duid.len, MDL)) {
00341                         log_fatal("No memory for server DUID.");
00342                 }
00343                 generated_duid.data = generated_duid.buffer->data;
00344                 putUShort(generated_duid.buffer->data, DUID_LL);
00345                 putUShort(generated_duid.buffer->data + 2,
00346                           p->hw_address.hbuf[0]);
00347                 memcpy(generated_duid.buffer->data + 4,
00348                        p->hw_address.hbuf+1, p->hw_address.hlen-1);
00349         } else {
00350                 log_fatal("Unsupported server DUID type %d.", server_duid_type);
00351         }
00352 
00353         set_server_duid(&generated_duid);
00354         data_string_forget(&generated_duid, MDL);
00355 
00356         return ISC_R_SUCCESS;
00357 }
00358 
00359 /*
00360  * Is the D6O_UNICAST option defined in dhcpd.conf ?
00361  */
00362 static isc_boolean_t unicast_option_defined;
00363 
00364 /*
00365  * Did we already search dhcpd.conf for D6O_UNICAST option ?
00366  * We need to store it here to not parse dhcpd.conf repeatedly.
00367  */
00368 static isc_boolean_t unicast_option_parsed = ISC_FALSE;
00369 
00370 
00371 /*
00372  * Is the D6O_UNICAST option defined in dhcpd.conf ?
00373  */
00374 isc_boolean_t
00375 is_unicast_option_defined(void) {
00376         struct option_state *opt_state;
00377         struct option_cache *oc;
00378 
00379         /*
00380          * If we are looking for the unicast option for the first time
00381          */
00382         if (unicast_option_parsed == ISC_FALSE) {
00383                 unicast_option_parsed = ISC_TRUE;
00384                 opt_state = NULL;
00385                 if (!option_state_allocate(&opt_state, MDL)) {
00386                         log_fatal("No memory for option state.");
00387                 }
00388 
00389                 execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
00390                              opt_state, &global_scope, root_group, NULL, NULL);
00391 
00392                 oc = lookup_option(&dhcpv6_universe, opt_state, D6O_UNICAST);
00393                 unicast_option_defined = (oc != NULL);
00394 
00395                 option_state_dereference(&opt_state, MDL);
00396         }
00397 
00398         return (unicast_option_defined);
00399 }
00400 
00401 /*
00402  * Get the client identifier from the packet.
00403  */
00404 isc_result_t
00405 get_client_id(struct packet *packet, struct data_string *client_id) {
00406         struct option_cache *oc;
00407 
00408         /*
00409          * Verify our client_id structure is empty.
00410          */
00411         if ((client_id->data != NULL) || (client_id->len != 0)) {
00412                 return DHCP_R_INVALIDARG;
00413         }
00414 
00415         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_CLIENTID);
00416         if (oc == NULL) {
00417                 return ISC_R_NOTFOUND;
00418         }
00419 
00420         if (!evaluate_option_cache(client_id, packet, NULL, NULL,
00421                                    packet->options, NULL,
00422                                    &global_scope, oc, MDL)) {
00423                 return ISC_R_FAILURE;
00424         }
00425 
00426         return ISC_R_SUCCESS;
00427 }
00428 
00429 /*
00430  * Message validation, defined in RFC 3315, sections 15.2, 15.5, 15.7:
00431  *
00432  *    Servers MUST discard any Solicit messages that do not include a
00433  *    Client Identifier option or that do include a Server Identifier
00434  *    option.
00435  */
00436 int
00437 valid_client_msg(struct packet *packet, struct data_string *client_id) {
00438         int ret_val;
00439         struct option_cache *oc;
00440         struct data_string data;
00441 
00442         ret_val = 0;
00443         memset(client_id, 0, sizeof(*client_id));
00444         memset(&data, 0, sizeof(data));
00445 
00446         switch (get_client_id(packet, client_id)) {
00447                 case ISC_R_SUCCESS:
00448                         break;
00449                 case ISC_R_NOTFOUND:
00450                         log_debug("Discarding %s from %s; "
00451                                   "client identifier missing",
00452                                   dhcpv6_type_names[packet->dhcpv6_msg_type],
00453                                   piaddr(packet->client_addr));
00454                         goto exit;
00455                 default:
00456                         log_error("Error processing %s from %s; "
00457                                   "unable to evaluate Client Identifier",
00458                                   dhcpv6_type_names[packet->dhcpv6_msg_type],
00459                                   piaddr(packet->client_addr));
00460                         goto exit;
00461         }
00462 
00463         /*
00464          * Required by RFC 3315, section 15.
00465          */
00466         if (packet->unicast) {
00467                 log_debug("Discarding %s from %s; packet sent unicast "
00468                           "(CLIENTID %s)",
00469                           dhcpv6_type_names[packet->dhcpv6_msg_type],
00470                           piaddr(packet->client_addr),
00471                           print_hex_1(client_id->len, client_id->data, 60));
00472                 goto exit;
00473         }
00474 
00475 
00476         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
00477         if (oc != NULL) {
00478                 if (evaluate_option_cache(&data, packet, NULL, NULL,
00479                                           packet->options, NULL,
00480                                           &global_scope, oc, MDL)) {
00481                         log_debug("Discarding %s from %s; "
00482                                   "server identifier found "
00483                                   "(CLIENTID %s, SERVERID %s)",
00484                                   dhcpv6_type_names[packet->dhcpv6_msg_type],
00485                                   piaddr(packet->client_addr),
00486                                   print_hex_1(client_id->len,
00487                                               client_id->data, 60),
00488                                   print_hex_2(data.len,
00489                                               data.data, 60));
00490                 } else {
00491                         log_debug("Discarding %s from %s; "
00492                                   "server identifier found "
00493                                   "(CLIENTID %s)",
00494                                   dhcpv6_type_names[packet->dhcpv6_msg_type],
00495                                   print_hex_1(client_id->len,
00496                                               client_id->data, 60),
00497                                   piaddr(packet->client_addr));
00498                 }
00499                 goto exit;
00500         }
00501 
00502         /* looks good */
00503         ret_val = 1;
00504 
00505 exit:
00506         if (data.len > 0) {
00507                 data_string_forget(&data, MDL);
00508         }
00509         if (!ret_val) {
00510                 if (client_id->len > 0) {
00511                         data_string_forget(client_id, MDL);
00512                 }
00513         }
00514         return ret_val;
00515 }
00516 
00517 /*
00518  * Response validation, defined in RFC 3315, sections 15.4, 15.6, 15.8, 
00519  * 15.9 (slightly different wording, but same meaning):
00520  *
00521  *   Servers MUST discard any received Request message that meet any of
00522  *   the following conditions:
00523  *
00524  *   -  the message does not include a Server Identifier option.
00525  *   -  the contents of the Server Identifier option do not match the
00526  *      server's DUID.
00527  *   -  the message does not include a Client Identifier option.
00528  */
00529 int
00530 valid_client_resp(struct packet *packet,
00531                   struct data_string *client_id,
00532                   struct data_string *server_id)
00533 {
00534         int ret_val;
00535         struct option_cache *oc;
00536 
00537         /* INSIST((duid.data != NULL) && (duid.len > 0)); */
00538 
00539         ret_val = 0;
00540         memset(client_id, 0, sizeof(*client_id));
00541         memset(server_id, 0, sizeof(*server_id));
00542 
00543         switch (get_client_id(packet, client_id)) {
00544                 case ISC_R_SUCCESS:
00545                         break;
00546                 case ISC_R_NOTFOUND:
00547                         log_debug("Discarding %s from %s; "
00548                                   "client identifier missing",
00549                                   dhcpv6_type_names[packet->dhcpv6_msg_type],
00550                                   piaddr(packet->client_addr));
00551                         goto exit;
00552                 default:
00553                         log_error("Error processing %s from %s; "
00554                                   "unable to evaluate Client Identifier",
00555                                   dhcpv6_type_names[packet->dhcpv6_msg_type],
00556                                   piaddr(packet->client_addr));
00557                         goto exit;
00558         }
00559 
00560         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
00561         if (oc == NULL) {
00562                 log_debug("Discarding %s from %s: "
00563                           "server identifier missing (CLIENTID %s)",
00564                           dhcpv6_type_names[packet->dhcpv6_msg_type],
00565                           piaddr(packet->client_addr),
00566                           print_hex_1(client_id->len, client_id->data, 60));
00567                 goto exit;
00568         }
00569         if (!evaluate_option_cache(server_id, packet, NULL, NULL,
00570                                    packet->options, NULL,
00571                                    &global_scope, oc, MDL)) {
00572                 log_error("Error processing %s from %s; "
00573                           "unable to evaluate Server Identifier (CLIENTID %s)",
00574                           dhcpv6_type_names[packet->dhcpv6_msg_type],
00575                           piaddr(packet->client_addr),
00576                           print_hex_1(client_id->len, client_id->data, 60));
00577                 goto exit;
00578         }
00579         if ((server_duid.len != server_id->len) ||
00580             (memcmp(server_duid.data, server_id->data, server_duid.len) != 0)) {
00581                 log_debug("Discarding %s from %s; "
00582                           "not our server identifier "
00583                           "(CLIENTID %s, SERVERID %s, server DUID %s)",
00584                           dhcpv6_type_names[packet->dhcpv6_msg_type],
00585                           piaddr(packet->client_addr),
00586                           print_hex_1(client_id->len, client_id->data, 60),
00587                           print_hex_2(server_id->len, server_id->data, 60),
00588                           print_hex_3(server_duid.len, server_duid.data, 60));
00589                 goto exit;
00590         }
00591 
00592         /* looks good */
00593         ret_val = 1;
00594 
00595 exit:
00596         if (!ret_val) {
00597                 if (server_id->len > 0) {
00598                         data_string_forget(server_id, MDL);
00599                 }
00600                 if (client_id->len > 0) {
00601                         data_string_forget(client_id, MDL);
00602                 }
00603         }
00604         return ret_val;
00605 }
00606 
00607 /*
00608  * Information request validation, defined in RFC 3315, section 15.12:
00609  *
00610  *   Servers MUST discard any received Information-request message that
00611  *   meets any of the following conditions:
00612  *
00613  *   -  The message includes a Server Identifier option and the DUID in
00614  *      the option does not match the server's DUID.
00615  *
00616  *   -  The message includes an IA option.
00617  */
00618 int
00619 valid_client_info_req(struct packet *packet, struct data_string *server_id) {
00620         int ret_val;
00621         struct option_cache *oc;
00622         struct data_string client_id;
00623         char client_id_str[80]; /* print_hex_1() uses maximum 60 characters,
00624                                    plus a few more for extra information */
00625 
00626         ret_val = 0;
00627         memset(server_id, 0, sizeof(*server_id));
00628         memset(&client_id, 0, sizeof(client_id));
00629 
00630         /*
00631          * Make a string that we can print out to give more 
00632          * information about the client if we need to.
00633          *
00634          * By RFC 3315, Section 18.1.5 clients SHOULD have a 
00635          * client-id on an Information-request packet, but it 
00636          * is not strictly necessary.
00637          */
00638         if (get_client_id(packet, &client_id) == ISC_R_SUCCESS) {
00639                 snprintf(client_id_str, sizeof(client_id_str), " (CLIENTID %s)",
00640                          print_hex_1(client_id.len, client_id.data, 60));
00641                 data_string_forget(&client_id, MDL);
00642         } else {
00643                 client_id_str[0] = '\0';
00644         }
00645 
00646         /*
00647          * Required by RFC 3315, section 15.
00648          */
00649         if (packet->unicast) {
00650                 log_debug("Discarding %s from %s; packet sent unicast%s",
00651                           dhcpv6_type_names[packet->dhcpv6_msg_type],
00652                           piaddr(packet->client_addr), client_id_str);
00653                 goto exit;
00654         }
00655 
00656         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
00657         if (oc != NULL) {
00658                 log_debug("Discarding %s from %s; "
00659                           "IA_NA option present%s",
00660                           dhcpv6_type_names[packet->dhcpv6_msg_type],
00661                           piaddr(packet->client_addr), client_id_str);
00662                 goto exit;
00663         }
00664         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
00665         if (oc != NULL) {
00666                 log_debug("Discarding %s from %s; "
00667                           "IA_TA option present%s",
00668                           dhcpv6_type_names[packet->dhcpv6_msg_type],
00669                           piaddr(packet->client_addr), client_id_str);
00670                 goto exit;
00671         }
00672         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
00673         if (oc != NULL) {
00674                 log_debug("Discarding %s from %s; "
00675                           "IA_PD option present%s",
00676                           dhcpv6_type_names[packet->dhcpv6_msg_type],
00677                           piaddr(packet->client_addr), client_id_str);
00678                 goto exit;
00679         }
00680 
00681         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_SERVERID);
00682         if (oc != NULL) {
00683                 if (!evaluate_option_cache(server_id, packet, NULL, NULL,
00684                                            packet->options, NULL,
00685                                            &global_scope, oc, MDL)) {
00686                         log_error("Error processing %s from %s; "
00687                                   "unable to evaluate Server Identifier%s",
00688                                   dhcpv6_type_names[packet->dhcpv6_msg_type],
00689                                   piaddr(packet->client_addr), client_id_str);
00690                         goto exit;
00691                 }
00692                 if ((server_duid.len != server_id->len) ||
00693                     (memcmp(server_duid.data, server_id->data,
00694                             server_duid.len) != 0)) {
00695                         log_debug("Discarding %s from %s; "
00696                                   "not our server identifier "
00697                                   "(SERVERID %s, server DUID %s)%s",
00698                                   dhcpv6_type_names[packet->dhcpv6_msg_type],
00699                                   piaddr(packet->client_addr),
00700                                   print_hex_1(server_id->len,
00701                                               server_id->data, 60),
00702                                   print_hex_2(server_duid.len,
00703                                               server_duid.data, 60),
00704                                   client_id_str);
00705                         goto exit;
00706                 }
00707         }
00708 
00709         /* looks good */
00710         ret_val = 1;
00711 
00712 exit:
00713         if (!ret_val) {
00714                 if (server_id->len > 0) {
00715                         data_string_forget(server_id, MDL);
00716                 }
00717         }
00718         return ret_val;
00719 }
00720 
00721 /* 
00722  * Options that we want to send, in addition to what was requested
00723  * via the ORO.
00724  */
00725 static const int required_opts[] = {
00726         D6O_CLIENTID,
00727         D6O_SERVERID,
00728         D6O_STATUS_CODE,
00729         D6O_PREFERENCE,
00730         0
00731 };
00732 static const int required_opts_NAA[] = {
00733         D6O_CLIENTID,
00734         D6O_SERVERID,
00735         D6O_STATUS_CODE,
00736         0
00737 };
00738 static const int required_opts_solicit[] = {
00739         D6O_CLIENTID,
00740         D6O_SERVERID,
00741         D6O_IA_NA,
00742         D6O_IA_TA,
00743         D6O_IA_PD,
00744         D6O_RAPID_COMMIT,
00745         D6O_STATUS_CODE,
00746         D6O_RECONF_ACCEPT,
00747         D6O_PREFERENCE,
00748         0
00749 };
00750 static const int required_opts_agent[] = {
00751         D6O_INTERFACE_ID,
00752         D6O_RELAY_MSG,
00753         0
00754 };
00755 static const int required_opts_IA[] = {
00756         D6O_IAADDR,
00757         D6O_STATUS_CODE,
00758         0
00759 };
00760 static const int required_opts_IA_PD[] = {
00761         D6O_IAPREFIX,
00762         D6O_STATUS_CODE,
00763         0
00764 };
00765 static const int required_opts_STATUS_CODE[] = {
00766         D6O_STATUS_CODE,
00767         0
00768 };
00769 
00770 /*
00771  * Extracts from packet contents an IA_* option, storing the IA structure
00772  * in its entirety in enc_opt_data, and storing any decoded DHCPv6 options
00773  * in enc_opt_state for later lookup and evaluation.  The 'offset' indicates
00774  * where in the IA_* the DHCPv6 options commence.
00775  */
00776 static int
00777 get_encapsulated_IA_state(struct option_state **enc_opt_state,
00778                           struct data_string *enc_opt_data,
00779                           struct packet *packet,
00780                           struct option_cache *oc,
00781                           int offset)
00782 {
00783         /* 
00784          * Get the raw data for the encapsulated options.
00785          */
00786         memset(enc_opt_data, 0, sizeof(*enc_opt_data));
00787         if (!evaluate_option_cache(enc_opt_data, packet,
00788                                    NULL, NULL, packet->options, NULL,
00789                                    &global_scope, oc, MDL)) {
00790                 log_error("get_encapsulated_IA_state: "
00791                           "error evaluating raw option.");
00792                 return 0;
00793         }
00794         if (enc_opt_data->len < offset) {
00795                 log_error("get_encapsulated_IA_state: raw option too small.");
00796                 data_string_forget(enc_opt_data, MDL);
00797                 return 0;
00798         }
00799 
00800         /*
00801          * Now create the option state structure, and pass it to the 
00802          * function that parses options.
00803          */
00804         *enc_opt_state = NULL;
00805         if (!option_state_allocate(enc_opt_state, MDL)) {
00806                 log_error("get_encapsulated_IA_state: no memory for options.");
00807                 data_string_forget(enc_opt_data, MDL);
00808                 return 0;
00809         }
00810         if (!parse_option_buffer(*enc_opt_state,
00811                                  enc_opt_data->data + offset, 
00812                                  enc_opt_data->len - offset,
00813                                  &dhcpv6_universe)) {
00814                 log_error("get_encapsulated_IA_state: error parsing options.");
00815                 option_state_dereference(enc_opt_state, MDL);
00816                 data_string_forget(enc_opt_data, MDL);
00817                 return 0;
00818         }
00819 
00820         return 1;
00821 }
00822 
00823 static int
00824 set_status_code(u_int16_t status_code, const char *status_message,
00825                 struct option_state *opt_state)
00826 {
00827         struct data_string d;
00828         int ret_val;
00829 
00830         memset(&d, 0, sizeof(d));
00831         d.len = sizeof(status_code) + strlen(status_message);
00832         if (!buffer_allocate(&d.buffer, d.len, MDL)) {
00833                 log_fatal("set_status_code: no memory for status code.");
00834         }
00835         d.data = d.buffer->data;
00836         putUShort(d.buffer->data, status_code);
00837         memcpy(d.buffer->data + sizeof(status_code), 
00838                status_message, d.len - sizeof(status_code));
00839         if (!save_option_buffer(&dhcpv6_universe, opt_state, 
00840                                 d.buffer, (unsigned char *)d.data, d.len, 
00841                                 D6O_STATUS_CODE, 0)) {
00842                 log_error("set_status_code: error saving status code.");
00843                 ret_val = 0;
00844         } else {
00845                 ret_val = 1;
00846         }
00847         data_string_forget(&d, MDL);
00848         return ret_val;
00849 }
00850 
00851 /*
00852  * We have a set of operations we do to set up the reply packet, which
00853  * is the same for many message types.
00854  */
00855 static int
00856 start_reply(struct packet *packet,
00857             const struct data_string *client_id, 
00858             const struct data_string *server_id,
00859             struct option_state **opt_state,
00860             struct dhcpv6_packet *reply)
00861 {
00862         struct option_cache *oc;
00863         const unsigned char *server_id_data;
00864         int server_id_len;
00865 
00866         /*
00867          * Build our option state for reply.
00868          */
00869         *opt_state = NULL;
00870         if (!option_state_allocate(opt_state, MDL)) {
00871                 log_error("start_reply: no memory for option_state.");
00872                 return 0;
00873         }
00874         execute_statements_in_scope(NULL, packet, NULL, NULL,
00875                                     packet->options, *opt_state,
00876                                     &global_scope, root_group, NULL, NULL);
00877 
00878         /*
00879          * A small bit of special handling for Solicit messages.
00880          *
00881          * We could move the logic into a flag, but for now just check
00882          * explicitly.
00883          */
00884         if (packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
00885                 reply->msg_type = DHCPV6_ADVERTISE;
00886 
00887                 /*
00888                  * If:
00889                  * - this message type supports rapid commit (Solicit), and
00890                  * - the server is configured to supply a rapid commit, and
00891                  * - the client requests a rapid commit,
00892                  * Then we add a rapid commit option, and send Reply (instead
00893                  * of an Advertise).
00894                  */
00895                 oc = lookup_option(&dhcpv6_universe,
00896                                    *opt_state, D6O_RAPID_COMMIT);
00897                 if (oc != NULL) {
00898                         oc = lookup_option(&dhcpv6_universe,
00899                                            packet->options, D6O_RAPID_COMMIT);
00900                         if (oc != NULL) {
00901                                 /* Rapid-commit in action. */
00902                                 reply->msg_type = DHCPV6_REPLY;
00903                         } else {
00904                                 /* Don't want a rapid-commit in advertise. */
00905                                 delete_option(&dhcpv6_universe,
00906                                               *opt_state, D6O_RAPID_COMMIT);
00907                         }
00908                 }
00909         } else {
00910                 reply->msg_type = DHCPV6_REPLY;
00911                 /* Delete the rapid-commit from the sent options. */
00912                 oc = lookup_option(&dhcpv6_universe,
00913                                    *opt_state, D6O_RAPID_COMMIT);
00914                 if (oc != NULL) {
00915                         delete_option(&dhcpv6_universe,
00916                                       *opt_state, D6O_RAPID_COMMIT);
00917                 }
00918         }
00919 
00920         /* 
00921          * Use the client's transaction identifier for the reply.
00922          */
00923         memcpy(reply->transaction_id, packet->dhcpv6_transaction_id, 
00924                sizeof(reply->transaction_id));
00925 
00926         /* 
00927          * RFC 3315, section 18.2 says we need server identifier and
00928          * client identifier.
00929          *
00930          * If the server ID is defined via the configuration file, then
00931          * it will already be present in the option state at this point, 
00932          * so we don't need to set it.
00933          *
00934          * If we have a server ID passed in from the caller, 
00935          * use that, otherwise use the global DUID.
00936          */
00937         oc = lookup_option(&dhcpv6_universe, *opt_state, D6O_SERVERID);
00938         if (oc == NULL) {
00939                 if (server_id == NULL) {
00940                         server_id_data = server_duid.data;
00941                         server_id_len = server_duid.len;
00942                 } else {
00943                         server_id_data = server_id->data;
00944                         server_id_len = server_id->len;
00945                 }
00946                 if (!save_option_buffer(&dhcpv6_universe, *opt_state, 
00947                                         NULL, (unsigned char *)server_id_data,
00948                                         server_id_len, D6O_SERVERID, 0)) {
00949                                 log_error("start_reply: "
00950                                           "error saving server identifier.");
00951                                 return 0;
00952                 }
00953         }
00954 
00955         if (client_id->buffer != NULL) {
00956                 if (!save_option_buffer(&dhcpv6_universe, *opt_state, 
00957                                         client_id->buffer, 
00958                                         (unsigned char *)client_id->data, 
00959                                         client_id->len, 
00960                                         D6O_CLIENTID, 0)) {
00961                         log_error("start_reply: error saving "
00962                                   "client identifier.");
00963                         return 0;
00964                 }
00965         }
00966 
00967         /*
00968          * If the client accepts reconfiguration, let it know that we
00969          * will send them.
00970          *
00971          * Note: we don't actually do this yet, but DOCSIS requires we
00972          *       claim to.
00973          */
00974         oc = lookup_option(&dhcpv6_universe, packet->options,
00975                            D6O_RECONF_ACCEPT);
00976         if (oc != NULL) {
00977                 if (!save_option_buffer(&dhcpv6_universe, *opt_state,
00978                                         NULL, (unsigned char *)"", 0, 
00979                                         D6O_RECONF_ACCEPT, 0)) {
00980                         log_error("start_reply: "
00981                                   "error saving RECONF_ACCEPT option.");
00982                         option_state_dereference(opt_state, MDL);
00983                         return 0;
00984                 }
00985         }
00986 
00987         return 1;
00988 }
00989 
00990 /*
00991  * Try to get the IPv6 address the client asked for from the
00992  * pool.
00993  *
00994  * addr is the result (should be a pointer to NULL on entry)
00995  * pool is the pool to search in
00996  * requested_addr is the address the client wants
00997  */
00998 static isc_result_t
00999 try_client_v6_address(struct iasubopt **addr,
01000                       struct ipv6_pool *pool,
01001                       const struct data_string *requested_addr)
01002 {
01003         struct in6_addr tmp_addr;
01004         isc_result_t result;
01005 
01006         if (requested_addr->len < sizeof(tmp_addr)) {
01007                 return DHCP_R_INVALIDARG;
01008         }
01009         memcpy(&tmp_addr, requested_addr->data, sizeof(tmp_addr));
01010         if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
01011                 return ISC_R_FAILURE;
01012         }
01013 
01014         /*
01015          * The address is not covered by this (or possibly any) dynamic
01016          * range.
01017          */
01018         if (!ipv6_in_pool(&tmp_addr, pool)) {
01019                 return ISC_R_ADDRNOTAVAIL;
01020         }
01021 
01022         if (lease6_exists(pool, &tmp_addr)) {
01023                 return ISC_R_ADDRINUSE;
01024         }
01025 
01026         result = iasubopt_allocate(addr, MDL);
01027         if (result != ISC_R_SUCCESS) {
01028                 return result;
01029         }
01030         (*addr)->addr = tmp_addr;
01031         (*addr)->plen = 0;
01032 
01033         /* Default is soft binding for 2 minutes. */
01034         result = add_lease6(pool, *addr, cur_time + 120);
01035         if (result != ISC_R_SUCCESS) {
01036                 iasubopt_dereference(addr, MDL);
01037         }
01038         return result;
01039 }
01040 
01041 
01063 static isc_result_t 
01064 pick_v6_address(struct reply_state *reply)
01065 {
01066         struct ipv6_pool *p = NULL;
01067         struct ipv6_pond *pond;
01068         int i;
01069         int start_pool;
01070         unsigned int attempts;
01071         char tmp_buf[INET6_ADDRSTRLEN];
01072         struct iasubopt **addr = &reply->lease;
01073 
01074         /*
01075          * Do a quick walk through of the ponds and pools
01076          * to see if we have any NA address pools
01077          */
01078         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
01079                 if (pond->ipv6_pools == NULL)
01080                         continue;
01081 
01082                 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
01083                         if (p->pool_type == D6O_IA_NA)
01084                                 break;
01085                 }
01086                 if (p != NULL)
01087                         break;
01088         }
01089 
01090         /* If we get here and p is NULL we have no useful pools */
01091         if (p == NULL) {
01092                 log_debug("Unable to pick client address: "
01093                           "no IPv6 pools on this shared network");
01094                 return ISC_R_NORESOURCES;
01095         }
01096                 
01097         /*
01098          * We have at least one pool that could provide an address
01099          * Now we walk through the ponds and pools again and check
01100          * to see if the client is permitted and if an address is
01101          * available
01102          * 
01103          * Within a given pond we start looking at the last pool we
01104          * allocated from, unless it had a collision trying to allocate
01105          * an address. This will tend to move us into less-filled pools.
01106          */
01107 
01108         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
01109                 if (((pond->prohibit_list != NULL) &&
01110                      (permitted(reply->packet, pond->prohibit_list))) ||
01111                     ((pond->permit_list != NULL) &&
01112                      (!permitted(reply->packet, pond->permit_list))))
01113                         continue;
01114 
01115                 start_pool = pond->last_ipv6_pool;
01116                 i = start_pool;
01117                 do {
01118                         p = pond->ipv6_pools[i];
01119                         if ((p->pool_type == D6O_IA_NA) &&
01120                             (create_lease6(p, addr, &attempts,
01121                                            &reply->ia->iaid_duid,
01122                                            cur_time + 120) == ISC_R_SUCCESS)) {
01123                                 /*
01124                                  * Record the pool used (or next one if there 
01125                                  * was a collision).
01126                                  */
01127                                 if (attempts > 1) {
01128                                         i++;
01129                                         if (pond->ipv6_pools[i] == NULL) {
01130                                                 i = 0;
01131                                         }
01132                                 }
01133                                 pond->last_ipv6_pool = i;
01134 
01135                                 log_debug("Picking pool address %s",
01136                                           inet_ntop(AF_INET6, &((*addr)->addr),
01137                                                     tmp_buf, sizeof(tmp_buf)));
01138                                 return (ISC_R_SUCCESS);
01139                         }
01140 
01141                         i++;
01142                         if (pond->ipv6_pools[i] == NULL) {
01143                                 i = 0;
01144                         }
01145                 } while (i != start_pool);
01146         }
01147 
01148         /*
01149          * If we failed to pick an IPv6 address from any of the subnets.
01150          * Presumably that means we have no addresses for the client.
01151          */
01152         log_debug("Unable to pick client address: no addresses available");
01153         return ISC_R_NORESOURCES;
01154 }
01155 
01156 /*
01157  * Try to get the IPv6 prefix the client asked for from the
01158  * prefix pool.
01159  *
01160  * pref is the result (should be a pointer to NULL on entry)
01161  * pool is the prefix pool to search in
01162  * requested_pref is the address the client wants
01163  */
01164 static isc_result_t
01165 try_client_v6_prefix(struct iasubopt **pref,
01166                      struct ipv6_pool *pool,
01167                      const struct data_string *requested_pref)
01168 {
01169         u_int8_t tmp_plen;
01170         struct in6_addr tmp_pref;
01171         struct iaddr ia;
01172         isc_result_t result;
01173 
01174         if (requested_pref->len < sizeof(tmp_plen) + sizeof(tmp_pref)) {
01175                 return DHCP_R_INVALIDARG;
01176         }
01177         tmp_plen = (int) requested_pref->data[0];
01178         if ((tmp_plen < 3) || (tmp_plen > 128) ||
01179             ((int)tmp_plen != pool->units)) {
01180                 return ISC_R_FAILURE;
01181         }
01182         memcpy(&tmp_pref, requested_pref->data + 1, sizeof(tmp_pref));
01183         if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
01184                 return ISC_R_FAILURE;
01185         }
01186         ia.len = 16;
01187         memcpy(&ia.iabuf, &tmp_pref, 16);
01188         if (!is_cidr_mask_valid(&ia, (int) tmp_plen)) {
01189                 return ISC_R_FAILURE;
01190         }
01191 
01192         if (!ipv6_in_pool(&tmp_pref, pool)) {
01193                 return ISC_R_ADDRNOTAVAIL;
01194         }
01195 
01196         if (prefix6_exists(pool, &tmp_pref, tmp_plen)) {
01197                 return ISC_R_ADDRINUSE;
01198         }
01199 
01200         result = iasubopt_allocate(pref, MDL);
01201         if (result != ISC_R_SUCCESS) {
01202                 return result;
01203         }
01204         (*pref)->addr = tmp_pref;
01205         (*pref)->plen = tmp_plen;
01206 
01207         /* Default is soft binding for 2 minutes. */
01208         result = add_lease6(pool, *pref, cur_time + 120);
01209         if (result != ISC_R_SUCCESS) {
01210                 iasubopt_dereference(pref, MDL);
01211         }
01212         return result;
01213 }
01214 
01237 static isc_result_t 
01238 pick_v6_prefix(struct reply_state *reply)
01239 {
01240         struct ipv6_pool *p = NULL;
01241         struct ipv6_pond *pond;
01242         int i;
01243         unsigned int attempts;
01244         char tmp_buf[INET6_ADDRSTRLEN];
01245         struct iasubopt **pref = &reply->lease;
01246 
01247         /*
01248          * Do a quick walk through of the ponds and pools
01249          * to see if we have any prefix pools
01250          */
01251         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
01252                 if (pond->ipv6_pools == NULL)
01253                         continue;
01254 
01255                 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
01256                         if (p->pool_type == D6O_IA_PD)
01257                                 break;
01258                 }
01259                 if (p != NULL)
01260                         break;
01261         }
01262 
01263         /* If we get here and p is NULL we have no useful pools */
01264         if (p == NULL) {
01265                 log_debug("Unable to pick client prefix: "
01266                           "no IPv6 pools on this shared network");
01267                 return ISC_R_NORESOURCES;
01268         }
01269 
01270         /*
01271          * We have at least one pool that could provide a prefix
01272          * Now we walk through the ponds and pools again and check
01273          * to see if the client is permitted and if an prefix is
01274          * available
01275          * 
01276          */
01277 
01278         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
01279                 if (((pond->prohibit_list != NULL) &&
01280                      (permitted(reply->packet, pond->prohibit_list))) ||
01281                     ((pond->permit_list != NULL) &&
01282                      (!permitted(reply->packet, pond->permit_list))))
01283                         continue;
01284 
01285                 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
01286                         if (p->pool_type != D6O_IA_PD) {
01287                                 continue;
01288                         }
01289 
01290                         /*
01291                          * Try only pools with the requested prefix length if any.
01292                          */
01293                         if ((reply->preflen >= 0) && (p->units != reply->preflen)) {
01294                                 continue;
01295                         }
01296 
01297                         if (create_prefix6(p, pref, &attempts, &reply->ia->iaid_duid,
01298                                            cur_time + 120) == ISC_R_SUCCESS) {
01299                                 log_debug("Picking pool prefix %s/%u",
01300                                           inet_ntop(AF_INET6, &((*pref)->addr),
01301                                                     tmp_buf, sizeof(tmp_buf)),
01302                                           (unsigned) (*pref)->plen);
01303 
01304                                 return (ISC_R_SUCCESS);
01305                         }
01306                 }
01307         }
01308 
01309         /*
01310          * If we failed to pick an IPv6 prefix
01311          * Presumably that means we have no prefixes for the client.
01312          */
01313         log_debug("Unable to pick client prefix: no prefixes available");
01314         return ISC_R_NORESOURCES;
01315 }
01316 
01317 /*
01318  *! \file server/dhcpv6.c
01319  *
01320  * \brief construct a reply containing information about a client's lease
01321  *
01322  * lease_to_client() is called from several messages to construct a
01323  * reply that contains all that we know about the client's correct lease
01324  * (or projected lease).
01325  *
01326  * Solicit - "Soft" binding, ignore unknown addresses or bindings, just
01327  *           send what we "may" give them on a request.
01328  *
01329  * Request - "Hard" binding, but ignore supplied addresses (just provide what
01330  *           the client should really use).
01331  *
01332  * Renew   - "Hard" binding, but client-supplied addresses are 'real'.  Error
01333  * Rebind    out any "wrong" addresses the client sends.  This means we send
01334  *           an empty IA_NA with a status code of NoBinding or NotOnLink or
01335  *           possibly send the address with zeroed lifetimes.
01336  *
01337  * Information-Request - No binding.
01338  *
01339  * The basic structure is to traverse the client-supplied data first, and
01340  * validate and echo back any contents that can be.  If the client-supplied
01341  * data does not error out (on renew/rebind as above), but we did not send
01342  * any addresses, attempt to allocate one.
01343  *
01344  * At the end of the this function we call commit_leases_timed() to
01345  * fsync and rotate the file as necessary.  commit_leases_timed() will
01346  * check that we have written at least one lease to the file and that
01347  * some time has passed before doing any fsync or file rewrite so we
01348  * don't bother tracking if we did a write_ia during this function.
01349  */
01350 /* TODO: look at client hints for lease times */
01351 
01352 static void
01353 lease_to_client(struct data_string *reply_ret,
01354                 struct packet *packet, 
01355                 const struct data_string *client_id,
01356                 const struct data_string *server_id)
01357 {
01358         static struct reply_state reply;
01359         struct option_cache *oc;
01360         struct data_string packet_oro;
01361 #if defined (RFC3315_PRE_ERRATA_2010_08)
01362         isc_boolean_t no_resources_avail = ISC_FALSE;
01363 #endif
01364         int i;
01365 
01366         memset(&packet_oro, 0, sizeof(packet_oro));
01367 
01368         /* Locate the client.  */
01369         if (shared_network_from_packet6(&reply.shared,
01370                                         packet) != ISC_R_SUCCESS)
01371                 goto exit;
01372 
01373         /* 
01374          * Initialize the reply.
01375          */
01376         packet_reference(&reply.packet, packet, MDL);
01377         data_string_copy(&reply.client_id, client_id, MDL);
01378 
01379         if (!start_reply(packet, client_id, server_id, &reply.opt_state,
01380                          &reply.buf.reply))
01381                 goto exit;
01382 
01383         /* Set the write cursor to just past the reply header. */
01384         reply.cursor = REPLY_OPTIONS_INDEX;
01385 
01386         /*
01387          * Get the ORO from the packet, if any.
01388          */
01389         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ORO);
01390         if (oc != NULL) {
01391                 if (!evaluate_option_cache(&packet_oro, packet, 
01392                                            NULL, NULL, 
01393                                            packet->options, NULL,
01394                                            &global_scope, oc, MDL)) {
01395                         log_error("lease_to_client: error evaluating ORO.");
01396                         goto exit;
01397                 }
01398         }
01399 
01400         /* 
01401          * Find a host record that matches from the packet, if any, and is
01402          * valid for the shared network the client is on.
01403          */
01404         if (find_hosts_by_uid(&reply.host, client_id->data, client_id->len,
01405                               MDL)) {
01406                 packet->known = 1;
01407                 seek_shared_host(&reply.host, reply.shared);
01408         }
01409 
01410         if ((reply.host == NULL) &&
01411             find_hosts_by_option(&reply.host, packet, packet->options, MDL)) {
01412                 packet->known = 1;
01413                 seek_shared_host(&reply.host, reply.shared);
01414         }
01415 
01416         /*
01417          * Check for 'hardware' matches last, as some of the synthesis methods
01418          * are not considered to be as reliable.
01419          */
01420         if ((reply.host == NULL) &&
01421             find_hosts_by_duid_chaddr(&reply.host, client_id)) {
01422                 packet->known = 1;
01423                 seek_shared_host(&reply.host, reply.shared);
01424         }
01425 
01426         /* Process the client supplied IA's onto the reply buffer. */
01427         reply.ia_count = 0;
01428         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
01429 
01430         for (; oc != NULL ; oc = oc->next) {
01431                 isc_result_t status;
01432 
01433                 /* Start counting resources (addresses) offered. */
01434                 reply.client_resources = 0;
01435                 reply.resources_included = ISC_FALSE;
01436 
01437                 status = reply_process_ia_na(&reply, oc);
01438 
01439                 /*
01440                  * We continue to try other IA's whether we can address
01441                  * this one or not.  Any other result is an immediate fail.
01442                  */
01443                 if ((status != ISC_R_SUCCESS) &&
01444                     (status != ISC_R_NORESOURCES))
01445                         goto exit;
01446 
01447 #if defined (RFC3315_PRE_ERRATA_2010_08)
01448                 /*
01449                  * If any address cannot be given to any IA, then set the
01450                  * NoAddrsAvail status code.
01451                  */
01452                 if (reply.client_resources == 0)
01453                         no_resources_avail = ISC_TRUE;
01454 #endif
01455         }
01456         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
01457         for (; oc != NULL ; oc = oc->next) {
01458                 isc_result_t status;
01459 
01460                 /* Start counting resources (addresses) offered. */
01461                 reply.client_resources = 0;
01462                 reply.resources_included = ISC_FALSE;
01463 
01464                 status = reply_process_ia_ta(&reply, oc);
01465 
01466                 /*
01467                  * We continue to try other IA's whether we can address
01468                  * this one or not.  Any other result is an immediate fail.
01469                  */
01470                 if ((status != ISC_R_SUCCESS) &&
01471                     (status != ISC_R_NORESOURCES))
01472                         goto exit;
01473 
01474 #if defined (RFC3315_PRE_ERRATA_2010_08)
01475                 /*
01476                  * If any address cannot be given to any IA, then set the
01477                  * NoAddrsAvail status code.
01478                  */
01479                 if (reply.client_resources == 0)
01480                         no_resources_avail = ISC_TRUE;
01481 #endif
01482         }
01483 
01484         /* Same for IA_PD's. */
01485         reply.pd_count = 0;
01486         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
01487         for (; oc != NULL ; oc = oc->next) {
01488                 isc_result_t status;
01489 
01490                 /* Start counting resources (prefixes) offered. */
01491                 reply.client_resources = 0;
01492                 reply.resources_included = ISC_FALSE;
01493 
01494                 status = reply_process_ia_pd(&reply, oc);
01495 
01496                 /*
01497                  * We continue to try other IA_PD's whether we can address
01498                  * this one or not.  Any other result is an immediate fail.
01499                  */
01500                 if ((status != ISC_R_SUCCESS) &&
01501                     (status != ISC_R_NORESOURCES))
01502                         goto exit;
01503         }
01504 
01505         /*
01506          * Make no reply if we gave no resources and is not
01507          * for Information-Request.
01508          */
01509         if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
01510                 if (reply.packet->dhcpv6_msg_type !=
01511                                             DHCPV6_INFORMATION_REQUEST)
01512                         goto exit;
01513 
01514                 /*
01515                  * Because we only execute statements on a per-IA basis,
01516                  * we need to execute statements in any non-IA reply to
01517                  * source configuration.
01518                  */
01519                 execute_statements_in_scope(NULL, reply.packet, NULL, NULL,
01520                                             reply.packet->options,
01521                                             reply.opt_state, &global_scope,
01522                                             reply.shared->group, root_group,
01523                                             NULL);
01524 
01525                 /* Execute statements from class scopes. */
01526                 for (i = reply.packet->class_count; i > 0; i--) {
01527                         execute_statements_in_scope(NULL, reply.packet,
01528                                                     NULL, NULL,
01529                                                     reply.packet->options,
01530                                                     reply.opt_state,
01531                                                     &global_scope,
01532                                                     reply.packet->classes[i - 1]->group,
01533                                                     reply.shared->group, NULL);
01534                 }
01535 
01536                 /* Bring in any configuration from a host record. */
01537                 if (reply.host != NULL)
01538                         execute_statements_in_scope(NULL, reply.packet,
01539                                                     NULL, NULL,
01540                                                     reply.packet->options,
01541                                                     reply.opt_state,
01542                                                     &global_scope,
01543                                                     reply.host->group,
01544                                                     reply.shared->group, NULL);
01545         }
01546 
01547         /* reject unicast message, unless we set unicast option */
01548         if ((packet->unicast == ISC_TRUE) && !is_unicast_option_defined())
01549         /*
01550          * RFC3315 section 18.2.1 (Request):
01551          *
01552          * When the server receives a Request message via unicast from a client
01553          * to which the server has not sent a unicast option, the server
01554          * discards the Request message and responds with a Reply message
01555          * containing a Status Code option with the value UseMulticast, a Server
01556          * Identifier option containing the server's DUID, the Client Identifier
01557          * option from the client message, and no other options.
01558          *
01559          * Section 18.2.3 (Renew):
01560          *
01561          * When the server receives a Renew message via unicast from a client to
01562          * which the server has not sent a unicast option, the server discards
01563          * the Renew message and responds with a Reply message containing a
01564          * Status Code option with the value UseMulticast, a Server Identifier
01565          * option containing the server's DUID, the Client Identifier option
01566          * from the client message, and no other options.
01567          */
01568         {
01569                 /* Set the UseMulticast status code. */
01570                 if (!set_status_code(STATUS_UseMulticast,
01571                                         "Unicast not allowed by server.",
01572                                         reply.opt_state)) {
01573                         log_error("lease_to_client: Unable to set "
01574                                         "UseMulticast status code.");
01575                         goto exit;
01576                 }
01577 
01578                 /* Rewind the cursor to the start. */
01579                 reply.cursor = REPLY_OPTIONS_INDEX;
01580 
01581                 /*
01582                  * Produce an reply that includes only:
01583                  *
01584                  * Status code.
01585                  * Server DUID.
01586                  * Client DUID.
01587                  */
01588                 reply.cursor += store_options6((char *)reply.buf.data +
01589                                         reply.cursor,
01590                                         sizeof(reply.buf) -
01591                                         reply.cursor,
01592                                         reply.opt_state, reply.packet,
01593                                         required_opts_NAA,
01594                                         NULL);
01595         }
01596 
01597         /*
01598          * RFC3315 section 17.2.2 (Solicit):
01599          *
01600          * If the server will not assign any addresses to any IAs in a
01601          * subsequent Request from the client, the server MUST send an
01602          * Advertise message to the client that includes only a Status
01603          * Code option with code NoAddrsAvail and a status message for
01604          * the user, a Server Identifier option with the server's DUID,
01605          * and a Client Identifier option with the client's DUID.
01606          *
01607          * Section 18.2.1 (Request):
01608          *
01609          * If the server cannot assign any addresses to an IA in the
01610          * message from the client, the server MUST include the IA in
01611          * the Reply message with no addresses in the IA and a Status
01612          * Code option in the IA containing status code NoAddrsAvail.
01613          *
01614          * Section 18.1.8 (Client Behavior):
01615          *
01616          * Leave unchanged any information about addresses the client has
01617          * recorded in the IA but that were not included in the IA from
01618          * the server.
01619          * Sends a Renew/Rebind if the IA is not in the Reply message.
01620          */
01621 #if defined (RFC3315_PRE_ERRATA_2010_08)
01622         else if (no_resources_avail && (reply.ia_count != 0) &&
01623                  (reply.packet->dhcpv6_msg_type == DHCPV6_SOLICIT))
01624         {
01625                 /* Set the NoAddrsAvail status code. */
01626                 if (!set_status_code(STATUS_NoAddrsAvail,
01627                                      "No addresses available for this "
01628                                      "interface.", reply.opt_state)) {
01629                         log_error("lease_to_client: Unable to set "
01630                                   "NoAddrsAvail status code.");
01631                         goto exit;
01632                 }
01633 
01634                 /* Rewind the cursor to the start. */
01635                 reply.cursor = REPLY_OPTIONS_INDEX;
01636 
01637                 /*
01638                  * Produce an advertise that includes only:
01639                  *
01640                  * Status code.
01641                  * Server DUID.
01642                  * Client DUID.
01643                  */
01644                 reply.buf.reply.msg_type = DHCPV6_ADVERTISE;
01645                 reply.cursor += store_options6((char *)reply.buf.data +
01646                                                         reply.cursor,
01647                                                sizeof(reply.buf) -
01648                                                         reply.cursor,
01649                                                reply.opt_state, reply.packet,
01650                                                required_opts_NAA,
01651                                                NULL);
01652         } else {
01653                 /*
01654                  * Having stored the client's IA's, store any options that
01655                  * will fit in the remaining space.
01656                  */
01657                 reply.cursor += store_options6((char *)reply.buf.data +
01658                                                         reply.cursor,
01659                                                sizeof(reply.buf) -
01660                                                         reply.cursor,
01661                                                reply.opt_state, reply.packet,
01662                                                required_opts_solicit,
01663                                                &packet_oro);
01664         }
01665 #else /* defined (RFC3315_PRE_ERRATA_2010_08) */
01666         /*
01667          * Having stored the client's IA's, store any options that
01668          * will fit in the remaining space.
01669          */
01670         else 
01671         reply.cursor += store_options6((char *)reply.buf.data + reply.cursor,
01672                                        sizeof(reply.buf) - reply.cursor,
01673                                        reply.opt_state, reply.packet,
01674                                        required_opts_solicit,
01675                                        &packet_oro);
01676 #endif /* defined (RFC3315_PRE_ERRATA_2010_08) */
01677 
01678         /* Return our reply to the caller. */
01679         reply_ret->len = reply.cursor;
01680         reply_ret->buffer = NULL;
01681         if (!buffer_allocate(&reply_ret->buffer, reply.cursor, MDL)) {
01682                 log_fatal("No memory to store Reply.");
01683         }
01684         memcpy(reply_ret->buffer->data, reply.buf.data, reply.cursor);
01685         reply_ret->data = reply_ret->buffer->data;
01686 
01687         /* If appropriate commit and rotate the lease file */
01688         (void) commit_leases_timed();
01689 
01690       exit:
01691         /* Cleanup. */
01692         if (reply.shared != NULL)
01693                 shared_network_dereference(&reply.shared, MDL);
01694         if (reply.host != NULL)
01695                 host_dereference(&reply.host, MDL);
01696         if (reply.opt_state != NULL)
01697                 option_state_dereference(&reply.opt_state, MDL);
01698         if (reply.packet != NULL)
01699                 packet_dereference(&reply.packet, MDL);
01700         if (reply.client_id.data != NULL)
01701                 data_string_forget(&reply.client_id, MDL);
01702         if (packet_oro.buffer != NULL)
01703                 data_string_forget(&packet_oro, MDL);
01704         reply.renew = reply.rebind = reply.prefer = reply.valid = 0;
01705         reply.cursor = 0;
01706 }
01707 
01708 /* Process a client-supplied IA_NA.  This may append options to the tail of
01709  * the reply packet being built in the reply_state structure.
01710  */
01711 static isc_result_t
01712 reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
01713         isc_result_t status = ISC_R_SUCCESS;
01714         u_int32_t iaid;
01715         unsigned ia_cursor;
01716         struct option_state *packet_ia;
01717         struct option_cache *oc;
01718         struct data_string ia_data, data;
01719 
01720         /* Initialize values that will get cleaned up on return. */
01721         packet_ia = NULL;
01722         memset(&ia_data, 0, sizeof(ia_data));
01723         memset(&data, 0, sizeof(data));
01724         /* 
01725          * Note that find_client_address() may set reply->lease. 
01726          */
01727 
01728         /* Make sure there is at least room for the header. */
01729         if ((reply->cursor + IA_NA_OFFSET + 4) > sizeof(reply->buf)) {
01730                 log_error("reply_process_ia_na: Reply too long for IA.");
01731                 return ISC_R_NOSPACE;
01732         }
01733 
01734 
01735         /* Fetch the IA_NA contents. */
01736         if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
01737                                        ia, IA_NA_OFFSET)) {
01738                 log_error("reply_process_ia_na: error evaluating ia");
01739                 status = ISC_R_FAILURE;
01740                 goto cleanup;
01741         }
01742 
01743         /* Extract IA_NA header contents. */
01744         iaid = getULong(ia_data.data);
01745         reply->renew = getULong(ia_data.data + 4);
01746         reply->rebind = getULong(ia_data.data + 8);
01747 
01748         /* Create an IA_NA structure. */
01749         if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data, 
01750                         reply->client_id.len, MDL) != ISC_R_SUCCESS) {
01751                 log_error("reply_process_ia_na: no memory for ia.");
01752                 status = ISC_R_NOMEMORY;
01753                 goto cleanup;
01754         }
01755         reply->ia->ia_type = D6O_IA_NA;
01756 
01757         /* Cache pre-existing IA, if any. */
01758         ia_hash_lookup(&reply->old_ia, ia_na_active,
01759                        (unsigned char *)reply->ia->iaid_duid.data,
01760                        reply->ia->iaid_duid.len, MDL);
01761 
01762         /*
01763          * Create an option cache to carry the IA_NA option contents, and
01764          * execute any user-supplied values into it.
01765          */
01766         if (!option_state_allocate(&reply->reply_ia, MDL)) {
01767                 status = ISC_R_NOMEMORY;
01768                 goto cleanup;
01769         }
01770 
01771         /* Check & cache the fixed host record. */
01772         if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
01773                 struct iaddr tmp_addr;
01774 
01775                 if (!evaluate_option_cache(&reply->fixed, NULL, NULL, NULL,
01776                                            NULL, NULL, &global_scope,
01777                                            reply->host->fixed_addr, MDL)) {
01778                         log_error("reply_process_ia_na: unable to evaluate "
01779                                   "fixed address.");
01780                         status = ISC_R_FAILURE;
01781                         goto cleanup;
01782                 }
01783 
01784                 if (reply->fixed.len < 16) {
01785                         log_error("reply_process_ia_na: invalid fixed address.");
01786                         status = DHCP_R_INVALIDARG;
01787                         goto cleanup;
01788                 }
01789 
01790                 /* Find the static lease's subnet. */
01791                 tmp_addr.len = 16;
01792                 memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
01793 
01794                 if (find_grouped_subnet(&reply->subnet, reply->shared,
01795                                         tmp_addr, MDL) == 0)
01796                         log_fatal("Impossible condition at %s:%d.", MDL);
01797 
01798                 reply->static_lease = ISC_TRUE;
01799         } else
01800                 reply->static_lease = ISC_FALSE;
01801 
01802         /*
01803          * Save the cursor position at the start of the IA, so we can
01804          * set length and adjust t1/t2 values later.  We write a temporary
01805          * header out now just in case we decide to adjust the packet
01806          * within sub-process functions.
01807          */
01808         ia_cursor = reply->cursor;
01809 
01810         /* Initialize the IA_NA header.  First the code. */
01811         putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_NA);
01812         reply->cursor += 2;
01813 
01814         /* Then option length. */
01815         putUShort(reply->buf.data + reply->cursor, 0x0Cu);
01816         reply->cursor += 2;
01817 
01818         /* Then IA_NA header contents; IAID. */
01819         putULong(reply->buf.data + reply->cursor, iaid);
01820         reply->cursor += 4;
01821 
01822         /* We store the client's t1 for now, and may over-ride it later. */
01823         putULong(reply->buf.data + reply->cursor, reply->renew);
01824         reply->cursor += 4;
01825 
01826         /* We store the client's t2 for now, and may over-ride it later. */
01827         putULong(reply->buf.data + reply->cursor, reply->rebind);
01828         reply->cursor += 4;
01829 
01830         /* 
01831          * For each address in this IA_NA, decide what to do about it.
01832          *
01833          * Guidelines:
01834          *
01835          * The client leaves unchanged any information about addresses
01836          * it has recorded but are not included ("cancel/break" below).
01837          * A not included IA ("cleanup" below) could give a Renew/Rebind.
01838          */
01839         oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
01840         reply->valid = reply->prefer = 0xffffffff;
01841         reply->client_valid = reply->client_prefer = 0;
01842         for (; oc != NULL ; oc = oc->next) {
01843                 status = reply_process_addr(reply, oc);
01844 
01845                 /*
01846                  * Canceled means we did not allocate addresses to the
01847                  * client, but we're "done" with this IA - we set a status
01848                  * code.  So transmit this reply, e.g., move on to the next
01849                  * IA.
01850                  */
01851                 if (status == ISC_R_CANCELED)
01852                         break;
01853 
01854                 if ((status != ISC_R_SUCCESS) &&
01855                     (status != ISC_R_ADDRINUSE) &&
01856                     (status != ISC_R_ADDRNOTAVAIL))
01857                         goto cleanup;
01858         }
01859 
01860         reply->ia_count++;
01861 
01862         /*
01863          * If we fell through the above and never gave the client
01864          * an address, give it one now.
01865          */
01866         if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
01867                 status = find_client_address(reply);
01868 
01869                 if (status == ISC_R_NORESOURCES) {
01870                         switch (reply->packet->dhcpv6_msg_type) {
01871                               case DHCPV6_SOLICIT:
01872                                 /*
01873                                  * No address for any IA is handled
01874                                  * by the caller.
01875                                  */
01876                                 /* FALL THROUGH */
01877 
01878                               case DHCPV6_REQUEST:
01879                                 /* Section 18.2.1 (Request):
01880                                  *
01881                                  * If the server cannot assign any addresses to
01882                                  * an IA in the message from the client, the
01883                                  * server MUST include the IA in the Reply
01884                                  * message with no addresses in the IA and a
01885                                  * Status Code option in the IA containing
01886                                  * status code NoAddrsAvail.
01887                                  */
01888                                 option_state_dereference(&reply->reply_ia, MDL);
01889                                 if (!option_state_allocate(&reply->reply_ia,
01890                                                            MDL))
01891                                 {
01892                                         log_error("reply_process_ia_na: No "
01893                                                   "memory for option state "
01894                                                   "wipe.");
01895                                         status = ISC_R_NOMEMORY;
01896                                         goto cleanup;
01897                                 }
01898 
01899                                 if (!set_status_code(STATUS_NoAddrsAvail,
01900                                                      "No addresses available "
01901                                                      "for this interface.",
01902                                                       reply->reply_ia)) {
01903                                         log_error("reply_process_ia_na: Unable "
01904                                                   "to set NoAddrsAvail status "
01905                                                   "code.");
01906                                         status = ISC_R_FAILURE;
01907                                         goto cleanup;
01908                                 }
01909 
01910                                 status = ISC_R_SUCCESS;
01911                                 break;
01912 
01913                               default:
01914                                 /*
01915                                  * RFC 3315 does not tell us to emit a status
01916                                  * code in this condition, or anything else.
01917                                  *
01918                                  * If we included non-allocated addresses
01919                                  * (zeroed lifetimes) in an IA, then the client
01920                                  * will deconfigure them.
01921                                  *
01922                                  * So we want to include the IA even if we
01923                                  * can't give it a new address if it includes
01924                                  * zeroed lifetime addresses.
01925                                  *
01926                                  * We don't want to include the IA if we
01927                                  * provide zero addresses including zeroed
01928                                  * lifetimes.
01929                                  */
01930                                 if (reply->resources_included)
01931                                         status = ISC_R_SUCCESS;
01932                                 else
01933                                         goto cleanup;
01934                                 break;
01935                         }
01936                 }
01937 
01938                 if (status != ISC_R_SUCCESS)
01939                         goto cleanup;
01940         }
01941 
01942         reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
01943                                         sizeof(reply->buf) - reply->cursor,
01944                                         reply->reply_ia, reply->packet,
01945                                         required_opts_IA, NULL);
01946 
01947         /* Reset the length of this IA to match what was just written. */
01948         putUShort(reply->buf.data + ia_cursor + 2,
01949                   reply->cursor - (ia_cursor + 4));
01950 
01951         /*
01952          * T1/T2 time selection is kind of weird.  We actually use DHCP
01953          * (v4) scoped options as handy existing places where these might
01954          * be configured by an administrator.  A value of zero tells the
01955          * client it may choose its own renewal time.
01956          */
01957         reply->renew = 0;
01958         oc = lookup_option(&dhcp_universe, reply->opt_state,
01959                            DHO_DHCP_RENEWAL_TIME);
01960         if (oc != NULL) {
01961                 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
01962                                            reply->packet->options,
01963                                            reply->opt_state, &global_scope,
01964                                            oc, MDL) ||
01965                     (data.len != 4)) {
01966                         log_error("Invalid renewal time.");
01967                 } else {
01968                         reply->renew = getULong(data.data);
01969                 }
01970 
01971                 if (data.data != NULL)
01972                         data_string_forget(&data, MDL);
01973         }
01974         putULong(reply->buf.data + ia_cursor + 8, reply->renew);
01975 
01976         /* Now T2. */
01977         reply->rebind = 0;
01978         oc = lookup_option(&dhcp_universe, reply->opt_state,
01979                            DHO_DHCP_REBINDING_TIME);
01980         if (oc != NULL) {
01981                 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
01982                                            reply->packet->options,
01983                                            reply->opt_state, &global_scope,
01984                                            oc, MDL) ||
01985                     (data.len != 4)) {
01986                         log_error("Invalid rebinding time.");
01987                 } else {
01988                         reply->rebind = getULong(data.data);
01989                 }
01990 
01991                 if (data.data != NULL)
01992                         data_string_forget(&data, MDL);
01993         }
01994         putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
01995 
01996         /*
01997          * yes, goto's aren't the best but we also want to avoid extra
01998          * indents
01999          */
02000         if (status == ISC_R_CANCELED)
02001                 goto cleanup;
02002 
02003         /*
02004          * Handle static leases, we always log stuff and if it's
02005          * a hard binding we run any commit statements that we have
02006          */
02007         if (reply->static_lease) {
02008                 char tmp_addr[INET6_ADDRSTRLEN];
02009                 log_info("%s NA: address %s to client with duid %s iaid = %d "
02010                          "static",
02011                          dhcpv6_type_names[reply->buf.reply.msg_type],
02012                          inet_ntop(AF_INET6, reply->fixed.data, tmp_addr,
02013                                    sizeof(tmp_addr)),
02014                          print_hex_1(reply->client_id.len,
02015                                      reply->client_id.data, 60),
02016                          iaid);
02017 
02018                 if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
02019                     (reply->on_star.on_commit != NULL)) {
02020                         execute_statements(NULL, reply->packet, NULL, NULL, 
02021                                            reply->packet->options,
02022                                            reply->opt_state, NULL,
02023                                            reply->on_star.on_commit, NULL);
02024                         executable_statement_dereference
02025                                 (&reply->on_star.on_commit, MDL);
02026                 }
02027                 goto cleanup;
02028         }
02029 
02030         /*
02031          * If we have any addresses log what we are doing.
02032          */
02033         if (reply->ia->num_iasubopt != 0) {
02034                 struct iasubopt *tmp;
02035                 int i;
02036                 char tmp_addr[INET6_ADDRSTRLEN];
02037 
02038                 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
02039                         tmp = reply->ia->iasubopt[i];
02040 
02041                         log_info("%s NA: address %s to client with duid %s "
02042                                  "iaid = %d valid for %d seconds",
02043                                  dhcpv6_type_names[reply->buf.reply.msg_type],
02044                                  inet_ntop(AF_INET6, &tmp->addr,
02045                                            tmp_addr, sizeof(tmp_addr)),
02046                                  print_hex_1(reply->client_id.len,
02047                                              reply->client_id.data, 60),
02048                                  iaid, tmp->valid);
02049                 }
02050         }
02051 
02052         /*
02053          * If this is not a 'soft' binding, consume the new changes into
02054          * the database (if any have been attached to the ia_na).
02055          *
02056          * Loop through the assigned dynamic addresses, referencing the
02057          * leases onto this IA_NA rather than any old ones, and updating
02058          * pool timers for each (if any).
02059          */
02060 
02061         if ((reply->ia->num_iasubopt != 0) &&
02062             (reply->buf.reply.msg_type == DHCPV6_REPLY)) {
02063                 struct iasubopt *tmp;
02064                 struct data_string *ia_id;
02065                 int i;
02066 
02067                 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
02068                         tmp = reply->ia->iasubopt[i];
02069 
02070                         if (tmp->ia != NULL)
02071                                 ia_dereference(&tmp->ia, MDL);
02072                         ia_reference(&tmp->ia, reply->ia, MDL);
02073 
02074                         /* Commit 'hard' bindings. */
02075                         renew_lease6(tmp->ipv6_pool, tmp);
02076                         schedule_lease_timeout(tmp->ipv6_pool);
02077 
02078                         /* If we have anything to do on commit do it now */
02079                         if (tmp->on_star.on_commit != NULL) {
02080                                 execute_statements(NULL, reply->packet,
02081                                                    NULL, NULL, 
02082                                                    reply->packet->options,
02083                                                    reply->opt_state,
02084                                                    &tmp->scope,
02085                                                    tmp->on_star.on_commit,
02086                                                    &tmp->on_star);
02087                                 executable_statement_dereference
02088                                         (&tmp->on_star.on_commit, MDL);
02089                         }
02090 
02091 #if defined (NSUPDATE)
02092                         /*
02093                          * Perform ddns updates.
02094                          */
02095                         oc = lookup_option(&server_universe, reply->opt_state,
02096                                            SV_DDNS_UPDATES);
02097                         if ((oc == NULL) ||
02098                             evaluate_boolean_option_cache(NULL, reply->packet,
02099                                                           NULL, NULL,
02100                                                         reply->packet->options,
02101                                                           reply->opt_state,
02102                                                           &tmp->scope,
02103                                                           oc, MDL)) {
02104                                 ddns_updates(reply->packet, NULL, NULL,
02105                                              tmp, NULL, reply->opt_state);
02106                         }
02107 #endif
02108                 }
02109 
02110                 /* Remove any old ia from the hash. */
02111                 if (reply->old_ia != NULL) {
02112                         ia_id = &reply->old_ia->iaid_duid;
02113                         ia_hash_delete(ia_na_active,
02114                                        (unsigned char *)ia_id->data,
02115                                        ia_id->len, MDL);
02116                         ia_dereference(&reply->old_ia, MDL);
02117                 }
02118 
02119                 /* Put new ia into the hash. */
02120                 reply->ia->cltt = cur_time;
02121                 ia_id = &reply->ia->iaid_duid;
02122                 ia_hash_add(ia_na_active, (unsigned char *)ia_id->data,
02123                             ia_id->len, reply->ia, MDL);
02124 
02125                 write_ia(reply->ia);
02126         }
02127 
02128       cleanup:
02129         if (packet_ia != NULL)
02130                 option_state_dereference(&packet_ia, MDL);
02131         if (reply->reply_ia != NULL)
02132                 option_state_dereference(&reply->reply_ia, MDL);
02133         if (ia_data.data != NULL)
02134                 data_string_forget(&ia_data, MDL);
02135         if (data.data != NULL)
02136                 data_string_forget(&data, MDL);
02137         if (reply->ia != NULL)
02138                 ia_dereference(&reply->ia, MDL);
02139         if (reply->old_ia != NULL)
02140                 ia_dereference(&reply->old_ia, MDL);
02141         if (reply->lease != NULL)
02142                 iasubopt_dereference(&reply->lease, MDL);
02143         if (reply->fixed.data != NULL)
02144                 data_string_forget(&reply->fixed, MDL);
02145         if (reply->subnet != NULL)
02146                 subnet_dereference(&reply->subnet, MDL);
02147         if (reply->on_star.on_expiry != NULL)
02148                 executable_statement_dereference
02149                         (&reply->on_star.on_expiry, MDL);
02150         if (reply->on_star.on_release != NULL)
02151                 executable_statement_dereference
02152                         (&reply->on_star.on_release, MDL);
02153 
02154         /*
02155          * ISC_R_CANCELED is a status code used by the addr processing to
02156          * indicate we're replying with a status code.  This is still a
02157          * success at higher layers.
02158          */
02159         return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
02160 }
02161 
02162 /*
02163  * Process an IAADDR within a given IA_xA, storing any IAADDR reply contents
02164  * into the reply's current ia-scoped option cache.  Returns ISC_R_CANCELED
02165  * in the event we are replying with a status code and do not wish to process
02166  * more IAADDRs within this IA.
02167  */
02168 static isc_result_t
02169 reply_process_addr(struct reply_state *reply, struct option_cache *addr) {
02170         u_int32_t pref_life, valid_life;
02171         struct binding_scope **scope;
02172         struct group *group;
02173         struct subnet *subnet;
02174         struct iaddr tmp_addr;
02175         struct option_cache *oc;
02176         struct data_string iaaddr, data;
02177         isc_result_t status = ISC_R_SUCCESS;
02178 
02179         /* Initializes values that will be cleaned up. */
02180         memset(&iaaddr, 0, sizeof(iaaddr));
02181         memset(&data, 0, sizeof(data));
02182         /* Note that reply->lease may be set by address_is_owned() */
02183 
02184         /*
02185          * There is no point trying to process an incoming address if there
02186          * is no room for an outgoing address.
02187          */
02188         if ((reply->cursor + 28) > sizeof(reply->buf)) {
02189                 log_error("reply_process_addr: Out of room for address.");
02190                 return ISC_R_NOSPACE;
02191         }
02192 
02193         /* Extract this IAADDR option. */
02194         if (!evaluate_option_cache(&iaaddr, reply->packet, NULL, NULL, 
02195                                    reply->packet->options, NULL, &global_scope,
02196                                    addr, MDL) ||
02197             (iaaddr.len < IAADDR_OFFSET)) {
02198                 log_error("reply_process_addr: error evaluating IAADDR.");
02199                 status = ISC_R_FAILURE;
02200                 goto cleanup;
02201         }
02202 
02203         /* The first 16 bytes are the IPv6 address. */
02204         pref_life = getULong(iaaddr.data + 16);
02205         valid_life = getULong(iaaddr.data + 20);
02206 
02207         if ((reply->client_valid == 0) ||
02208             (reply->client_valid > valid_life))
02209                 reply->client_valid = valid_life;
02210 
02211         if ((reply->client_prefer == 0) ||
02212             (reply->client_prefer > pref_life))
02213                 reply->client_prefer = pref_life;
02214 
02215         /* 
02216          * Clients may choose to send :: as an address, with the idea to give
02217          * hints about preferred-lifetime or valid-lifetime.
02218          */
02219         tmp_addr.len = 16;
02220         memset(tmp_addr.iabuf, 0, 16);
02221         if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
02222                 /* Status remains success; we just ignore this one. */
02223                 goto cleanup;
02224         }
02225 
02226         /* tmp_addr len remains 16 */
02227         memcpy(tmp_addr.iabuf, iaaddr.data, 16);
02228 
02229         /*
02230          * Verify that this address is on the client's network.
02231          */
02232         for (subnet = reply->shared->subnets ; subnet != NULL ;
02233              subnet = subnet->next_sibling) {
02234                 if (addr_eq(subnet_number(tmp_addr, subnet->netmask),
02235                             subnet->net))
02236                         break;
02237         }
02238 
02239         /* Address not found on shared network. */
02240         if (subnet == NULL) {
02241                 /* Ignore this address on 'soft' bindings. */
02242                 if (reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) {
02243                         /* disable rapid commit */
02244                         reply->buf.reply.msg_type = DHCPV6_ADVERTISE;
02245                         delete_option(&dhcpv6_universe,
02246                                       reply->opt_state,
02247                                       D6O_RAPID_COMMIT);
02248                         /* status remains success */
02249                         goto cleanup;
02250                 }
02251 
02252                 /*
02253                  * RFC3315 section 18.2.1:
02254                  *
02255                  * If the server finds that the prefix on one or more IP
02256                  * addresses in any IA in the message from the client is not
02257                  * appropriate for the link to which the client is connected,
02258                  * the server MUST return the IA to the client with a Status
02259                  * Code option with the value NotOnLink.
02260                  */
02261                 if (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) {
02262                         /* Rewind the IA_NA to empty. */
02263                         option_state_dereference(&reply->reply_ia, MDL);
02264                         if (!option_state_allocate(&reply->reply_ia, MDL)) {
02265                                 log_error("reply_process_addr: No memory for "
02266                                           "option state wipe.");
02267                                 status = ISC_R_NOMEMORY;
02268                                 goto cleanup;
02269                         }
02270 
02271                         /* Append a NotOnLink status code. */
02272                         if (!set_status_code(STATUS_NotOnLink,
02273                                              "Address not for use on this "
02274                                              "link.", reply->reply_ia)) {
02275                                 log_error("reply_process_addr: Failure "
02276                                           "setting status code.");
02277                                 status = ISC_R_FAILURE;
02278                                 goto cleanup;
02279                         }
02280 
02281                         /* Fin (no more IAADDRs). */
02282                         status = ISC_R_CANCELED;
02283                         goto cleanup;
02284                 }
02285 
02286                 /*
02287                  * RFC3315 sections 18.2.3 and 18.2.4 have identical language:
02288                  *
02289                  * If the server finds that any of the addresses are not
02290                  * appropriate for the link to which the client is attached,
02291                  * the server returns the address to the client with lifetimes
02292                  * of 0.
02293                  */
02294                 if ((reply->packet->dhcpv6_msg_type != DHCPV6_RENEW) &&
02295                     (reply->packet->dhcpv6_msg_type != DHCPV6_REBIND)) {
02296                         log_error("It is impossible to lease a client that is "
02297                                   "not sending a solicit, request, renew, or "
02298                                   "rebind.");
02299                         status = ISC_R_FAILURE;
02300                         goto cleanup;
02301                 }
02302 
02303                 reply->send_prefer = reply->send_valid = 0;
02304                 goto send_addr;
02305         }
02306 
02307         /* Verify the address belongs to the client. */
02308         if (!address_is_owned(reply, &tmp_addr)) {
02309                 /*
02310                  * For solicit and request, any addresses included are
02311                  * 'requested' addresses.  For rebind, we actually have
02312                  * no direction on what to do from 3315 section 18.2.4!
02313                  * So I think the best bet is to try and give it out, and if
02314                  * we can't, zero lifetimes.
02315                  */
02316                 if ((reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) ||
02317                     (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) ||
02318                     (reply->packet->dhcpv6_msg_type == DHCPV6_REBIND)) {
02319                         status = reply_process_try_addr(reply, &tmp_addr);
02320 
02321                         /*
02322                          * If the address is in use, or isn't in any dynamic
02323                          * range, continue as normal.  If any other error was
02324                          * found, error out.
02325                          */
02326                         if ((status != ISC_R_SUCCESS) && 
02327                             (status != ISC_R_ADDRINUSE) &&
02328                             (status != ISC_R_ADDRNOTAVAIL))
02329                                 goto cleanup;
02330 
02331                         /*
02332                          * If we didn't honor this lease, for solicit and
02333                          * request we simply omit it from our answer.  For
02334                          * rebind, we send it with zeroed lifetimes.
02335                          */
02336                         if (reply->lease == NULL) {
02337                                 if (reply->packet->dhcpv6_msg_type ==
02338                                                         DHCPV6_REBIND) {
02339                                         reply->send_prefer = 0;
02340                                         reply->send_valid = 0;
02341                                         goto send_addr;
02342                                 }
02343 
02344                                 /* status remains success - ignore */
02345                                 goto cleanup;
02346                         }
02347                 /*
02348                  * RFC3315 section 18.2.3:
02349                  *
02350                  * If the server cannot find a client entry for the IA the
02351                  * server returns the IA containing no addresses with a Status
02352                  * Code option set to NoBinding in the Reply message.
02353                  *
02354                  * On mismatch we (ab)use this pretending we have not the IA
02355                  * as soon as we have not an address.
02356                  */
02357                 } else if (reply->packet->dhcpv6_msg_type == DHCPV6_RENEW) {
02358                         /* Rewind the IA_NA to empty. */
02359                         option_state_dereference(&reply->reply_ia, MDL);
02360                         if (!option_state_allocate(&reply->reply_ia, MDL)) {
02361                                 log_error("reply_process_addr: No memory for "
02362                                           "option state wipe.");
02363                                 status = ISC_R_NOMEMORY;
02364                                 goto cleanup;
02365                         }
02366 
02367                         /* Append a NoBinding status code.  */
02368                         if (!set_status_code(STATUS_NoBinding,
02369                                              "Address not bound to this "
02370                                              "interface.", reply->reply_ia)) {
02371                                 log_error("reply_process_addr: Unable to "
02372                                           "attach status code.");
02373                                 status = ISC_R_FAILURE;
02374                                 goto cleanup;
02375                         }
02376 
02377                         /* Fin (no more IAADDRs). */
02378                         status = ISC_R_CANCELED;
02379                         goto cleanup;
02380                 } else {
02381                         log_error("It is impossible to lease a client that is "
02382                                   "not sending a solicit, request, renew, or "
02383                                   "rebind message.");
02384                         status = ISC_R_FAILURE;
02385                         goto cleanup;
02386                 }
02387         }
02388 
02389         if (reply->static_lease) {
02390                 if (reply->host == NULL)
02391                         log_fatal("Impossible condition at %s:%d.", MDL);
02392 
02393                 scope = &global_scope;
02394                 group = reply->subnet->group;
02395         } else {
02396                 if (reply->lease == NULL)
02397                         log_fatal("Impossible condition at %s:%d.", MDL);
02398 
02399                 scope = &reply->lease->scope;
02400                 group = reply->lease->ipv6_pool->ipv6_pond->group;
02401         }
02402 
02403         /*
02404          * If client_resources is nonzero, then the reply_process_is_addressed
02405          * function has executed configuration state into the reply option
02406          * cache.  We will use that valid cache to derive configuration for
02407          * whether or not to engage in additional addresses, and similar.
02408          */
02409         if (reply->client_resources != 0) {
02410                 unsigned limit = 1;
02411 
02412                 /*
02413                  * Does this client have "enough" addresses already?  Default
02414                  * to one.  Everybody gets one, and one should be enough for
02415                  * anybody.
02416                  */
02417                 oc = lookup_option(&server_universe, reply->opt_state,
02418                                    SV_LIMIT_ADDRS_PER_IA);
02419                 if (oc != NULL) {
02420                         if (!evaluate_option_cache(&data, reply->packet,
02421                                                    NULL, NULL,
02422                                                    reply->packet->options,
02423                                                    reply->opt_state,
02424                                                    scope, oc, MDL) ||
02425                             (data.len != 4)) {
02426                                 log_error("reply_process_addr: unable to "
02427                                           "evaluate addrs-per-ia value.");
02428                                 status = ISC_R_FAILURE;
02429                                 goto cleanup;
02430                         }
02431 
02432                         limit = getULong(data.data);
02433                         data_string_forget(&data, MDL);
02434                 }
02435 
02436                 /*
02437                  * If we wish to limit the client to a certain number of
02438                  * addresses, then omit the address from the reply.
02439                  */
02440                 if (reply->client_resources >= limit)
02441                         goto cleanup;
02442         }
02443 
02444         status = reply_process_is_addressed(reply, scope, group);
02445         if (status != ISC_R_SUCCESS)
02446                 goto cleanup;
02447 
02448       send_addr:
02449         status = reply_process_send_addr(reply, &tmp_addr);
02450 
02451       cleanup:
02452         if (iaaddr.data != NULL)
02453                 data_string_forget(&iaaddr, MDL);
02454         if (data.data != NULL)
02455                 data_string_forget(&data, MDL);
02456         if (reply->lease != NULL)
02457                 iasubopt_dereference(&reply->lease, MDL);
02458 
02459         return status;
02460 }
02461 
02462 /*
02463  * Verify the address belongs to the client.  If we've got a host
02464  * record with a fixed address, it has to be the assigned address
02465  * (fault out all else).  Otherwise it's a dynamic address, so lookup
02466  * that address and make sure it belongs to this DUID:IAID pair.
02467  */
02468 static isc_boolean_t
02469 address_is_owned(struct reply_state *reply, struct iaddr *addr) {
02470         int i;
02471         struct ipv6_pond *pond;
02472 
02473         /*
02474          * This faults out addresses that don't match fixed addresses.
02475          */
02476         if (reply->static_lease) {
02477                 if (reply->fixed.data == NULL)
02478                         log_fatal("Impossible condition at %s:%d.", MDL);
02479 
02480                 if (memcmp(addr->iabuf, reply->fixed.data, 16) == 0)
02481                         return (ISC_TRUE);
02482 
02483                 return (ISC_FALSE);
02484         }
02485 
02486         if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
02487                 return (ISC_FALSE);
02488 
02489         for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
02490                 struct iasubopt *tmp;
02491 
02492                 tmp = reply->old_ia->iasubopt[i];
02493 
02494                 if (memcmp(addr->iabuf, &tmp->addr, 16) == 0) {
02495                         if (lease6_usable(tmp) == ISC_FALSE) {
02496                                 return (ISC_FALSE);
02497                         }
02498 
02499                         pond = tmp->ipv6_pool->ipv6_pond;
02500                         if (((pond->prohibit_list != NULL) &&
02501                              (permitted(reply->packet, pond->prohibit_list))) ||
02502                             ((pond->permit_list != NULL) &&
02503                              (!permitted(reply->packet, pond->permit_list))))
02504                                 return (ISC_FALSE);
02505 
02506                         iasubopt_reference(&reply->lease, tmp, MDL);
02507 
02508                         return (ISC_TRUE);
02509                 }
02510         }
02511 
02512         return (ISC_FALSE);
02513 }
02514 
02515 /* Process a client-supplied IA_TA.  This may append options to the tail of
02516  * the reply packet being built in the reply_state structure.
02517  */
02518 static isc_result_t
02519 reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
02520         isc_result_t status = ISC_R_SUCCESS;
02521         u_int32_t iaid;
02522         unsigned ia_cursor;
02523         struct option_state *packet_ia;
02524         struct option_cache *oc;
02525         struct data_string ia_data, data;
02526         struct data_string iaaddr;
02527         u_int32_t pref_life, valid_life;
02528         struct iaddr tmp_addr;
02529 
02530         /* Initialize values that will get cleaned up on return. */
02531         packet_ia = NULL;
02532         memset(&ia_data, 0, sizeof(ia_data));
02533         memset(&data, 0, sizeof(data));
02534         memset(&iaaddr, 0, sizeof(iaaddr));
02535 
02536         /* Make sure there is at least room for the header. */
02537         if ((reply->cursor + IA_TA_OFFSET + 4) > sizeof(reply->buf)) {
02538                 log_error("reply_process_ia_ta: Reply too long for IA.");
02539                 return ISC_R_NOSPACE;
02540         }
02541 
02542 
02543         /* Fetch the IA_TA contents. */
02544         if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
02545                                        ia, IA_TA_OFFSET)) {
02546                 log_error("reply_process_ia_ta: error evaluating ia");
02547                 status = ISC_R_FAILURE;
02548                 goto cleanup;
02549         }
02550 
02551         /* Extract IA_TA header contents. */
02552         iaid = getULong(ia_data.data);
02553 
02554         /* Create an IA_TA structure. */
02555         if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data,
02556                         reply->client_id.len, MDL) != ISC_R_SUCCESS) {
02557                 log_error("reply_process_ia_ta: no memory for ia.");
02558                 status = ISC_R_NOMEMORY;
02559                 goto cleanup;
02560         }
02561         reply->ia->ia_type = D6O_IA_TA;
02562 
02563         /* Cache pre-existing IA, if any. */
02564         ia_hash_lookup(&reply->old_ia, ia_ta_active,
02565                        (unsigned char *)reply->ia->iaid_duid.data,
02566                        reply->ia->iaid_duid.len, MDL);
02567 
02568         /*
02569          * Create an option cache to carry the IA_TA option contents, and
02570          * execute any user-supplied values into it.
02571          */
02572         if (!option_state_allocate(&reply->reply_ia, MDL)) {
02573                 status = ISC_R_NOMEMORY;
02574                 goto cleanup;
02575         }
02576 
02577         /*
02578          * Temporary leases are dynamic by definition.
02579          */
02580         reply->static_lease = ISC_FALSE;
02581 
02582         /*
02583          * Save the cursor position at the start of the IA, so we can
02584          * set length later.  We write a temporary
02585          * header out now just in case we decide to adjust the packet
02586          * within sub-process functions.
02587          */
02588         ia_cursor = reply->cursor;
02589 
02590         /* Initialize the IA_TA header.  First the code. */
02591         putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_TA);
02592         reply->cursor += 2;
02593 
02594         /* Then option length. */
02595         putUShort(reply->buf.data + reply->cursor, 0x04u);
02596         reply->cursor += 2;
02597 
02598         /* Then IA_TA header contents; IAID. */
02599         putULong(reply->buf.data + reply->cursor, iaid);
02600         reply->cursor += 4;
02601 
02602         /* 
02603          * Deal with an IAADDR for lifetimes.
02604          * For all or none, process IAADDRs as hints.
02605          */
02606         reply->valid = reply->prefer = 0xffffffff;
02607         reply->client_valid = reply->client_prefer = 0;
02608         oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAADDR);
02609         for (; oc != NULL; oc = oc->next) {
02610                 memset(&iaaddr, 0, sizeof(iaaddr));
02611                 if (!evaluate_option_cache(&iaaddr, reply->packet,
02612                                            NULL, NULL,
02613                                            reply->packet->options, NULL,
02614                                            &global_scope, oc, MDL) ||
02615                     (iaaddr.len < IAADDR_OFFSET)) {
02616                         log_error("reply_process_ia_ta: error "
02617                                   "evaluating IAADDR.");
02618                         status = ISC_R_FAILURE;
02619                         goto cleanup;
02620                 }
02621                 /* The first 16 bytes are the IPv6 address. */
02622                 pref_life = getULong(iaaddr.data + 16);
02623                 valid_life = getULong(iaaddr.data + 20);
02624 
02625                 if ((reply->client_valid == 0) ||
02626                     (reply->client_valid > valid_life))
02627                         reply->client_valid = valid_life;
02628 
02629                 if ((reply->client_prefer == 0) ||
02630                     (reply->client_prefer > pref_life))
02631                         reply->client_prefer = pref_life;
02632 
02633                 /* Nothing more if something has failed. */
02634                 if (status == ISC_R_CANCELED)
02635                         continue;
02636 
02637                 tmp_addr.len = 16;
02638                 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
02639                 if (!temporary_is_available(reply, &tmp_addr))
02640                         goto bad_temp;
02641                 status = reply_process_is_addressed(reply,
02642                                                     &reply->lease->scope,
02643                                                     reply->lease->ipv6_pool->ipv6_pond->group);
02644                 if (status != ISC_R_SUCCESS)
02645                         goto bad_temp;
02646                 status = reply_process_send_addr(reply, &tmp_addr);
02647                 if (status != ISC_R_SUCCESS)
02648                         goto bad_temp;
02649                 if (reply->lease != NULL)
02650                         iasubopt_dereference(&reply->lease, MDL);
02651                 continue;
02652 
02653         bad_temp:
02654                 /* Rewind the IA_TA to empty. */
02655                 option_state_dereference(&reply->reply_ia, MDL);
02656                 if (!option_state_allocate(&reply->reply_ia, MDL)) {
02657                         status = ISC_R_NOMEMORY;
02658                         goto cleanup;
02659                 }
02660                 status = ISC_R_CANCELED;
02661                 reply->client_resources = 0;
02662                 reply->resources_included = ISC_FALSE;
02663                 if (reply->lease != NULL)
02664                         iasubopt_dereference(&reply->lease, MDL);
02665         }
02666         reply->ia_count++;
02667 
02668         /*
02669          * Give the client temporary addresses.
02670          */
02671         if (reply->client_resources != 0)
02672                 goto store;
02673         status = find_client_temporaries(reply);
02674         if (status == ISC_R_NORESOURCES) {
02675                 switch (reply->packet->dhcpv6_msg_type) {
02676                       case DHCPV6_SOLICIT:
02677                         /*
02678                          * No address for any IA is handled
02679                          * by the caller.
02680                          */
02681                         /* FALL THROUGH */
02682 
02683                       case DHCPV6_REQUEST:
02684                         /* Section 18.2.1 (Request):
02685                          *
02686                          * If the server cannot assign any addresses to
02687                          * an IA in the message from the client, the
02688                          * server MUST include the IA in the Reply
02689                          * message with no addresses in the IA and a
02690                          * Status Code option in the IA containing
02691                          * status code NoAddrsAvail.
02692                          */
02693                         option_state_dereference(&reply->reply_ia, MDL);
02694                         if (!option_state_allocate(&reply->reply_ia,  MDL)) {
02695                                 log_error("reply_process_ia_ta: No "
02696                                           "memory for option state wipe.");
02697                                 status = ISC_R_NOMEMORY;
02698                                 goto cleanup;
02699                         }
02700 
02701                         if (!set_status_code(STATUS_NoAddrsAvail,
02702                                              "No addresses available "
02703                                              "for this interface.",
02704                                               reply->reply_ia)) {
02705                                 log_error("reply_process_ia_ta: Unable "
02706                                           "to set NoAddrsAvail status code.");
02707                                 status = ISC_R_FAILURE;
02708                                 goto cleanup;
02709                         }
02710 
02711                         status = ISC_R_SUCCESS;
02712                         break;
02713 
02714                       default:
02715                         /*
02716                          * We don't want to include the IA if we
02717                          * provide zero addresses including zeroed
02718                          * lifetimes.
02719                          */
02720                         if (reply->resources_included)
02721                                 status = ISC_R_SUCCESS;
02722                         else
02723                                 goto cleanup;
02724                         break;
02725                 }
02726         } else if (status != ISC_R_SUCCESS)
02727                 goto cleanup;
02728 
02729       store:
02730         reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
02731                                         sizeof(reply->buf) - reply->cursor,
02732                                         reply->reply_ia, reply->packet,
02733                                         required_opts_IA, NULL);
02734 
02735         /* Reset the length of this IA to match what was just written. */
02736         putUShort(reply->buf.data + ia_cursor + 2,
02737                   reply->cursor - (ia_cursor + 4));
02738 
02739         /*
02740          * yes, goto's aren't the best but we also want to avoid extra
02741          * indents
02742          */
02743         if (status == ISC_R_CANCELED)
02744                 goto cleanup;
02745 
02746         /*
02747          * If we have any addresses log what we are doing.
02748          */
02749         if (reply->ia->num_iasubopt != 0) {
02750                 struct iasubopt *tmp;
02751                 int i;
02752                 char tmp_addr[INET6_ADDRSTRLEN];
02753 
02754                 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
02755                         tmp = reply->ia->iasubopt[i];
02756 
02757                         log_info("%s TA: address %s to client with duid %s "
02758                                  "iaid = %d valid for %d seconds",
02759                                  dhcpv6_type_names[reply->buf.reply.msg_type],
02760                                  inet_ntop(AF_INET6, &tmp->addr,
02761                                            tmp_addr, sizeof(tmp_addr)),
02762                                  print_hex_1(reply->client_id.len,
02763                                              reply->client_id.data, 60),
02764                                  iaid,
02765                                  tmp->valid);
02766                 }
02767         }
02768 
02769         /*
02770          * For hard bindings we consume the new changes into
02771          * the database (if any have been attached to the ia_ta).
02772          *
02773          * Loop through the assigned dynamic addresses, referencing the
02774          * leases onto this IA_TA rather than any old ones, and updating
02775          * pool timers for each (if any).
02776          */
02777         if ((reply->ia->num_iasubopt != 0) &&
02778             (reply->buf.reply.msg_type == DHCPV6_REPLY)) {
02779                 struct iasubopt *tmp;
02780                 struct data_string *ia_id;
02781                 int i;
02782 
02783                 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
02784                         tmp = reply->ia->iasubopt[i];
02785 
02786                         if (tmp->ia != NULL)
02787                                 ia_dereference(&tmp->ia, MDL);
02788                         ia_reference(&tmp->ia, reply->ia, MDL);
02789 
02790                         /* Commit 'hard' bindings. */
02791                         renew_lease6(tmp->ipv6_pool, tmp);
02792                         schedule_lease_timeout(tmp->ipv6_pool);
02793 
02794                         /* If we have anything to do on commit do it now */
02795                         if (tmp->on_star.on_commit != NULL) {
02796                                 execute_statements(NULL, reply->packet,
02797                                                    NULL, NULL, 
02798                                                    reply->packet->options,
02799                                                    reply->opt_state,
02800                                                    &tmp->scope,
02801                                                    tmp->on_star.on_commit,
02802                                                    &tmp->on_star);
02803                                 executable_statement_dereference
02804                                         (&tmp->on_star.on_commit, MDL);
02805                         }
02806 
02807 #if defined (NSUPDATE)
02808                         /*
02809                          * Perform ddns updates.
02810                          */
02811                         oc = lookup_option(&server_universe, reply->opt_state,
02812                                            SV_DDNS_UPDATES);
02813                         if ((oc == NULL) ||
02814                             evaluate_boolean_option_cache(NULL, reply->packet,
02815                                                           NULL, NULL,
02816                                                         reply->packet->options,
02817                                                           reply->opt_state,
02818                                                           &tmp->scope,
02819                                                           oc, MDL)) {
02820                                 ddns_updates(reply->packet, NULL, NULL,
02821                                              tmp, NULL, reply->opt_state);
02822                         }
02823 #endif
02824                 }
02825 
02826                 /* Remove any old ia from the hash. */
02827                 if (reply->old_ia != NULL) {
02828                         ia_id = &reply->old_ia->iaid_duid;
02829                         ia_hash_delete(ia_ta_active,
02830                                        (unsigned char *)ia_id->data,
02831                                        ia_id->len, MDL);
02832                         ia_dereference(&reply->old_ia, MDL);
02833                 }
02834 
02835                 /* Put new ia into the hash. */
02836                 reply->ia->cltt = cur_time;
02837                 ia_id = &reply->ia->iaid_duid;
02838                 ia_hash_add(ia_ta_active, (unsigned char *)ia_id->data,
02839                             ia_id->len, reply->ia, MDL);
02840 
02841                 write_ia(reply->ia);
02842         }
02843 
02844       cleanup:
02845         if (packet_ia != NULL)
02846                 option_state_dereference(&packet_ia, MDL);
02847         if (iaaddr.data != NULL)
02848                 data_string_forget(&iaaddr, MDL);
02849         if (reply->reply_ia != NULL)
02850                 option_state_dereference(&reply->reply_ia, MDL);
02851         if (ia_data.data != NULL)
02852                 data_string_forget(&ia_data, MDL);
02853         if (data.data != NULL)
02854                 data_string_forget(&data, MDL);
02855         if (reply->ia != NULL)
02856                 ia_dereference(&reply->ia, MDL);
02857         if (reply->old_ia != NULL)
02858                 ia_dereference(&reply->old_ia, MDL);
02859         if (reply->lease != NULL)
02860                 iasubopt_dereference(&reply->lease, MDL);
02861 
02862         /*
02863          * ISC_R_CANCELED is a status code used by the addr processing to
02864          * indicate we're replying with other addresses.  This is still a
02865          * success at higher layers.
02866          */
02867         return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
02868 }
02869 
02870 /*
02871  * Verify the temporary address is available.
02872  */
02873 static isc_boolean_t
02874 temporary_is_available(struct reply_state *reply, struct iaddr *addr) {
02875         struct in6_addr tmp_addr;
02876         struct subnet *subnet;
02877         struct ipv6_pool *pool = NULL;
02878         struct ipv6_pond *pond = NULL;
02879         int i;
02880 
02881         memcpy(&tmp_addr, addr->iabuf, sizeof(tmp_addr));
02882         /*
02883          * Clients may choose to send :: as an address, with the idea to give
02884          * hints about preferred-lifetime or valid-lifetime.
02885          * So this is not a request for this address.
02886          */
02887         if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
02888                 return ISC_FALSE;
02889 
02890         /*
02891          * Verify that this address is on the client's network.
02892          */
02893         for (subnet = reply->shared->subnets ; subnet != NULL ;
02894              subnet = subnet->next_sibling) {
02895                 if (addr_eq(subnet_number(*addr, subnet->netmask),
02896                             subnet->net))
02897                         break;
02898         }
02899 
02900         /* Address not found on shared network. */
02901         if (subnet == NULL)
02902                 return ISC_FALSE;
02903 
02904         /*
02905          * Check if this address is owned (must be before next step).
02906          */
02907         if (address_is_owned(reply, addr))
02908                 return ISC_TRUE;
02909 
02910         /*
02911          * Verify that this address is in a temporary pool and try to get it.
02912          */
02913         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
02914                 if (((pond->prohibit_list != NULL) &&
02915                      (permitted(reply->packet, pond->prohibit_list))) ||
02916                     ((pond->permit_list != NULL) &&
02917                      (!permitted(reply->packet, pond->permit_list))))
02918                         continue;
02919 
02920                 for (i = 0 ; (pool = pond->ipv6_pools[i]) != NULL ; i++) {
02921                         if (pool->pool_type != D6O_IA_TA)
02922                                 continue;
02923 
02924                         if (ipv6_in_pool(&tmp_addr, pool))
02925                                 break;
02926                 }
02927 
02928                 if (pool != NULL)
02929                         break;
02930         }
02931 
02932         if (pool == NULL)
02933                 return ISC_FALSE;
02934         if (lease6_exists(pool, &tmp_addr))
02935                 return ISC_FALSE;
02936         if (iasubopt_allocate(&reply->lease, MDL) != ISC_R_SUCCESS)
02937                 return ISC_FALSE;
02938         reply->lease->addr = tmp_addr;
02939         reply->lease->plen = 0;
02940         /* Default is soft binding for 2 minutes. */
02941         if (add_lease6(pool, reply->lease, cur_time + 120) != ISC_R_SUCCESS)
02942                 return ISC_FALSE;
02943 
02944         return ISC_TRUE;
02945 }
02946 
02947 /*
02948  * Get a temporary address per prefix.
02949  */
02950 static isc_result_t
02951 find_client_temporaries(struct reply_state *reply) {
02952         int i;
02953         struct ipv6_pool *p = NULL;
02954         struct ipv6_pond *pond;
02955         isc_result_t status = ISC_R_NORESOURCES;;
02956         unsigned int attempts;
02957         struct iaddr send_addr;
02958 
02959         /*
02960          * Do a quick walk through of the ponds and pools
02961          * to see if we have any prefix pools
02962          */
02963         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
02964                 if (pond->ipv6_pools == NULL)
02965                         continue;
02966 
02967                 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
02968                         if (p->pool_type == D6O_IA_TA)
02969                                 break;
02970                 }
02971                 if (p != NULL)
02972                         break;
02973         }
02974 
02975         /* If we get here and p is NULL we have no useful pools */
02976         if (p == NULL) {
02977                 log_debug("Unable to get client addresses: "
02978                           "no IPv6 pools on this shared network");
02979                 return ISC_R_NORESOURCES;
02980         }
02981 
02982         /*
02983          * We have at least one pool that could provide an address
02984          * Now we walk through the ponds and pools again and check
02985          * to see if the client is permitted and if an address is
02986          * available
02987          */
02988 
02989         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
02990                 if (((pond->prohibit_list != NULL) &&
02991                      (permitted(reply->packet, pond->prohibit_list))) ||
02992                     ((pond->permit_list != NULL) &&
02993                      (!permitted(reply->packet, pond->permit_list))))
02994                         continue;
02995 
02996                 for (i = 0; (p = pond->ipv6_pools[i]) != NULL; i++) {
02997                         if (p->pool_type != D6O_IA_TA) {
02998                                 continue;
02999                         }
03000 
03001                         /*
03002                          * Get an address in this temporary pool.
03003                          */
03004                         status = create_lease6(p, &reply->lease, &attempts,
03005                                                &reply->client_id, cur_time + 120);
03006                         if (status != ISC_R_SUCCESS) {
03007                                 log_debug("Unable to get a temporary address.");
03008                                 goto cleanup;
03009                         }
03010 
03011                         status = reply_process_is_addressed(reply,
03012                                                             &reply->lease->scope,
03013                                                             pond->group);
03014                         if (status != ISC_R_SUCCESS) {
03015                                 goto cleanup;
03016                         }
03017                         send_addr.len = 16;
03018                         memcpy(send_addr.iabuf, &reply->lease->addr, 16);
03019                         status = reply_process_send_addr(reply, &send_addr);
03020                         if (status != ISC_R_SUCCESS) {
03021                                 goto cleanup;
03022                         }
03023                         /*
03024                          * reply->lease can't be null as we use it above
03025                          * add check if that changes
03026                          */
03027                         iasubopt_dereference(&reply->lease, MDL);
03028                 }
03029         }
03030 
03031       cleanup:
03032         if (reply->lease != NULL) {
03033                 iasubopt_dereference(&reply->lease, MDL);
03034         }
03035         return status;
03036 }
03037 
03038 /*
03039  * This function only returns failure on 'hard' failures.  If it succeeds,
03040  * it will leave a lease structure behind.
03041  */
03042 static isc_result_t
03043 reply_process_try_addr(struct reply_state *reply, struct iaddr *addr) {
03044         isc_result_t status = ISC_R_ADDRNOTAVAIL;
03045         struct ipv6_pool *pool = NULL;
03046         struct ipv6_pond *pond = NULL;
03047         int i;
03048         struct data_string data_addr;
03049 
03050         if ((reply == NULL) || (reply->shared == NULL) ||
03051             (addr == NULL) || (reply->lease != NULL))
03052                 return (DHCP_R_INVALIDARG);
03053 
03054         /*
03055          * Do a quick walk through of the ponds and pools
03056          * to see if we have any NA address pools
03057          */
03058         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
03059                 if (pond->ipv6_pools == NULL)
03060                         continue;
03061 
03062                 for (i = 0; ; i++) {
03063                         pool = pond->ipv6_pools[i];
03064                         if ((pool == NULL) ||
03065                             (pool->pool_type == D6O_IA_NA))
03066                                 break;
03067                 }
03068                 if (pool != NULL)
03069                         break;
03070         }
03071 
03072         /* If we get here and p is NULL we have no useful pools */
03073         if (pool == NULL) {
03074                 return (ISC_R_ADDRNOTAVAIL);
03075         }
03076 
03077         memset(&data_addr, 0, sizeof(data_addr));
03078         data_addr.len = addr->len;
03079         data_addr.data = addr->iabuf;
03080 
03081         /*
03082          * We have at least one pool that could provide an address
03083          * Now we walk through the ponds and pools again and check
03084          * to see if the client is permitted and if an address is
03085          * available
03086          * 
03087          * Within a given pond we start looking at the last pool we
03088          * allocated from, unless it had a collision trying to allocate
03089          * an address. This will tend to move us into less-filled pools.
03090          */
03091 
03092         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
03093                 if (((pond->prohibit_list != NULL) &&
03094                      (permitted(reply->packet, pond->prohibit_list))) ||
03095                     ((pond->permit_list != NULL) &&
03096                      (!permitted(reply->packet, pond->permit_list))))
03097                         continue;
03098 
03099                 for (i = 0 ; (pool = pond->ipv6_pools[i]) != NULL ; i++) {
03100                         if (pool->pool_type != D6O_IA_NA)
03101                                 continue;
03102 
03103                         status = try_client_v6_address(&reply->lease, pool,
03104                                                        &data_addr);
03105                         if (status == ISC_R_SUCCESS)
03106                                 break;
03107                 }
03108 
03109                 if (status == ISC_R_SUCCESS)
03110                         break;
03111         }
03112 
03113         /* Note that this is just pedantry.  There is no allocation to free. */
03114         data_string_forget(&data_addr, MDL);
03115         /* Return just the most recent status... */
03116         return (status);
03117 }
03118 
03119 /* Look around for an address to give the client.  First, look through the
03120  * old IA for addresses we can extend.  Second, try to allocate a new address.
03121  * Finally, actually add that address into the current reply IA.
03122  */
03123 static isc_result_t
03124 find_client_address(struct reply_state *reply) {
03125         struct iaddr send_addr;
03126         isc_result_t status = ISC_R_NORESOURCES;
03127         struct iasubopt *lease, *best_lease = NULL;
03128         struct binding_scope **scope;
03129         struct group *group;
03130         int i;
03131 
03132         if (reply->static_lease) {
03133                 if (reply->host == NULL)
03134                         return DHCP_R_INVALIDARG;
03135 
03136                 send_addr.len = 16;
03137                 memcpy(send_addr.iabuf, reply->fixed.data, 16);
03138 
03139                 scope = &global_scope;
03140                 group = reply->subnet->group;
03141                 goto send_addr;
03142         }
03143 
03144         if (reply->old_ia != NULL)  {
03145                 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
03146                         struct shared_network *candidate_shared;
03147                         struct ipv6_pond *pond;
03148 
03149                         lease = reply->old_ia->iasubopt[i];
03150                         candidate_shared = lease->ipv6_pool->shared_network;
03151                         pond = lease->ipv6_pool->ipv6_pond;
03152 
03153                         /*
03154                          * Look for the best lease on the client's shared
03155                          * network, that is still permitted
03156                          */
03157 
03158                         if ((candidate_shared != reply->shared) ||
03159                             (lease6_usable(lease) != ISC_TRUE))
03160                                 continue;
03161 
03162                         if (((pond->prohibit_list != NULL) &&
03163                              (permitted(reply->packet, pond->prohibit_list))) ||
03164                             ((pond->permit_list != NULL) &&
03165                              (!permitted(reply->packet, pond->permit_list))))
03166                                 continue;
03167 
03168                         best_lease = lease_compare(lease, best_lease);
03169                 }
03170         }
03171 
03172         /* Try to pick a new address if we didn't find one, or if we found an
03173          * abandoned lease.
03174          */
03175         if ((best_lease == NULL) || (best_lease->state == FTS_ABANDONED)) {
03176                 status = pick_v6_address(reply);
03177         } else if (best_lease != NULL) {
03178                 iasubopt_reference(&reply->lease, best_lease, MDL);
03179                 status = ISC_R_SUCCESS;
03180         }
03181 
03182         /* Pick the abandoned lease as a last resort. */
03183         if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
03184                 /* I don't see how this is supposed to be done right now. */
03185                 log_error("Reclaiming abandoned addresses is not yet "
03186                           "supported.  Treating this as an out of space "
03187                           "condition.");
03188                 /* iasubopt_reference(&reply->lease, best_lease, MDL); */
03189         }
03190 
03191         /* Give up now if we didn't find a lease. */
03192         if (status != ISC_R_SUCCESS)
03193                 return status;
03194 
03195         if (reply->lease == NULL)
03196                 log_fatal("Impossible condition at %s:%d.", MDL);
03197 
03198         /* Draw binding scopes from the lease's binding scope, and config
03199          * from the lease's containing subnet and higher.  Note that it may
03200          * be desirable to place the group attachment directly in the pool.
03201          */
03202         scope = &reply->lease->scope;
03203         group = reply->lease->ipv6_pool->ipv6_pond->group;
03204 
03205         send_addr.len = 16;
03206         memcpy(send_addr.iabuf, &reply->lease->addr, 16);
03207 
03208       send_addr:
03209         status = reply_process_is_addressed(reply, scope, group);
03210         if (status != ISC_R_SUCCESS)
03211                 return status;
03212 
03213         status = reply_process_send_addr(reply, &send_addr);
03214         return status;
03215 }
03216 
03217 /* Once an address is found for a client, perform several common functions;
03218  * Calculate and store valid and preferred lease times, draw client options
03219  * into the option state.
03220  */
03221 static isc_result_t
03222 reply_process_is_addressed(struct reply_state *reply,
03223                            struct binding_scope **scope, struct group *group)
03224 {
03225         isc_result_t status = ISC_R_SUCCESS;
03226         struct data_string data;
03227         struct option_cache *oc;
03228         struct option_state *tmp_options = NULL;
03229         struct on_star *on_star;
03230         int i;
03231 
03232         /* Initialize values we will cleanup. */
03233         memset(&data, 0, sizeof(data));
03234 
03235         /*
03236          * Find the proper on_star block to use.  We use the
03237          * one in the lease if we have a lease or the one in
03238          * the reply if we don't have a lease because this is
03239          * a static instance
03240          */
03241         if (reply->lease) {
03242                 on_star = &reply->lease->on_star;
03243         } else {
03244                 on_star = &reply->on_star;
03245         }
03246 
03247         /*
03248          * Bring in the root configuration.  We only do this to bring
03249          * in the on * statements, as we didn't have the lease available
03250          * we did it the first time.
03251          */
03252         option_state_allocate(&tmp_options, MDL);
03253         execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
03254                                     reply->packet->options, tmp_options,
03255                                     &global_scope, root_group, NULL,
03256                                     on_star);
03257         if (tmp_options != NULL) {
03258                 option_state_dereference(&tmp_options, MDL);
03259         }
03260 
03261         /*
03262          * Bring configured options into the root packet level cache - start
03263          * with the lease's closest enclosing group (passed in by the caller
03264          * as 'group').
03265          */
03266         execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
03267                                     reply->packet->options, reply->opt_state,
03268                                     scope, group, root_group, on_star);
03269 
03270         /* Execute statements from class scopes. */
03271         for (i = reply->packet->class_count; i > 0; i--) {
03272                 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
03273                                             reply->packet->options,
03274                                             reply->opt_state, scope,
03275                                             reply->packet->classes[i - 1]->group,
03276                                             group, on_star);
03277         }
03278 
03279         /*
03280          * If there is a host record, over-ride with values configured there,
03281          * without re-evaluating configuration from the previously executed
03282          * group or its common enclosers.
03283          */
03284         if (reply->host != NULL)
03285                 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
03286                                             reply->packet->options,
03287                                             reply->opt_state, scope,
03288                                             reply->host->group, group,
03289                                             on_star);
03290 
03291         /* Determine valid lifetime. */
03292         if (reply->client_valid == 0)
03293                 reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
03294         else
03295                 reply->send_valid = reply->client_valid;
03296 
03297         oc = lookup_option(&server_universe, reply->opt_state,
03298                            SV_DEFAULT_LEASE_TIME);
03299         if (oc != NULL) {
03300                 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
03301                                            reply->packet->options,
03302                                            reply->opt_state,
03303                                            scope, oc, MDL) ||
03304                     (data.len != 4)) {
03305                         log_error("reply_process_is_addressed: unable to "
03306                                   "evaluate default lease time");
03307                         status = ISC_R_FAILURE;
03308                         goto cleanup;
03309                 }
03310 
03311                 reply->send_valid = getULong(data.data);
03312                 data_string_forget(&data, MDL);
03313         }
03314 
03315         if (reply->client_prefer == 0)
03316                 reply->send_prefer = reply->send_valid;
03317         else
03318                 reply->send_prefer = reply->client_prefer;
03319 
03320         if (reply->send_prefer >= reply->send_valid)
03321                 reply->send_prefer = (reply->send_valid / 2) +
03322                                      (reply->send_valid / 8);
03323 
03324         oc = lookup_option(&server_universe, reply->opt_state,
03325                            SV_PREFER_LIFETIME);
03326         if (oc != NULL) {
03327                 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
03328                                            reply->packet->options,
03329                                            reply->opt_state,
03330                                            scope, oc, MDL) ||
03331                     (data.len != 4)) {
03332                         log_error("reply_process_is_addressed: unable to "
03333                                   "evaluate preferred lease time");
03334                         status = ISC_R_FAILURE;
03335                         goto cleanup;
03336                 }
03337 
03338                 reply->send_prefer = getULong(data.data);
03339                 data_string_forget(&data, MDL);
03340         }
03341 
03342         /* Note lowest values for later calculation of renew/rebind times. */
03343         if (reply->prefer > reply->send_prefer)
03344                 reply->prefer = reply->send_prefer;
03345 
03346         if (reply->valid > reply->send_valid)
03347                 reply->valid = reply->send_valid;
03348 
03349 #if 0
03350         /*
03351          * XXX: Old 4.0.0 alpha code would change the host {} record
03352          * XXX: uid upon lease assignment.  This was intended to cover the
03353          * XXX: case where a client first identifies itself using vendor
03354          * XXX: options in a solicit, or request, but later neglects to include
03355          * XXX: these options in a Renew or Rebind.  It is not clear that this
03356          * XXX: is required, and has some startling ramifications (such as
03357          * XXX: how to recover this dynamic host {} state across restarts).
03358          */
03359         if (reply->host != NULL)
03360                 change_host_uid(host, reply->client_id->data,
03361                                 reply->client_id->len);
03362 #endif /* 0 */
03363 
03364         /* Perform dynamic lease related update work. */
03365         if (reply->lease != NULL) {
03366                 /* Cached lifetimes */
03367                 reply->lease->prefer = reply->send_prefer;
03368                 reply->lease->valid = reply->send_valid;
03369 
03370                 /* Advance (or rewind) the valid lifetime. */
03371                 if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
03372                         reply->lease->soft_lifetime_end_time =
03373                                 cur_time + reply->send_valid;
03374                         /* Wait before renew! */
03375                 }
03376 
03377                 status = ia_add_iasubopt(reply->ia, reply->lease, MDL);
03378                 if (status != ISC_R_SUCCESS) {
03379                         log_fatal("reply_process_is_addressed: Unable to "
03380                                   "attach lease to new IA: %s",
03381                                   isc_result_totext(status));
03382                 }
03383 
03384                 /*
03385                  * If this is a new lease, make sure it is attached somewhere.
03386                  */
03387                 if (reply->lease->ia == NULL) {
03388                         ia_reference(&reply->lease->ia, reply->ia, MDL);
03389                 }
03390         }
03391 
03392         /* Bring a copy of the relevant options into the IA scope. */
03393         execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
03394                                     reply->packet->options, reply->reply_ia,
03395                                     scope, group, root_group, NULL);
03396 
03397         /* Execute statements from class scopes. */
03398         for (i = reply->packet->class_count; i > 0; i--) {
03399                 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
03400                                             reply->packet->options,
03401                                             reply->reply_ia, scope,
03402                                             reply->packet->classes[i - 1]->group,
03403                                             group, NULL);
03404         }
03405           
03406         /*
03407          * And bring in host record configuration, if any, but not to overlap
03408          * the previous group or its common enclosers.
03409          */
03410         if (reply->host != NULL)
03411                 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
03412                                             reply->packet->options,
03413                                             reply->reply_ia, scope,
03414                                             reply->host->group, group, NULL);
03415 
03416       cleanup:
03417         if (data.data != NULL)
03418                 data_string_forget(&data, MDL);
03419 
03420         if (status == ISC_R_SUCCESS)
03421                 reply->client_resources++;
03422 
03423         return status;
03424 }
03425 
03426 /* Simply send an IAADDR within the IA scope as described. */
03427 static isc_result_t
03428 reply_process_send_addr(struct reply_state *reply, struct iaddr *addr) {
03429         isc_result_t status = ISC_R_SUCCESS;
03430         struct data_string data;
03431 
03432         memset(&data, 0, sizeof(data));
03433 
03434         /* Now append the lease. */
03435         data.len = IAADDR_OFFSET;
03436         if (!buffer_allocate(&data.buffer, data.len, MDL)) {
03437                 log_error("reply_process_send_addr: out of memory"
03438                           "allocating new IAADDR buffer.");
03439                 status = ISC_R_NOMEMORY;
03440                 goto cleanup;
03441         }
03442         data.data = data.buffer->data;
03443 
03444         memcpy(data.buffer->data, addr->iabuf, 16);
03445         putULong(data.buffer->data + 16, reply->send_prefer);
03446         putULong(data.buffer->data + 20, reply->send_valid);
03447 
03448         if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
03449                                   data.buffer, data.buffer->data,
03450                                   data.len, D6O_IAADDR, 0)) {
03451                 log_error("reply_process_send_addr: unable "
03452                           "to save IAADDR option");
03453                 status = ISC_R_FAILURE;
03454                 goto cleanup;
03455         }
03456 
03457         reply->resources_included = ISC_TRUE;
03458 
03459       cleanup:
03460         if (data.data != NULL)
03461                 data_string_forget(&data, MDL);
03462 
03463         return status;
03464 }
03465 
03466 /* Choose the better of two leases. */
03467 static struct iasubopt *
03468 lease_compare(struct iasubopt *alpha, struct iasubopt *beta) {
03469         if (alpha == NULL)
03470                 return beta;
03471         if (beta == NULL)
03472                 return alpha;
03473 
03474         switch(alpha->state) {
03475               case FTS_ACTIVE:
03476                 switch(beta->state) {
03477                       case FTS_ACTIVE:
03478                         /* Choose the lease with the longest lifetime (most
03479                          * likely the most recently allocated).
03480                          */
03481                         if (alpha->hard_lifetime_end_time < 
03482                             beta->hard_lifetime_end_time)
03483                                 return beta;
03484                         else
03485                                 return alpha;
03486 
03487                       case FTS_EXPIRED:
03488                       case FTS_ABANDONED:
03489                         return alpha;
03490 
03491                       default:
03492                         log_fatal("Impossible condition at %s:%d.", MDL);
03493                 }
03494                 break;
03495 
03496               case FTS_EXPIRED:
03497                 switch (beta->state) {
03498                       case FTS_ACTIVE:
03499                         return beta;
03500 
03501                       case FTS_EXPIRED:
03502                         /* Choose the most recently expired lease. */
03503                         if (alpha->hard_lifetime_end_time <
03504                             beta->hard_lifetime_end_time)
03505                                 return beta;
03506                         else if ((alpha->hard_lifetime_end_time ==
03507                                   beta->hard_lifetime_end_time) &&
03508                                  (alpha->soft_lifetime_end_time <
03509                                   beta->soft_lifetime_end_time))
03510                                 return beta;
03511                         else
03512                                 return alpha;
03513 
03514                       case FTS_ABANDONED:
03515                         return alpha;
03516 
03517                       default:
03518                         log_fatal("Impossible condition at %s:%d.", MDL);
03519                 }
03520                 break;
03521 
03522               case FTS_ABANDONED:
03523                 switch (beta->state) {
03524                       case FTS_ACTIVE:
03525                       case FTS_EXPIRED:
03526                         return alpha;
03527 
03528                       case FTS_ABANDONED:
03529                         /* Choose the lease that was abandoned longest ago. */
03530                         if (alpha->hard_lifetime_end_time <
03531                             beta->hard_lifetime_end_time)
03532                                 return alpha;
03533 
03534                       default:
03535                         log_fatal("Impossible condition at %s:%d.", MDL);
03536                 }
03537                 break;
03538 
03539               default:
03540                 log_fatal("Impossible condition at %s:%d.", MDL);
03541         }
03542 
03543         log_fatal("Triple impossible condition at %s:%d.", MDL);
03544         return NULL;
03545 }
03546 
03547 /* Process a client-supplied IA_PD.  This may append options to the tail of
03548  * the reply packet being built in the reply_state structure.
03549  */
03550 static isc_result_t
03551 reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
03552         isc_result_t status = ISC_R_SUCCESS;
03553         u_int32_t iaid;
03554         unsigned ia_cursor;
03555         struct option_state *packet_ia;
03556         struct option_cache *oc;
03557         struct data_string ia_data, data;
03558 
03559         /* Initialize values that will get cleaned up on return. */
03560         packet_ia = NULL;
03561         memset(&ia_data, 0, sizeof(ia_data));
03562         memset(&data, 0, sizeof(data));
03563         /* 
03564          * Note that find_client_prefix() may set reply->lease.
03565          */
03566 
03567         /* Make sure there is at least room for the header. */
03568         if ((reply->cursor + IA_PD_OFFSET + 4) > sizeof(reply->buf)) {
03569                 log_error("reply_process_ia_pd: Reply too long for IA.");
03570                 return ISC_R_NOSPACE;
03571         }
03572 
03573 
03574         /* Fetch the IA_PD contents. */
03575         if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
03576                                        ia, IA_PD_OFFSET)) {
03577                 log_error("reply_process_ia_pd: error evaluating ia");
03578                 status = ISC_R_FAILURE;
03579                 goto cleanup;
03580         }
03581 
03582         /* Extract IA_PD header contents. */
03583         iaid = getULong(ia_data.data);
03584         reply->renew = getULong(ia_data.data + 4);
03585         reply->rebind = getULong(ia_data.data + 8);
03586 
03587         /* Create an IA_PD structure. */
03588         if (ia_allocate(&reply->ia, iaid, (char *)reply->client_id.data, 
03589                         reply->client_id.len, MDL) != ISC_R_SUCCESS) {
03590                 log_error("reply_process_ia_pd: no memory for ia.");
03591                 status = ISC_R_NOMEMORY;
03592                 goto cleanup;
03593         }
03594         reply->ia->ia_type = D6O_IA_PD;
03595 
03596         /* Cache pre-existing IA_PD, if any. */
03597         ia_hash_lookup(&reply->old_ia, ia_pd_active,
03598                        (unsigned char *)reply->ia->iaid_duid.data,
03599                        reply->ia->iaid_duid.len, MDL);
03600 
03601         /*
03602          * Create an option cache to carry the IA_PD option contents, and
03603          * execute any user-supplied values into it.
03604          */
03605         if (!option_state_allocate(&reply->reply_ia, MDL)) {
03606                 status = ISC_R_NOMEMORY;
03607                 goto cleanup;
03608         }
03609 
03610         /* Check & count the fixed prefix host records. */
03611         reply->static_prefixes = 0;
03612         if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
03613                 struct iaddrcidrnetlist *fp;
03614 
03615                 for (fp = reply->host->fixed_prefix; fp != NULL;
03616                      fp = fp->next) {
03617                         reply->static_prefixes += 1;
03618                 }
03619         }
03620 
03621         /*
03622          * Save the cursor position at the start of the IA_PD, so we can
03623          * set length and adjust t1/t2 values later.  We write a temporary
03624          * header out now just in case we decide to adjust the packet
03625          * within sub-process functions.
03626          */
03627         ia_cursor = reply->cursor;
03628 
03629         /* Initialize the IA_PD header.  First the code. */
03630         putUShort(reply->buf.data + reply->cursor, (unsigned)D6O_IA_PD);
03631         reply->cursor += 2;
03632 
03633         /* Then option length. */
03634         putUShort(reply->buf.data + reply->cursor, 0x0Cu);
03635         reply->cursor += 2;
03636 
03637         /* Then IA_PD header contents; IAID. */
03638         putULong(reply->buf.data + reply->cursor, iaid);
03639         reply->cursor += 4;
03640 
03641         /* We store the client's t1 for now, and may over-ride it later. */
03642         putULong(reply->buf.data + reply->cursor, reply->renew);
03643         reply->cursor += 4;
03644 
03645         /* We store the client's t2 for now, and may over-ride it later. */
03646         putULong(reply->buf.data + reply->cursor, reply->rebind);
03647         reply->cursor += 4;
03648 
03649         /* 
03650          * For each prefix in this IA_PD, decide what to do about it.
03651          */
03652         oc = lookup_option(&dhcpv6_universe, packet_ia, D6O_IAPREFIX);
03653         reply->valid = reply->prefer = 0xffffffff;
03654         reply->client_valid = reply->client_prefer = 0;
03655         reply->preflen = -1;
03656         for (; oc != NULL ; oc = oc->next) {
03657                 status = reply_process_prefix(reply, oc);
03658 
03659                 /*
03660                  * Canceled means we did not allocate prefixes to the
03661                  * client, but we're "done" with this IA - we set a status
03662                  * code.  So transmit this reply, e.g., move on to the next
03663                  * IA.
03664                  */
03665                 if (status == ISC_R_CANCELED)
03666                         break;
03667 
03668                 if ((status != ISC_R_SUCCESS) &&
03669                     (status != ISC_R_ADDRINUSE) &&
03670                     (status != ISC_R_ADDRNOTAVAIL))
03671                         goto cleanup;
03672         }
03673 
03674         reply->pd_count++;
03675 
03676         /*
03677          * If we fell through the above and never gave the client
03678          * a prefix, give it one now.
03679          */
03680         if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
03681                 status = find_client_prefix(reply);
03682 
03683                 if (status == ISC_R_NORESOURCES) {
03684                         switch (reply->packet->dhcpv6_msg_type) {
03685                               case DHCPV6_SOLICIT:
03686                                 /*
03687                                  * No prefix for any IA is handled
03688                                  * by the caller.
03689                                  */
03690                                 /* FALL THROUGH */
03691 
03692                               case DHCPV6_REQUEST:
03693                                 /* Same than for addresses. */
03694                                 option_state_dereference(&reply->reply_ia, MDL);
03695                                 if (!option_state_allocate(&reply->reply_ia,
03696                                                            MDL))
03697                                 {
03698                                         log_error("reply_process_ia_pd: No "
03699                                                   "memory for option state "
03700                                                   "wipe.");
03701                                         status = ISC_R_NOMEMORY;
03702                                         goto cleanup;
03703                                 }
03704 
03705                                 if (!set_status_code(STATUS_NoPrefixAvail,
03706                                                      "No prefixes available "
03707                                                      "for this interface.",
03708                                                       reply->reply_ia)) {
03709                                         log_error("reply_process_ia_pd: "
03710                                                   "Unable to set "
03711                                                   "NoPrefixAvail status "
03712                                                   "code.");
03713                                         status = ISC_R_FAILURE;
03714                                         goto cleanup;
03715                                 }
03716 
03717                                 status = ISC_R_SUCCESS;
03718                                 break;
03719 
03720                               default:
03721                                 if (reply->resources_included)
03722                                         status = ISC_R_SUCCESS;
03723                                 else
03724                                         goto cleanup;
03725                                 break;
03726                         }
03727                 }
03728 
03729                 if (status != ISC_R_SUCCESS)
03730                         goto cleanup;
03731         }
03732 
03733         reply->cursor += store_options6((char *)reply->buf.data + reply->cursor,
03734                                         sizeof(reply->buf) - reply->cursor,
03735                                         reply->reply_ia, reply->packet,
03736                                         required_opts_IA_PD, NULL);
03737 
03738         /* Reset the length of this IA_PD to match what was just written. */
03739         putUShort(reply->buf.data + ia_cursor + 2,
03740                   reply->cursor - (ia_cursor + 4));
03741 
03742         /*
03743          * T1/T2 time selection is kind of weird.  We actually use DHCP
03744          * (v4) scoped options as handy existing places where these might
03745          * be configured by an administrator.  A value of zero tells the
03746          * client it may choose its own renewal time.
03747          */
03748         reply->renew = 0;
03749         oc = lookup_option(&dhcp_universe, reply->opt_state,
03750                            DHO_DHCP_RENEWAL_TIME);
03751         if (oc != NULL) {
03752                 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
03753                                            reply->packet->options,
03754                                            reply->opt_state, &global_scope,
03755                                            oc, MDL) ||
03756                     (data.len != 4)) {
03757                         log_error("Invalid renewal time.");
03758                 } else {
03759                         reply->renew = getULong(data.data);
03760                 }
03761 
03762                 if (data.data != NULL)
03763                         data_string_forget(&data, MDL);
03764         }
03765         putULong(reply->buf.data + ia_cursor + 8, reply->renew);
03766 
03767         /* Now T2. */
03768         reply->rebind = 0;
03769         oc = lookup_option(&dhcp_universe, reply->opt_state,
03770                            DHO_DHCP_REBINDING_TIME);
03771         if (oc != NULL) {
03772                 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
03773                                            reply->packet->options,
03774                                            reply->opt_state, &global_scope,
03775                                            oc, MDL) ||
03776                     (data.len != 4)) {
03777                         log_error("Invalid rebinding time.");
03778                 } else {
03779                         reply->rebind = getULong(data.data);
03780                 }
03781 
03782                 if (data.data != NULL)
03783                         data_string_forget(&data, MDL);
03784         }
03785         putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
03786 
03787         /*
03788          * yes, goto's aren't the best but we also want to avoid extra
03789          * indents
03790          */
03791         if (status == ISC_R_CANCELED)
03792                 goto cleanup;
03793 
03794         /*
03795          * Handle static prefixes, we always log stuff and if it's
03796          * a hard binding we run any commit statements that we have
03797          */
03798         if (reply->static_prefixes != 0) {
03799                 char tmp_addr[INET6_ADDRSTRLEN];
03800                 log_info("%s PD: address %s/%d to client with duid %s "
03801                          "iaid = %d static",
03802                          dhcpv6_type_names[reply->buf.reply.msg_type],
03803                          inet_ntop(AF_INET6, reply->fixed_pref.lo_addr.iabuf,
03804                                    tmp_addr, sizeof(tmp_addr)),
03805                          reply->fixed_pref.bits,
03806                          print_hex_1(reply->client_id.len,
03807                                      reply->client_id.data, 60),
03808                          iaid);
03809                 if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
03810                     (reply->on_star.on_commit != NULL)) {
03811                         execute_statements(NULL, reply->packet, NULL, NULL,
03812                                            reply->packet->options,
03813                                            reply->opt_state,
03814                                            NULL, reply->on_star.on_commit,
03815                                            NULL);
03816                         executable_statement_dereference
03817                                 (&reply->on_star.on_commit, MDL);
03818                 }
03819                 goto cleanup;
03820         }
03821 
03822         /*
03823          * If we have any addresses log what we are doing.
03824          */
03825         if (reply->ia->num_iasubopt != 0) {
03826                 struct iasubopt *tmp;
03827                 int i;
03828                 char tmp_addr[INET6_ADDRSTRLEN];
03829 
03830                 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
03831                         tmp = reply->ia->iasubopt[i];
03832 
03833                         log_info("%s PD: address %s/%d to client with duid %s"
03834                                  " iaid = %d valid for %d seconds",
03835                                  dhcpv6_type_names[reply->buf.reply.msg_type],
03836                                  inet_ntop(AF_INET6, &tmp->addr,
03837                                            tmp_addr, sizeof(tmp_addr)),
03838                                  (int)tmp->plen,
03839                                  print_hex_1(reply->client_id.len,
03840                                              reply->client_id.data, 60),
03841                                  iaid, tmp->valid);
03842                 }
03843         }
03844 
03845         /*
03846          * If this is not a 'soft' binding, consume the new changes into
03847          * the database (if any have been attached to the ia_pd).
03848          *
03849          * Loop through the assigned dynamic prefixes, referencing the
03850          * prefixes onto this IA_PD rather than any old ones, and updating
03851          * prefix pool timers for each (if any).
03852          */
03853         if ((reply->buf.reply.msg_type == DHCPV6_REPLY) &&
03854             (reply->ia->num_iasubopt != 0)) {
03855                 struct iasubopt *tmp;
03856                 struct data_string *ia_id;
03857                 int i;
03858 
03859                 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
03860                         tmp = reply->ia->iasubopt[i];
03861 
03862                         if (tmp->ia != NULL)
03863                                 ia_dereference(&tmp->ia, MDL);
03864                         ia_reference(&tmp->ia, reply->ia, MDL);
03865 
03866                         /* Commit 'hard' bindings. */
03867                         renew_lease6(tmp->ipv6_pool, tmp);
03868                         schedule_lease_timeout(tmp->ipv6_pool);
03869 
03870                         /* If we have anything to do on commit do it now */
03871                         if (tmp->on_star.on_commit != NULL) {
03872                                 execute_statements(NULL, reply->packet,
03873                                                    NULL, NULL, 
03874                                                    reply->packet->options,
03875                                                    reply->opt_state,
03876                                                    &tmp->scope,
03877                                                    tmp->on_star.on_commit,
03878                                                    &tmp->on_star);
03879                                 executable_statement_dereference
03880                                         (&tmp->on_star.on_commit, MDL);
03881                         }
03882                 }
03883 
03884                 /* Remove any old ia from the hash. */
03885                 if (reply->old_ia != NULL) {
03886                         ia_id = &reply->old_ia->iaid_duid;
03887                         ia_hash_delete(ia_pd_active,
03888                                        (unsigned char *)ia_id->data,
03889                                        ia_id->len, MDL);
03890                         ia_dereference(&reply->old_ia, MDL);
03891                 }
03892 
03893                 /* Put new ia into the hash. */
03894                 reply->ia->cltt = cur_time;
03895                 ia_id = &reply->ia->iaid_duid;
03896                 ia_hash_add(ia_pd_active, (unsigned char *)ia_id->data,
03897                             ia_id->len, reply->ia, MDL);
03898 
03899                 write_ia(reply->ia);
03900         }
03901 
03902       cleanup:
03903         if (packet_ia != NULL)
03904                 option_state_dereference(&packet_ia, MDL);
03905         if (reply->reply_ia != NULL)
03906                 option_state_dereference(&reply->reply_ia, MDL);
03907         if (ia_data.data != NULL)
03908                 data_string_forget(&ia_data, MDL);
03909         if (data.data != NULL)
03910                 data_string_forget(&data, MDL);
03911         if (reply->ia != NULL)
03912                 ia_dereference(&reply->ia, MDL);
03913         if (reply->old_ia != NULL)
03914                 ia_dereference(&reply->old_ia, MDL);
03915         if (reply->lease != NULL)
03916                 iasubopt_dereference(&reply->lease, MDL);
03917         if (reply->on_star.on_expiry != NULL)
03918                 executable_statement_dereference
03919                         (&reply->on_star.on_expiry, MDL);
03920         if (reply->on_star.on_release != NULL)
03921                 executable_statement_dereference
03922                         (&reply->on_star.on_release, MDL);
03923 
03924         /*
03925          * ISC_R_CANCELED is a status code used by the prefix processing to
03926          * indicate we're replying with a status code.  This is still a
03927          * success at higher layers.
03928          */
03929         return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
03930 }
03931 
03932 /*
03933  * Process an IAPREFIX within a given IA_PD, storing any IAPREFIX reply
03934  * contents into the reply's current ia_pd-scoped option cache.  Returns
03935  * ISC_R_CANCELED in the event we are replying with a status code and do
03936  * not wish to process more IAPREFIXes within this IA_PD.
03937  */
03938 static isc_result_t
03939 reply_process_prefix(struct reply_state *reply, struct option_cache *pref) {
03940         u_int32_t pref_life, valid_life;
03941         struct binding_scope **scope;
03942         struct iaddrcidrnet tmp_pref;
03943         struct option_cache *oc;
03944         struct data_string iapref, data;
03945         isc_result_t status = ISC_R_SUCCESS;
03946         struct group *group;
03947 
03948         /* Initializes values that will be cleaned up. */
03949         memset(&iapref, 0, sizeof(iapref));
03950         memset(&data, 0, sizeof(data));
03951         /* Note that reply->lease may be set by prefix_is_owned() */
03952 
03953         /*
03954          * There is no point trying to process an incoming prefix if there
03955          * is no room for an outgoing prefix.
03956          */
03957         if ((reply->cursor + 29) > sizeof(reply->buf)) {
03958                 log_error("reply_process_prefix: Out of room for prefix.");
03959                 return ISC_R_NOSPACE;
03960         }
03961 
03962         /* Extract this IAPREFIX option. */
03963         if (!evaluate_option_cache(&iapref, reply->packet, NULL, NULL, 
03964                                    reply->packet->options, NULL, &global_scope,
03965                                    pref, MDL) ||
03966             (iapref.len < IAPREFIX_OFFSET)) {
03967                 log_error("reply_process_prefix: error evaluating IAPREFIX.");
03968                 status = ISC_R_FAILURE;
03969                 goto cleanup;
03970         }
03971 
03972         /*
03973          * Layout: preferred and valid lifetimes followed by the prefix
03974          * length and the IPv6 address.
03975          */
03976         pref_life = getULong(iapref.data);
03977         valid_life = getULong(iapref.data + 4);
03978 
03979         if ((reply->client_valid == 0) ||
03980             (reply->client_valid > valid_life))
03981                 reply->client_valid = valid_life;
03982 
03983         if ((reply->client_prefer == 0) ||
03984             (reply->client_prefer > pref_life))
03985                 reply->client_prefer = pref_life;
03986 
03987         /* 
03988          * Clients may choose to send ::/0 as a prefix, with the idea to give
03989          * hints about preferred-lifetime or valid-lifetime.
03990          */
03991         tmp_pref.lo_addr.len = 16;
03992         memset(tmp_pref.lo_addr.iabuf, 0, 16);
03993         if ((iapref.data[8] == 0) &&
03994             (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
03995                 /* Status remains success; we just ignore this one. */
03996                 goto cleanup;
03997         }
03998 
03999         /*
04000          * Clients may choose to send ::/X as a prefix to specify a
04001          * preferred/requested prefix length. Note X is never zero here.
04002          */
04003         tmp_pref.bits = (int) iapref.data[8];
04004         if (reply->preflen < 0) {
04005                 /* Cache the first preferred prefix length. */
04006                 reply->preflen = tmp_pref.bits;
04007         }
04008         if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
04009                 goto cleanup;
04010         }
04011 
04012         memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
04013 
04014         /* Verify the prefix belongs to the client. */
04015         if (!prefix_is_owned(reply, &tmp_pref)) {
04016                 /* Same than for addresses. */
04017                 if ((reply->packet->dhcpv6_msg_type == DHCPV6_SOLICIT) ||
04018                     (reply->packet->dhcpv6_msg_type == DHCPV6_REQUEST) ||
04019                     (reply->packet->dhcpv6_msg_type == DHCPV6_REBIND)) {
04020                         status = reply_process_try_prefix(reply, &tmp_pref);
04021 
04022                         /* Either error out or skip this prefix. */
04023                         if ((status != ISC_R_SUCCESS) &&
04024                             (status != ISC_R_ADDRINUSE) &&
04025                             (status != ISC_R_ADDRNOTAVAIL))
04026                                 goto cleanup;
04027 
04028                         if (reply->lease == NULL) {
04029                                 if (reply->packet->dhcpv6_msg_type ==
04030                                                         DHCPV6_REBIND) {
04031                                         reply->send_prefer = 0;
04032                                         reply->send_valid = 0;
04033                                         goto send_pref;
04034                                 }
04035 
04036                                 /* status remains success - ignore */
04037                                 goto cleanup;
04038                         }
04039                 /*
04040                  * RFC3633 section 18.2.3:
04041                  *
04042                  * If the delegating router cannot find a binding
04043                  * for the requesting router's IA_PD the delegating
04044                  * router returns the IA_PD containing no prefixes
04045                  * with a Status Code option set to NoBinding in the
04046                  * Reply message.
04047                  *
04048                  * On mismatch we (ab)use this pretending we have not the IA
04049                  * as soon as we have not a prefix.
04050                  */
04051                 } else if (reply->packet->dhcpv6_msg_type == DHCPV6_RENEW) {
04052                         /* Rewind the IA_PD to empty. */
04053                         option_state_dereference(&reply->reply_ia, MDL);
04054                         if (!option_state_allocate(&reply->reply_ia, MDL)) {
04055                                 log_error("reply_process_prefix: No memory "
04056                                           "for option state wipe.");
04057                                 status = ISC_R_NOMEMORY;
04058                                 goto cleanup;
04059                         }
04060 
04061                         /* Append a NoBinding status code.  */
04062                         if (!set_status_code(STATUS_NoBinding,
04063                                              "Prefix not bound to this "
04064                                              "interface.", reply->reply_ia)) {
04065                                 log_error("reply_process_prefix: Unable to "
04066                                           "attach status code.");
04067                                 status = ISC_R_FAILURE;
04068                                 goto cleanup;
04069                         }
04070 
04071                         /* Fin (no more IAPREFIXes). */
04072                         status = ISC_R_CANCELED;
04073                         goto cleanup;
04074                 } else {
04075                         log_error("It is impossible to lease a client that is "
04076                                   "not sending a solicit, request, renew, or "
04077                                   "rebind message.");
04078                         status = ISC_R_FAILURE;
04079                         goto cleanup;
04080                 }
04081         }
04082 
04083         if (reply->static_prefixes > 0) {
04084                 if (reply->host == NULL)
04085                         log_fatal("Impossible condition at %s:%d.", MDL);
04086 
04087                 scope = &global_scope;
04088 
04089                 /* Find the static prefixe's subnet. */
04090                 if (find_grouped_subnet(&reply->subnet, reply->shared,
04091                                         tmp_pref.lo_addr, MDL) == 0)
04092                         log_fatal("Impossible condition at %s:%d.", MDL);
04093                 group = reply->subnet->group;
04094                 subnet_dereference(&reply->subnet, MDL);
04095 
04096                 /* Copy the static prefix for logging purposes */
04097                 memcpy(&reply->fixed_pref, &tmp_pref, sizeof(tmp_pref));
04098         } else {
04099                 if (reply->lease == NULL)
04100                         log_fatal("Impossible condition at %s:%d.", MDL);
04101 
04102                 scope = &reply->lease->scope;
04103                 group = reply->lease->ipv6_pool->ipv6_pond->group;
04104         }
04105 
04106         /*
04107          * If client_resources is nonzero, then the reply_process_is_prefixed
04108          * function has executed configuration state into the reply option
04109          * cache.  We will use that valid cache to derive configuration for
04110          * whether or not to engage in additional prefixes, and similar.
04111          */
04112         if (reply->client_resources != 0) {
04113                 unsigned limit = 1;
04114 
04115                 /*
04116                  * Does this client have "enough" prefixes already?  Default
04117                  * to one.  Everybody gets one, and one should be enough for
04118                  * anybody.
04119                  */
04120                 oc = lookup_option(&server_universe, reply->opt_state,
04121                                    SV_LIMIT_PREFS_PER_IA);
04122                 if (oc != NULL) {
04123                         if (!evaluate_option_cache(&data, reply->packet,
04124                                                    NULL, NULL,
04125                                                    reply->packet->options,
04126                                                    reply->opt_state,
04127                                                    scope, oc, MDL) ||
04128                             (data.len != 4)) {
04129                                 log_error("reply_process_prefix: unable to "
04130                                           "evaluate prefs-per-ia value.");
04131                                 status = ISC_R_FAILURE;
04132                                 goto cleanup;
04133                         }
04134 
04135                         limit = getULong(data.data);
04136                         data_string_forget(&data, MDL);
04137                 }
04138 
04139                 /*
04140                  * If we wish to limit the client to a certain number of
04141                  * prefixes, then omit the prefix from the reply.
04142                  */
04143                 if (reply->client_resources >= limit)
04144                         goto cleanup;
04145         }
04146 
04147         status = reply_process_is_prefixed(reply, scope, group);
04148         if (status != ISC_R_SUCCESS)
04149                 goto cleanup;
04150 
04151       send_pref:
04152         status = reply_process_send_prefix(reply, &tmp_pref);
04153 
04154       cleanup:
04155         if (iapref.data != NULL)
04156                 data_string_forget(&iapref, MDL);
04157         if (data.data != NULL)
04158                 data_string_forget(&data, MDL);
04159         if (reply->lease != NULL)
04160                 iasubopt_dereference(&reply->lease, MDL);
04161 
04162         return status;
04163 }
04164 
04165 /*
04166  * Verify the prefix belongs to the client.  If we've got a host
04167  * record with fixed prefixes, it has to be an assigned prefix
04168  * (fault out all else).  Otherwise it's a dynamic prefix, so lookup
04169  * that prefix and make sure it belongs to this DUID:IAID pair.
04170  */
04171 static isc_boolean_t
04172 prefix_is_owned(struct reply_state *reply, struct iaddrcidrnet *pref) {
04173         struct iaddrcidrnetlist *l;
04174         int i;
04175         struct ipv6_pond *pond;
04176 
04177         /*
04178          * This faults out prefixes that don't match fixed prefixes.
04179          */
04180         if (reply->static_prefixes > 0) {
04181                 for (l = reply->host->fixed_prefix; l != NULL; l = l->next) {
04182                         if ((pref->bits == l->cidrnet.bits) &&
04183                             (memcmp(pref->lo_addr.iabuf,
04184                                     l->cidrnet.lo_addr.iabuf, 16) == 0))
04185                                 return (ISC_TRUE);
04186                 }
04187                 return (ISC_FALSE);
04188         }
04189 
04190         if ((reply->old_ia == NULL) ||
04191             (reply->old_ia->num_iasubopt == 0))
04192                 return (ISC_FALSE);
04193 
04194         for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
04195                 struct iasubopt *tmp;
04196 
04197                 tmp = reply->old_ia->iasubopt[i];
04198 
04199                 if ((pref->bits == (int) tmp->plen) &&
04200                     (memcmp(pref->lo_addr.iabuf, &tmp->addr, 16) == 0)) {
04201                         if (lease6_usable(tmp) == ISC_FALSE) {
04202                                 return (ISC_FALSE);
04203                         }
04204 
04205                         pond = tmp->ipv6_pool->ipv6_pond;
04206                         if (((pond->prohibit_list != NULL) &&
04207                              (permitted(reply->packet, pond->prohibit_list))) ||
04208                             ((pond->permit_list != NULL) &&
04209                              (!permitted(reply->packet, pond->permit_list))))
04210                                 return (ISC_FALSE);
04211 
04212                         iasubopt_reference(&reply->lease, tmp, MDL);
04213                         return (ISC_TRUE);
04214                 }
04215         }
04216 
04217         return (ISC_FALSE);
04218 }
04219 
04220 /*
04221  * This function only returns failure on 'hard' failures.  If it succeeds,
04222  * it will leave a prefix structure behind.
04223  */
04224 static isc_result_t
04225 reply_process_try_prefix(struct reply_state *reply,
04226                          struct iaddrcidrnet *pref) {
04227         isc_result_t status = ISC_R_ADDRNOTAVAIL;
04228         struct ipv6_pool *pool = NULL;
04229         struct ipv6_pond *pond = NULL;
04230         int i;
04231         struct data_string data_pref;
04232 
04233         if ((reply == NULL) || (reply->shared == NULL) ||
04234             (pref == NULL) || (reply->lease != NULL))
04235                 return (DHCP_R_INVALIDARG);
04236 
04237         /*
04238          * Do a quick walk through of the ponds and pools
04239          * to see if we have any prefix pools
04240          */
04241         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
04242                 if (pond->ipv6_pools == NULL)
04243                         continue;
04244 
04245                 for (i = 0; (pool = pond->ipv6_pools[i]) != NULL; i++) {
04246                         if (pool->pool_type == D6O_IA_PD)
04247                                 break;
04248                 }
04249                 if (pool != NULL)
04250                         break;
04251         }
04252 
04253         /* If we get here and p is NULL we have no useful pools */
04254         if (pool == NULL) {
04255                 return (ISC_R_ADDRNOTAVAIL);
04256         }
04257 
04258         memset(&data_pref, 0, sizeof(data_pref));
04259         data_pref.len = 17;
04260         if (!buffer_allocate(&data_pref.buffer, data_pref.len, MDL)) {
04261                 log_error("reply_process_try_prefix: out of memory.");
04262                 return (ISC_R_NOMEMORY);
04263         }
04264         data_pref.data = data_pref.buffer->data;
04265         data_pref.buffer->data[0] = (u_int8_t) pref->bits;
04266         memcpy(data_pref.buffer->data + 1, pref->lo_addr.iabuf, 16);
04267 
04268         /*
04269          * We have at least one pool that could provide a prefix
04270          * Now we walk through the ponds and pools again and check
04271          * to see if the client is permitted and if an prefix is
04272          * available
04273          * 
04274          */
04275 
04276         for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->next) {
04277                 if (((pond->prohibit_list != NULL) &&
04278                      (permitted(reply->packet, pond->prohibit_list))) ||
04279                     ((pond->permit_list != NULL) &&
04280                      (!permitted(reply->packet, pond->permit_list))))
04281                         continue;
04282 
04283                 for (i = 0; (pool = pond->ipv6_pools[i]) != NULL; i++) {
04284                         if (pool->pool_type != D6O_IA_PD) {
04285                                 continue;
04286                         }
04287 
04288                         status = try_client_v6_prefix(&reply->lease, pool,
04289                                                       &data_pref);
04290                         /* If we found it in this pool (either in use or available), 
04291                            there is no need to look further. */
04292                         if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
04293                                 break;
04294                         }
04295                 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
04296                         break;
04297         }
04298 
04299         data_string_forget(&data_pref, MDL);
04300         /* Return just the most recent status... */
04301         return (status);
04302 }
04303 
04304 /* Look around for a prefix to give the client.  First, look through the old
04305  * IA_PD for prefixes we can extend.  Second, try to allocate a new prefix.
04306  * Finally, actually add that prefix into the current reply IA_PD.
04307  */
04308 static isc_result_t
04309 find_client_prefix(struct reply_state *reply) {
04310         struct iaddrcidrnet send_pref;
04311         isc_result_t status = ISC_R_NORESOURCES;
04312         struct iasubopt *prefix, *best_prefix = NULL;
04313         struct binding_scope **scope;
04314         int i;
04315         struct group *group;
04316 
04317         if (reply->static_prefixes > 0) {
04318                 struct iaddrcidrnetlist *l;
04319 
04320                 if (reply->host == NULL)
04321                         return DHCP_R_INVALIDARG;
04322 
04323                 for (l = reply->host->fixed_prefix; l != NULL; l = l->next) {
04324                         if (l->cidrnet.bits == reply->preflen)
04325                                 break;
04326                 }
04327                 if (l == NULL) {
04328                         /*
04329                          * If no fixed prefix has the preferred length,
04330                          * get the first one.
04331                          */
04332                         l = reply->host->fixed_prefix;
04333                 }
04334                 memcpy(&send_pref, &l->cidrnet, sizeof(send_pref));
04335 
04336                 scope = &global_scope;
04337 
04338                 /* Find the static prefixe's subnet. */
04339                 if (find_grouped_subnet(&reply->subnet, reply->shared,
04340                                         send_pref.lo_addr, MDL) == 0)
04341                         log_fatal("Impossible condition at %s:%d.", MDL);
04342                 group = reply->subnet->group;
04343                 subnet_dereference(&reply->subnet, MDL);
04344 
04345                 /* Copy the prefix for logging purposes */
04346                 memcpy(&reply->fixed_pref, &l->cidrnet, sizeof(send_pref));
04347 
04348                 goto send_pref;
04349         }
04350 
04351         if (reply->old_ia != NULL)  {
04352                 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
04353                         struct shared_network *candidate_shared;
04354                         struct ipv6_pond *pond;
04355 
04356                         prefix = reply->old_ia->iasubopt[i];
04357                         candidate_shared = prefix->ipv6_pool->shared_network;
04358                         pond = prefix->ipv6_pool->ipv6_pond;
04359 
04360                         /*
04361                          * Consider this prefix if it is in a global pool or
04362                          * if it is scoped in a pool under the client's shared
04363                          * network.
04364                          */
04365                         if (((candidate_shared != NULL) &&
04366                              (candidate_shared != reply->shared)) ||
04367                             (lease6_usable(prefix) != ISC_TRUE))
04368                                 continue;
04369 
04370                         /*
04371                          * And check if the prefix is still permitted
04372                          */
04373 
04374                         if (((pond->prohibit_list != NULL) &&
04375                              (permitted(reply->packet, pond->prohibit_list))) ||
04376                             ((pond->permit_list != NULL) &&
04377                              (!permitted(reply->packet, pond->permit_list))))
04378                                 continue;
04379 
04380                         best_prefix = prefix_compare(reply, prefix,
04381                                                      best_prefix);
04382                 }
04383         }
04384 
04385         /* Try to pick a new prefix if we didn't find one, or if we found an
04386          * abandoned prefix.
04387          */
04388         if ((best_prefix == NULL) || (best_prefix->state == FTS_ABANDONED)) {
04389                 status = pick_v6_prefix(reply);
04390         } else if (best_prefix != NULL) {
04391                 iasubopt_reference(&reply->lease, best_prefix, MDL);
04392                 status = ISC_R_SUCCESS;
04393         }
04394 
04395         /* Pick the abandoned prefix as a last resort. */
04396         if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
04397                 /* I don't see how this is supposed to be done right now. */
04398                 log_error("Reclaiming abandoned prefixes is not yet "
04399                           "supported.  Treating this as an out of space "
04400                           "condition.");
04401                 /* iasubopt_reference(&reply->lease, best_prefix, MDL); */
04402         }
04403 
04404         /* Give up now if we didn't find a prefix. */
04405         if (status != ISC_R_SUCCESS)
04406                 return status;
04407 
04408         if (reply->lease == NULL)
04409                 log_fatal("Impossible condition at %s:%d.", MDL);
04410 
04411         scope = &reply->lease->scope;
04412         group = reply->lease->ipv6_pool->ipv6_pond->group;
04413 
04414         send_pref.lo_addr.len = 16;
04415         memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
04416         send_pref.bits = (int) reply->lease->plen;
04417 
04418       send_pref:
04419         status = reply_process_is_prefixed(reply, scope, group);
04420         if (status != ISC_R_SUCCESS)
04421                 return status;
04422 
04423         status = reply_process_send_prefix(reply, &send_pref);
04424         return status;
04425 }
04426 
04427 /* Once a prefix is found for a client, perform several common functions;
04428  * Calculate and store valid and preferred prefix times, draw client options
04429  * into the option state.
04430  */
04431 static isc_result_t
04432 reply_process_is_prefixed(struct reply_state *reply,
04433                           struct binding_scope **scope, struct group *group)
04434 {
04435         isc_result_t status = ISC_R_SUCCESS;
04436         struct data_string data;
04437         struct option_cache *oc;
04438         struct option_state *tmp_options = NULL;
04439         struct on_star *on_star;
04440         int i;
04441 
04442         /* Initialize values we will cleanup. */
04443         memset(&data, 0, sizeof(data));
04444 
04445         /*
04446          * Find the proper on_star block to use.  We use the
04447          * one in the lease if we have a lease or the one in
04448          * the reply if we don't have a lease because this is
04449          * a static instance
04450          */
04451         if (reply->lease) {
04452                 on_star = &reply->lease->on_star;
04453         } else {
04454                 on_star = &reply->on_star;
04455         }
04456 
04457         /*
04458          * Bring in the root configuration.  We only do this to bring
04459          * in the on * statements, as we didn't have the lease available
04460          * we we did it the first time.
04461          */
04462         option_state_allocate(&tmp_options, MDL);
04463         execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
04464                                     reply->packet->options, tmp_options,
04465                                     &global_scope, root_group, NULL,
04466                                     on_star);
04467         if (tmp_options != NULL) {
04468                 option_state_dereference(&tmp_options, MDL);
04469         }
04470 
04471         /*
04472          * Bring configured options into the root packet level cache - start
04473          * with the lease's closest enclosing group (passed in by the caller
04474          * as 'group').
04475          */
04476         execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
04477                                     reply->packet->options, reply->opt_state,
04478                                     scope, group, root_group, on_star);
04479 
04480         /* Execute statements from class scopes. */
04481         for (i = reply->packet->class_count; i > 0; i--) {
04482                 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
04483                                             reply->packet->options,
04484                                             reply->opt_state, scope,
04485                                             reply->packet->classes[i - 1]->group,
04486                                             group, on_star);
04487         }
04488           
04489         /*
04490          * If there is a host record, over-ride with values configured there,
04491          * without re-evaluating configuration from the previously executed
04492          * group or its common enclosers.
04493          */
04494         if (reply->host != NULL)
04495                 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
04496                                             reply->packet->options,
04497                                             reply->opt_state, scope,
04498                                             reply->host->group, group,
04499                                             on_star);
04500 
04501         /* Determine valid lifetime. */
04502         if (reply->client_valid == 0)
04503                 reply->send_valid = DEFAULT_DEFAULT_LEASE_TIME;
04504         else
04505                 reply->send_valid = reply->client_valid;
04506 
04507         oc = lookup_option(&server_universe, reply->opt_state,
04508                            SV_DEFAULT_LEASE_TIME);
04509         if (oc != NULL) {
04510                 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
04511                                            reply->packet->options,
04512                                            reply->opt_state,
04513                                            scope, oc, MDL) ||
04514                     (data.len != 4)) {
04515                         log_error("reply_process_is_prefixed: unable to "
04516                                   "evaluate default prefix time");
04517                         status = ISC_R_FAILURE;
04518                         goto cleanup;
04519                 }
04520 
04521                 reply->send_valid = getULong(data.data);
04522                 data_string_forget(&data, MDL);
04523         }
04524 
04525         if (reply->client_prefer == 0)
04526                 reply->send_prefer = reply->send_valid;
04527         else
04528                 reply->send_prefer = reply->client_prefer;
04529 
04530         if (reply->send_prefer >= reply->send_valid)
04531                 reply->send_prefer = (reply->send_valid / 2) +
04532                                      (reply->send_valid / 8);
04533 
04534         oc = lookup_option(&server_universe, reply->opt_state,
04535                            SV_PREFER_LIFETIME);
04536         if (oc != NULL) {
04537                 if (!evaluate_option_cache(&data, reply->packet, NULL, NULL,
04538                                            reply->packet->options,
04539                                            reply->opt_state,
04540                                            scope, oc, MDL) ||
04541                     (data.len != 4)) {
04542                         log_error("reply_process_is_prefixed: unable to "
04543                                   "evaluate preferred prefix time");
04544                         status = ISC_R_FAILURE;
04545                         goto cleanup;
04546                 }
04547 
04548                 reply->send_prefer = getULong(data.data);
04549                 data_string_forget(&data, MDL);
04550         }
04551 
04552         /* Note lowest values for later calculation of renew/rebind times. */
04553         if (reply->prefer > reply->send_prefer)
04554                 reply->prefer = reply->send_prefer;
04555 
04556         if (reply->valid > reply->send_valid)
04557                 reply->valid = reply->send_valid;
04558 
04559         /* Perform dynamic prefix related update work. */
04560         if (reply->lease != NULL) {
04561                 /* Cached lifetimes */
04562                 reply->lease->prefer = reply->send_prefer;
04563                 reply->lease->valid = reply->send_valid;
04564 
04565                 /* Advance (or rewind) the valid lifetime. */
04566                 if (reply->buf.reply.msg_type == DHCPV6_REPLY) {
04567                         reply->lease->soft_lifetime_end_time =
04568                                 cur_time + reply->send_valid;
04569                         /* Wait before renew! */
04570                 }
04571 
04572                 status = ia_add_iasubopt(reply->ia, reply->lease, MDL);
04573                 if (status != ISC_R_SUCCESS) {
04574                         log_fatal("reply_process_is_prefixed: Unable to "
04575                                   "attach prefix to new IA_PD: %s",
04576                                   isc_result_totext(status));
04577                 }
04578 
04579                 /*
04580                  * If this is a new prefix, make sure it is attached somewhere.
04581                  */
04582                 if (reply->lease->ia == NULL) {
04583                         ia_reference(&reply->lease->ia, reply->ia, MDL);
04584                 }
04585         }
04586 
04587         /* Bring a copy of the relevant options into the IA_PD scope. */
04588         execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
04589                                     reply->packet->options, reply->reply_ia,
04590                                     scope, group, root_group, NULL);
04591 
04592         /* Execute statements from class scopes. */
04593         for (i = reply->packet->class_count; i > 0; i--) {
04594                 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
04595                                             reply->packet->options,
04596                                             reply->reply_ia, scope,
04597                                             reply->packet->classes[i - 1]->group,
04598                                             group, NULL);
04599         }
04600           
04601         /*
04602          * And bring in host record configuration, if any, but not to overlap
04603          * the previous group or its common enclosers.
04604          */
04605         if (reply->host != NULL)
04606                 execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
04607                                             reply->packet->options,
04608                                             reply->reply_ia, scope,
04609                                             reply->host->group, group, NULL);
04610 
04611       cleanup:
04612         if (data.data != NULL)
04613                 data_string_forget(&data, MDL);
04614 
04615         if (status == ISC_R_SUCCESS)
04616                 reply->client_resources++;
04617 
04618         return status;
04619 }
04620 
04621 /* Simply send an IAPREFIX within the IA_PD scope as described. */
04622 static isc_result_t
04623 reply_process_send_prefix(struct reply_state *reply,
04624                           struct iaddrcidrnet *pref) {
04625         isc_result_t status = ISC_R_SUCCESS;
04626         struct data_string data;
04627 
04628         memset(&data, 0, sizeof(data));
04629 
04630         /* Now append the prefix. */
04631         data.len = IAPREFIX_OFFSET;
04632         if (!buffer_allocate(&data.buffer, data.len, MDL)) {
04633                 log_error("reply_process_send_prefix: out of memory"
04634                           "allocating new IAPREFIX buffer.");
04635                 status = ISC_R_NOMEMORY;
04636                 goto cleanup;
04637         }
04638         data.data = data.buffer->data;
04639 
04640         putULong(data.buffer->data, reply->send_prefer);
04641         putULong(data.buffer->data + 4, reply->send_valid);
04642         data.buffer->data[8] = pref->bits;
04643         memcpy(data.buffer->data + 9, pref->lo_addr.iabuf, 16);
04644 
04645         if (!append_option_buffer(&dhcpv6_universe, reply->reply_ia,
04646                                   data.buffer, data.buffer->data,
04647                                   data.len, D6O_IAPREFIX, 0)) {
04648                 log_error("reply_process_send_prefix: unable "
04649                           "to save IAPREFIX option");
04650                 status = ISC_R_FAILURE;
04651                 goto cleanup;
04652         }
04653 
04654         reply->resources_included = ISC_TRUE;
04655 
04656       cleanup:
04657         if (data.data != NULL)
04658                 data_string_forget(&data, MDL);
04659 
04660         return status;
04661 }
04662 
04663 /* Choose the better of two prefixes. */
04664 static struct iasubopt *
04665 prefix_compare(struct reply_state *reply,
04666                struct iasubopt *alpha, struct iasubopt *beta) {
04667         if (alpha == NULL)
04668                 return beta;
04669         if (beta == NULL)
04670                 return alpha;
04671 
04672         if (reply->preflen >= 0) {
04673                 if ((alpha->plen == reply->preflen) &&
04674                     (beta->plen != reply->preflen))
04675                         return alpha;
04676                 if ((beta->plen == reply->preflen) &&
04677                     (alpha->plen != reply->preflen))
04678                         return beta;
04679         }
04680 
04681         switch(alpha->state) {
04682               case FTS_ACTIVE:
04683                 switch(beta->state) {
04684                       case FTS_ACTIVE:
04685                         /* Choose the prefix with the longest lifetime (most
04686                          * likely the most recently allocated).
04687                          */
04688                         if (alpha->hard_lifetime_end_time < 
04689                             beta->hard_lifetime_end_time)
04690                                 return beta;
04691                         else
04692                                 return alpha;
04693 
04694                       case FTS_EXPIRED:
04695                       case FTS_ABANDONED:
04696                         return alpha;
04697 
04698                       default:
04699                         log_fatal("Impossible condition at %s:%d.", MDL);
04700                 }
04701                 break;
04702 
04703               case FTS_EXPIRED:
04704                 switch (beta->state) {
04705                       case FTS_ACTIVE:
04706                         return beta;
04707 
04708                       case FTS_EXPIRED:
04709                         /* Choose the most recently expired prefix. */
04710                         if (alpha->hard_lifetime_end_time <
04711                             beta->hard_lifetime_end_time)
04712                                 return beta;
04713                         else if ((alpha->hard_lifetime_end_time ==
04714                                   beta->hard_lifetime_end_time) &&
04715                                  (alpha->soft_lifetime_end_time <
04716                                   beta->soft_lifetime_end_time))
04717                                 return beta;
04718                         else
04719                                 return alpha;
04720 
04721                       case FTS_ABANDONED:
04722                         return alpha;
04723 
04724                       default:
04725                         log_fatal("Impossible condition at %s:%d.", MDL);
04726                 }
04727                 break;
04728 
04729               case FTS_ABANDONED:
04730                 switch (beta->state) {
04731                       case FTS_ACTIVE:
04732                       case FTS_EXPIRED:
04733                         return alpha;
04734 
04735                       case FTS_ABANDONED:
04736                         /* Choose the prefix that was abandoned longest ago. */
04737                         if (alpha->hard_lifetime_end_time <
04738                             beta->hard_lifetime_end_time)
04739                                 return alpha;
04740 
04741                       default:
04742                         log_fatal("Impossible condition at %s:%d.", MDL);
04743                 }
04744                 break;
04745 
04746               default:
04747                 log_fatal("Impossible condition at %s:%d.", MDL);
04748         }
04749 
04750         log_fatal("Triple impossible condition at %s:%d.", MDL);
04751         return NULL;
04752 }
04753 
04754 /*
04755  * Solicit is how a client starts requesting addresses.
04756  *
04757  * If the client asks for rapid commit, and we support it, we will 
04758  * allocate the addresses and reply.
04759  *
04760  * Otherwise we will send an advertise message.
04761  */
04762 
04763 static void
04764 dhcpv6_solicit(struct data_string *reply_ret, struct packet *packet) {
04765         struct data_string client_id;
04766 
04767         TRACE(DHCPD_6_SOLICIT_START());
04768 
04769         /* 
04770          * Validate our input.
04771          */
04772         if (!valid_client_msg(packet, &client_id)) {
04773                 return;
04774         }
04775 
04776         lease_to_client(reply_ret, packet, &client_id, NULL);
04777 
04778         /*
04779          * Clean up.
04780          */
04781         data_string_forget(&client_id, MDL);
04782 
04783         TRACE(DHCPD_6_SOLICIT_DONE());
04784 }
04785 
04786 /*
04787  * Request is how a client actually requests addresses.
04788  *
04789  * Very similar to Solicit handling, except the server DUID is required.
04790  */
04791 
04792 static void
04793 dhcpv6_request(struct data_string *reply_ret, struct packet *packet) {
04794         struct data_string client_id;
04795         struct data_string server_id;
04796 
04797         TRACE(DHCPD_6_REQUEST_START());
04798 
04799         /*
04800          * Validate our input.
04801          */
04802         if (!valid_client_resp(packet, &client_id, &server_id)) {
04803                 return;
04804         }
04805 
04806         /*
04807          * Issue our lease.
04808          */
04809         lease_to_client(reply_ret, packet, &client_id, &server_id);
04810 
04811         /*
04812          * Cleanup.
04813          */
04814         data_string_forget(&client_id, MDL);
04815         data_string_forget(&server_id, MDL);
04816 
04817         TRACE(DHCPD_6_REQUEST_DONE());
04818 }
04819 
04820 /* Find a DHCPv6 packet's shared network from hints in the packet.
04821  */
04822 static isc_result_t
04823 shared_network_from_packet6(struct shared_network **shared,
04824                             struct packet *packet)
04825 {
04826         const struct packet *chk_packet;
04827         const struct in6_addr *link_addr, *first_link_addr;
04828         struct iaddr tmp_addr;
04829         struct subnet *subnet;
04830         isc_result_t status;
04831 
04832         if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
04833                 return DHCP_R_INVALIDARG;
04834 
04835         /*
04836          * First, find the link address where the packet from the client
04837          * first appeared (if this packet was relayed).
04838          */
04839         first_link_addr = NULL;
04840         chk_packet = packet->dhcpv6_container_packet;
04841         while (chk_packet != NULL) {
04842                 link_addr = &chk_packet->dhcpv6_link_address;
04843                 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
04844                     !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
04845                         first_link_addr = link_addr;
04846                         break;
04847                 }
04848                 chk_packet = chk_packet->dhcpv6_container_packet;
04849         }
04850 
04851         /*
04852          * If there is a relayed link address, find the subnet associated
04853          * with that, and use that to get the appropriate
04854          * shared_network.
04855          */
04856         if (first_link_addr != NULL) {
04857                 tmp_addr.len = sizeof(*first_link_addr);
04858                 memcpy(tmp_addr.iabuf,
04859                        first_link_addr, sizeof(*first_link_addr));
04860                 subnet = NULL;
04861                 if (!find_subnet(&subnet, tmp_addr, MDL)) {
04862                         log_debug("No subnet found for link-address %s.",
04863                                   piaddr(tmp_addr));
04864                         return ISC_R_NOTFOUND;
04865                 }
04866                 status = shared_network_reference(shared,
04867                                                   subnet->shared_network, MDL);
04868                 subnet_dereference(&subnet, MDL);
04869 
04870         /*
04871          * If there is no link address, we will use the interface
04872          * that this packet came in on to pick the shared_network.
04873          */
04874         } else if (packet->interface != NULL) {
04875                 status = shared_network_reference(shared,
04876                                          packet->interface->shared_network,
04877                                          MDL);
04878                 if (packet->dhcpv6_container_packet != NULL) {
04879                         log_info("[L2 Relay] No link address in relay packet "
04880                                  "assuming L2 relay and using receiving "
04881                                  "interface");
04882                 }
04883 
04884         } else {
04885                 /*
04886                  * We shouldn't be able to get here but if there is no link
04887                  * address and no interface we don't know where to get the
04888                  * pool from log an error and return an error.
04889                  */
04890                 log_error("No interface and no link address " 
04891                           "can't determine pool");
04892                 status = DHCP_R_INVALIDARG;
04893         }
04894 
04895         return status;
04896 }
04897 
04898 /*
04899  * When a client thinks it might be on a new link, it sends a 
04900  * Confirm message.
04901  *
04902  * From RFC3315 section 18.2.2:
04903  *
04904  *   When the server receives a Confirm message, the server determines
04905  *   whether the addresses in the Confirm message are appropriate for the
04906  *   link to which the client is attached.  If all of the addresses in the
04907  *   Confirm message pass this test, the server returns a status of
04908  *   Success.  If any of the addresses do not pass this test, the server
04909  *   returns a status of NotOnLink.  If the server is unable to perform
04910  *   this test (for example, the server does not have information about
04911  *   prefixes on the link to which the client is connected), or there were
04912  *   no addresses in any of the IAs sent by the client, the server MUST
04913  *   NOT send a reply to the client.
04914  */
04915 
04916 static void
04917 dhcpv6_confirm(struct data_string *reply_ret, struct packet *packet) {
04918         struct shared_network *shared;
04919         struct subnet *subnet;
04920         struct option_cache *ia, *ta, *oc;
04921         struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
04922         struct option_state *cli_enc_opt_state, *opt_state;
04923         struct iaddr cli_addr;
04924         int pass;
04925         isc_boolean_t inappropriate, has_addrs;
04926         char reply_data[65536];
04927         struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
04928         int reply_ofs = (int)(offsetof(struct dhcpv6_packet, options));
04929 
04930         TRACE(DHCPD_6_CONFIRM_START());
04931 
04932         /* 
04933          * Basic client message validation.
04934          */
04935         memset(&client_id, 0, sizeof(client_id));
04936         if (!valid_client_msg(packet, &client_id)) {
04937                 return;
04938         }
04939 
04940         /*
04941          * Do not process Confirms that do not have IA's we do not recognize.
04942          */
04943         ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
04944         ta = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_TA);
04945         if ((ia == NULL) && (ta == NULL))
04946                 return;
04947 
04948         /*
04949          * IA_PD's are simply ignored.
04950          */
04951         delete_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
04952 
04953         /* 
04954          * Bit of variable initialization.
04955          */
04956         opt_state = cli_enc_opt_state = NULL;
04957         memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
04958         memset(&iaaddr, 0, sizeof(iaaddr));
04959         memset(&packet_oro, 0, sizeof(packet_oro));
04960 
04961         /* Determine what shared network the client is connected to.  We
04962          * must not respond if we don't have any information about the
04963          * network the client is on.
04964          */
04965         shared = NULL;
04966         if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
04967             (shared == NULL))
04968                 goto exit;
04969 
04970         /* If there are no recorded subnets, then we have no
04971          * information about this subnet - ignore Confirms.
04972          */
04973         subnet = shared->subnets;
04974         if (subnet == NULL)
04975                 goto exit;
04976 
04977         /* Are the addresses in all the IA's appropriate for that link? */
04978         has_addrs = inappropriate = ISC_FALSE;
04979         pass = D6O_IA_NA;
04980         while(!inappropriate) {
04981                 /* If we've reached the end of the IA_NA pass, move to the
04982                  * IA_TA pass.
04983                  */
04984                 if ((pass == D6O_IA_NA) && (ia == NULL)) {
04985                         pass = D6O_IA_TA;
04986                         ia = ta;
04987                 }
04988 
04989                 /* If we've reached the end of all passes, we're done. */
04990                 if (ia == NULL)
04991                         break;
04992 
04993                 if (((pass == D6O_IA_NA) &&
04994                      !get_encapsulated_IA_state(&cli_enc_opt_state,
04995                                                 &cli_enc_opt_data,
04996                                                 packet, ia, IA_NA_OFFSET)) ||
04997                     ((pass == D6O_IA_TA) &&
04998                      !get_encapsulated_IA_state(&cli_enc_opt_state,
04999                                                 &cli_enc_opt_data,
05000                                                 packet, ia, IA_TA_OFFSET))) {
05001                         goto exit;
05002                 }
05003 
05004                 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state,
05005                                    D6O_IAADDR);
05006 
05007                 for ( ; oc != NULL ; oc = oc->next) {
05008                         if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL,
05009                                                    packet->options, NULL,
05010                                                    &global_scope, oc, MDL) ||
05011                             (iaaddr.len < IAADDR_OFFSET)) {
05012                                 log_error("dhcpv6_confirm: "
05013                                           "error evaluating IAADDR.");
05014                                 goto exit;
05015                         }
05016 
05017                         /* Copy out the IPv6 address for processing. */
05018                         cli_addr.len = 16;
05019                         memcpy(cli_addr.iabuf, iaaddr.data, 16);
05020 
05021                         data_string_forget(&iaaddr, MDL);
05022 
05023                         /* Record that we've processed at least one address. */
05024                         has_addrs = ISC_TRUE;
05025 
05026                         /* Find out if any subnets cover this address. */
05027                         for (subnet = shared->subnets ; subnet != NULL ;
05028                              subnet = subnet->next_sibling) {
05029                                 if (addr_eq(subnet_number(cli_addr,
05030                                                           subnet->netmask),
05031                                             subnet->net))
05032                                         break;
05033                         }
05034 
05035                         /* If we reach the end of the subnet list, and no
05036                          * subnet matches the client address, then it must
05037                          * be inappropriate to the link (so far as our
05038                          * configuration says).  Once we've found one
05039                          * inappropriate address, there is no reason to
05040                          * continue searching.
05041                          */
05042                         if (subnet == NULL) {
05043                                 inappropriate = ISC_TRUE;
05044                                 break;
05045                         }
05046                 }
05047 
05048                 option_state_dereference(&cli_enc_opt_state, MDL);
05049                 data_string_forget(&cli_enc_opt_data, MDL);
05050 
05051                 /* Advance to the next IA_*. */
05052                 ia = ia->next;
05053         }
05054 
05055         /* If the client supplied no addresses, do not reply. */
05056         if (!has_addrs)
05057                 goto exit;
05058 
05059         /* 
05060          * Set up reply.
05061          */
05062         if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
05063                 goto exit;
05064         }
05065 
05066         /* 
05067          * Set our status.
05068          */
05069         if (inappropriate) {
05070                 if (!set_status_code(STATUS_NotOnLink, 
05071                                      "Some of the addresses are not on link.",
05072                                      opt_state)) {
05073                         goto exit;
05074                 }
05075         } else {
05076                 if (!set_status_code(STATUS_Success, 
05077                                      "All addresses still on link.",
05078                                      opt_state)) {
05079                         goto exit;
05080                 }
05081         }
05082 
05083         /* 
05084          * Only one option: add it.
05085          */
05086         reply_ofs += store_options6(reply_data+reply_ofs,
05087                                     sizeof(reply_data)-reply_ofs, 
05088                                     opt_state, packet,
05089                                     required_opts, &packet_oro);
05090 
05091         /* 
05092          * Return our reply to the caller.
05093          */
05094         reply_ret->len = reply_ofs;
05095         reply_ret->buffer = NULL;
05096         if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
05097                 log_fatal("No memory to store reply.");
05098         }
05099         reply_ret->data = reply_ret->buffer->data;
05100         memcpy(reply_ret->buffer->data, reply, reply_ofs);
05101 
05102 exit:
05103         /* Cleanup any stale data strings. */
05104         if (cli_enc_opt_data.buffer != NULL)
05105                 data_string_forget(&cli_enc_opt_data, MDL);
05106         if (iaaddr.buffer != NULL)
05107                 data_string_forget(&iaaddr, MDL);
05108         if (client_id.buffer != NULL)
05109                 data_string_forget(&client_id, MDL);
05110         if (packet_oro.buffer != NULL)
05111                 data_string_forget(&packet_oro, MDL);
05112 
05113         /* Release any stale option states. */
05114         if (cli_enc_opt_state != NULL)
05115                 option_state_dereference(&cli_enc_opt_state, MDL);
05116         if (opt_state != NULL)
05117                 option_state_dereference(&opt_state, MDL);
05118 
05119         TRACE(DHCPD_6_CONFIRM_DONE());
05120 }
05121 
05122 /*
05123  * Renew is when a client wants to extend its lease/prefix, at time T1.
05124  *
05125  * We handle this the same as if the client wants a new lease/prefix,
05126  * except for the error code of when addresses don't match.
05127  */
05128 
05129 static void
05130 dhcpv6_renew(struct data_string *reply, struct packet *packet) {
05131         struct data_string client_id;
05132         struct data_string server_id;
05133 
05134         TRACE(DHCPD_6_RENEW_START());
05135 
05136         /* 
05137          * Validate the request.
05138          */
05139         if (!valid_client_resp(packet, &client_id, &server_id)) {
05140                 return;
05141         }
05142 
05143         /*
05144          * Renew our lease.
05145          */
05146         lease_to_client(reply, packet, &client_id, &server_id);
05147 
05148         /*
05149          * Cleanup.
05150          */
05151         data_string_forget(&server_id, MDL);
05152         data_string_forget(&client_id, MDL);
05153 
05154         TRACE(DHCPD_6_RENEW_DONE());
05155 }
05156 
05157 /*
05158  * Rebind is when a client wants to extend its lease, at time T2.
05159  *
05160  * We handle this the same as if the client wants a new lease, except
05161  * for the error code of when addresses don't match.
05162  */
05163 
05164 static void
05165 dhcpv6_rebind(struct data_string *reply, struct packet *packet) {
05166         struct data_string client_id;
05167 
05168         TRACE(DHCPD_6_REBIND_START());
05169 
05170         if (!valid_client_msg(packet, &client_id)) {
05171                 return;
05172         }
05173 
05174         lease_to_client(reply, packet, &client_id, NULL);
05175 
05176         data_string_forget(&client_id, MDL);
05177 
05178         TRACE(DHCPD_6_REBIND_DONE());
05179 }
05180 
05181 static void
05182 ia_na_match_decline(const struct data_string *client_id,
05183                     const struct data_string *iaaddr,
05184                     struct iasubopt *lease)
05185 {
05186         char tmp_addr[INET6_ADDRSTRLEN];
05187 
05188         log_error("Client %s reports address %s is "
05189                   "already in use by another host!",
05190                   print_hex_1(client_id->len, client_id->data, 60),
05191                   inet_ntop(AF_INET6, iaaddr->data, 
05192                             tmp_addr, sizeof(tmp_addr)));
05193         if (lease != NULL) {
05194                 decline_lease6(lease->ipv6_pool, lease);
05195                 lease->ia->cltt = cur_time;
05196                 write_ia(lease->ia);
05197         }
05198 }
05199 
05200 static void
05201 ia_na_nomatch_decline(const struct data_string *client_id,
05202                       const struct data_string *iaaddr,
05203                       u_int32_t *ia_na_id,
05204                       struct packet *packet,
05205                       char *reply_data,
05206                       int *reply_ofs,
05207                       int reply_len)
05208 {
05209         char tmp_addr[INET6_ADDRSTRLEN];
05210         struct option_state *host_opt_state;
05211         int len;
05212 
05213         log_info("Client %s declines address %s, which is not offered to it.",
05214                  print_hex_1(client_id->len, client_id->data, 60),
05215                  inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
05216 
05217         /*
05218          * Create state for this IA_NA.
05219          */
05220         host_opt_state = NULL;
05221         if (!option_state_allocate(&host_opt_state, MDL)) {
05222                 log_error("ia_na_nomatch_decline: out of memory "
05223                           "allocating option_state.");
05224                 goto exit;
05225         }
05226 
05227         if (!set_status_code(STATUS_NoBinding, "Decline for unknown address.",
05228                              host_opt_state)) {
05229                 goto exit;
05230         }
05231 
05232         /*
05233          * Insure we have enough space
05234          */
05235         if (reply_len < (*reply_ofs + 16)) {
05236                 log_error("ia_na_nomatch_decline: "
05237                           "out of space for reply packet.");
05238                 goto exit;
05239         }
05240 
05241         /*
05242          * Put our status code into the reply packet.
05243          */
05244         len = store_options6(reply_data+(*reply_ofs)+16,
05245                              reply_len-(*reply_ofs)-16,
05246                              host_opt_state, packet,
05247                              required_opts_STATUS_CODE, NULL);
05248 
05249         /*
05250          * Store the non-encapsulated option data for this 
05251          * IA_NA into our reply packet. Defined in RFC 3315, 
05252          * section 22.4.  
05253          */
05254         /* option number */
05255         putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
05256         /* option length */
05257         putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
05258         /* IA_NA, copied from the client */
05259         memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
05260         /* t1 and t2, odd that we need them, but here it is */
05261         putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
05262         putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
05263 
05264         /*
05265          * Get ready for next IA_NA.
05266          */
05267         *reply_ofs += (len + 16);
05268 
05269 exit:
05270         option_state_dereference(&host_opt_state, MDL);
05271 }
05272 
05273 static void
05274 iterate_over_ia_na(struct data_string *reply_ret, 
05275                    struct packet *packet,
05276                    const struct data_string *client_id,
05277                    const struct data_string *server_id,
05278                    const char *packet_type,
05279                    void (*ia_na_match)(),
05280                    void (*ia_na_nomatch)())
05281 {
05282         struct option_state *opt_state;
05283         struct host_decl *packet_host;
05284         struct option_cache *ia;
05285         struct option_cache *oc;
05286         /* cli_enc_... variables come from the IA_NA/IA_TA options */
05287         struct data_string cli_enc_opt_data;
05288         struct option_state *cli_enc_opt_state;
05289         struct host_decl *host;
05290         struct option_state *host_opt_state;
05291         struct data_string iaaddr;
05292         struct data_string fixed_addr;
05293         char reply_data[65536];
05294         struct dhcpv6_packet *reply = (struct dhcpv6_packet *)reply_data;
05295         int reply_ofs = (int)(offsetof(struct dhcpv6_packet, options));
05296         char status_msg[32];
05297         struct iasubopt *lease;
05298         struct ia_xx *existing_ia_na;
05299         int i;
05300         struct data_string key;
05301         u_int32_t iaid;
05302 
05303         /*
05304          * Initialize to empty values, in case we have to exit early.
05305          */
05306         opt_state = NULL;
05307         memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
05308         cli_enc_opt_state = NULL;
05309         memset(&iaaddr, 0, sizeof(iaaddr));
05310         memset(&fixed_addr, 0, sizeof(fixed_addr));
05311         host_opt_state = NULL;
05312         lease = NULL;
05313 
05314         /* 
05315          * Find the host record that matches from the packet, if any.
05316          */
05317         packet_host = NULL;
05318         if (!find_hosts_by_uid(&packet_host, 
05319                                client_id->data, client_id->len, MDL)) {
05320                 packet_host = NULL;
05321                 /* 
05322                  * Note: In general, we don't expect a client to provide
05323                  *       enough information to match by option for these
05324                  *       types of messages, but if we don't have a UID
05325                  *       match we can check anyway.
05326                  */
05327                 if (!find_hosts_by_option(&packet_host, 
05328                                           packet, packet->options, MDL)) {
05329                         packet_host = NULL;
05330 
05331                         if (!find_hosts_by_duid_chaddr(&packet_host,
05332                                                        client_id))
05333                                 packet_host = NULL;
05334                 }
05335         }
05336 
05337         /* 
05338          * Set our reply information.
05339          */
05340         reply->msg_type = DHCPV6_REPLY;
05341         memcpy(reply->transaction_id, packet->dhcpv6_transaction_id, 
05342                sizeof(reply->transaction_id));
05343 
05344         /*
05345          * Build our option state for reply.
05346          */
05347         opt_state = NULL;
05348         if (!option_state_allocate(&opt_state, MDL)) {
05349                 log_error("iterate_over_ia_na: no memory for option_state.");
05350                 goto exit;
05351         }
05352         execute_statements_in_scope(NULL, packet, NULL, NULL, 
05353                                     packet->options, opt_state, 
05354                                     &global_scope, root_group, NULL, NULL);
05355 
05356         /* 
05357          * RFC 3315, section 18.2.7 tells us which options to include.
05358          */
05359         oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
05360         if (oc == NULL) {
05361                 if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL, 
05362                                         (unsigned char *)server_duid.data, 
05363                                         server_duid.len, D6O_SERVERID, 0)) {
05364                         log_error("iterate_over_ia_na: "
05365                                   "error saving server identifier.");
05366                         goto exit;
05367                 }
05368         }
05369 
05370         if (!save_option_buffer(&dhcpv6_universe, opt_state, 
05371                                 client_id->buffer, 
05372                                 (unsigned char *)client_id->data,
05373                                 client_id->len, 
05374                                 D6O_CLIENTID, 0)) {
05375                 log_error("iterate_over_ia_na: "
05376                           "error saving client identifier.");
05377                 goto exit;
05378         }
05379 
05380         /* reject unicast message, unless we set unicast option */
05381         if ((packet->unicast == ISC_TRUE) && !is_unicast_option_defined()) {
05382                 /*
05383                  * RFC3315 section 18.2.6 (Release):
05384                  *
05385                  * When the server receives a Release message via unicast from a client
05386                  * to which the server has not sent a unicast option, the server
05387                  * discards the Release message and responds with a Reply message
05388                  * containing a Status Code option with value UseMulticast, a Server
05389                  * Identifier option containing the server's DUID, the Client Identifier
05390                  * option from the client message, and no other options.
05391                  *
05392                  * Section 18.2.7 (Decline):
05393                  *
05394                  * When the server receives a Decline message via unicast from a client
05395                  * to which the server has not sent a unicast option, the server
05396                  * discards the Decline message and responds with a Reply message
05397                  * containing a Status Code option with the value UseMulticast, a Server
05398                  * Identifier option containing the server's DUID, the Client Identifier
05399                  * option from the client message, and no other options.
05400                  */
05401                 snprintf(status_msg, sizeof(status_msg),
05402                                  "%s received unicast.", packet_type);
05403                 if (!set_status_code(STATUS_UseMulticast, status_msg, opt_state)) {
05404                         goto exit;
05405                 }
05406 
05407                 /*
05408                  * Produce an reply that includes only:
05409                  *
05410                  * Status code.
05411                  * Server DUID.
05412                  * Client DUID.
05413                  */
05414                 reply_ofs += store_options6(reply_data+reply_ofs,
05415                                     sizeof(reply_data)-reply_ofs,
05416                                     opt_state, packet,
05417                                     required_opts_NAA, NULL);
05418 
05419                 goto return_reply;
05420         } else {
05421                 snprintf(status_msg, sizeof(status_msg), "%s received.", packet_type);
05422                 if (!set_status_code(STATUS_Success, status_msg, opt_state)) {
05423                         goto exit;
05424                 }
05425 
05426                 /*
05427                  * Add our options that are not associated with any IA_NA or IA_TA.
05428                  */
05429                 reply_ofs += store_options6(reply_data+reply_ofs,
05430                                             sizeof(reply_data)-reply_ofs,
05431                                             opt_state, packet,
05432                                             required_opts, NULL);
05433         }
05434 
05435         /*
05436          * Loop through the IA_NA reported by the client, and deal with
05437          * addresses reported as already in use.
05438          */
05439         for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_NA);
05440              ia != NULL; ia = ia->next) {
05441 
05442                 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
05443                                                &cli_enc_opt_data,
05444                                                packet, ia, IA_NA_OFFSET)) {
05445                         goto exit;
05446                 }
05447 
05448                 iaid = getULong(cli_enc_opt_data.data);
05449 
05450                 /* 
05451                  * XXX: It is possible that we can get multiple addresses
05452                  *      sent by the client. We don't send multiple 
05453                  *      addresses, so this indicates a client error. 
05454                  *      We should check for multiple IAADDR options, log
05455                  *      if found, and set as an error.
05456                  */
05457                 oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state, 
05458                                    D6O_IAADDR);
05459                 if (oc == NULL) {
05460                         /* no address given for this IA, ignore */
05461                         option_state_dereference(&cli_enc_opt_state, MDL);
05462                         data_string_forget(&cli_enc_opt_data, MDL);
05463                         continue;
05464                 }
05465 
05466                 memset(&iaaddr, 0, sizeof(iaaddr));
05467                 if (!evaluate_option_cache(&iaaddr, packet, NULL, NULL, 
05468                                            packet->options, NULL,
05469                                            &global_scope, oc, MDL)) {
05470                         log_error("iterate_over_ia_na: "
05471                                   "error evaluating IAADDR.");
05472                         goto exit;
05473                 }
05474 
05475                 /* 
05476                  * Now we need to figure out which host record matches
05477                  * this IA_NA and IAADDR (encapsulated option contents
05478                  * matching a host record by option).
05479                  *
05480                  * XXX: We don't currently track IA_NA separately, but
05481                  *      we will need to do this!
05482                  */
05483                 host = NULL;
05484                 if (!find_hosts_by_option(&host, packet, 
05485                                           cli_enc_opt_state, MDL)) { 
05486                         if (packet_host != NULL) {
05487                                 host = packet_host;
05488                         } else {
05489                                 host = NULL;
05490                         }
05491                 }
05492                 while (host != NULL) {
05493                         if (host->fixed_addr != NULL) {
05494                                 if (!evaluate_option_cache(&fixed_addr, NULL, 
05495                                                            NULL, NULL, NULL, 
05496                                                            NULL, &global_scope,
05497                                                            host->fixed_addr, 
05498                                                            MDL)) {
05499                                         log_error("iterate_over_ia_na: error "
05500                                                   "evaluating host address.");
05501                                         goto exit;
05502                                 }
05503                                 if ((iaaddr.len >= 16) &&
05504                                     !memcmp(fixed_addr.data, iaaddr.data, 16)) {
05505                                         data_string_forget(&fixed_addr, MDL);
05506                                         break;
05507                                 }
05508                                 data_string_forget(&fixed_addr, MDL);
05509                         }
05510                         host = host->n_ipaddr;
05511                 }
05512 
05513                 if ((host == NULL) && (iaaddr.len >= IAADDR_OFFSET)) {
05514                         /*
05515                          * Find existing IA_NA.
05516                          */
05517                         if (ia_make_key(&key, iaid, 
05518                                         (char *)client_id->data,
05519                                         client_id->len, 
05520                                         MDL) != ISC_R_SUCCESS) {
05521                                 log_fatal("iterate_over_ia_na: no memory for "
05522                                           "key.");
05523                         }
05524 
05525                         existing_ia_na = NULL;
05526                         if (ia_hash_lookup(&existing_ia_na, ia_na_active, 
05527                                            (unsigned char *)key.data, 
05528                                            key.len, MDL)) {
05529                                 /* 
05530                                  * Make sure this address is in the IA_NA.
05531                                  */
05532                                 for (i=0; i<existing_ia_na->num_iasubopt; i++) {
05533                                         struct iasubopt *tmp;
05534                                         struct in6_addr *in6_addr;
05535 
05536                                         tmp = existing_ia_na->iasubopt[i];
05537                                         in6_addr = &tmp->addr;
05538                                         if (memcmp(in6_addr, 
05539                                                    iaaddr.data, 16) == 0) {
05540                                                 iasubopt_reference(&lease,
05541                                                                    tmp, MDL);
05542                                                 break;
05543                                         }
05544                                 }
05545                         }
05546 
05547                         data_string_forget(&key, MDL);
05548                 }
05549 
05550                 if ((host != NULL) || (lease != NULL)) {
05551                         ia_na_match(client_id, &iaaddr, lease);
05552                 } else {
05553                         ia_na_nomatch(client_id, &iaaddr, 
05554                                       (u_int32_t *)cli_enc_opt_data.data, 
05555                                       packet, reply_data, &reply_ofs, 
05556                                       sizeof(reply_data));
05557                 }
05558 
05559                 if (lease != NULL) {
05560                         iasubopt_dereference(&lease, MDL);
05561                 }
05562 
05563                 data_string_forget(&iaaddr, MDL);
05564                 option_state_dereference(&cli_enc_opt_state, MDL);
05565                 data_string_forget(&cli_enc_opt_data, MDL);
05566         }
05567 
05568         /* 
05569          * Return our reply to the caller.
05570          */
05571 return_reply:
05572         reply_ret->len = reply_ofs;
05573         reply_ret->buffer = NULL;
05574         if (!buffer_allocate(&reply_ret->buffer, reply_ofs, MDL)) {
05575                 log_fatal("No memory to store reply.");
05576         }
05577         reply_ret->data = reply_ret->buffer->data;
05578         memcpy(reply_ret->buffer->data, reply, reply_ofs);
05579 
05580 exit:
05581         if (lease != NULL) {
05582                 iasubopt_dereference(&lease, MDL);
05583         }
05584         if (host_opt_state != NULL) {
05585                 option_state_dereference(&host_opt_state, MDL);
05586         }
05587         if (fixed_addr.buffer != NULL) {
05588                 data_string_forget(&fixed_addr, MDL);
05589         }
05590         if (iaaddr.buffer != NULL) {
05591                 data_string_forget(&iaaddr, MDL);
05592         }
05593         if (cli_enc_opt_state != NULL) {
05594                 option_state_dereference(&cli_enc_opt_state, MDL);
05595         }
05596         if (cli_enc_opt_data.buffer != NULL) {
05597                 data_string_forget(&cli_enc_opt_data, MDL);
05598         }
05599         if (opt_state != NULL) {
05600                 option_state_dereference(&opt_state, MDL);
05601         }
05602 }
05603 
05604 /*
05605  * Decline means a client has detected that something else is using an
05606  * address we gave it.
05607  *
05608  * Since we're only dealing with fixed leases for now, there's not
05609  * much we can do, other that log the occurrence.
05610  * 
05611  * When we start issuing addresses from pools, then we will have to
05612  * record our declined addresses and issue another. In general with
05613  * IPv6 there is no worry about DoS by clients exhausting space, but
05614  * we still need to be aware of this possibility.
05615  */
05616 
05617 /* TODO: IA_TA */
05618 static void
05619 dhcpv6_decline(struct data_string *reply, struct packet *packet) {
05620         struct data_string client_id;
05621         struct data_string server_id;
05622 
05623         TRACE(DHCPD_6_DECLINE_START());
05624 
05625         /* 
05626          * Validate our input.
05627          */
05628         if (!valid_client_resp(packet, &client_id, &server_id)) {
05629                 return;
05630         }
05631 
05632         /*
05633          * Undefined for IA_PD.
05634          */
05635         delete_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
05636 
05637         /*
05638          * And operate on each IA_NA in this packet.
05639          */
05640         iterate_over_ia_na(reply, packet, &client_id, &server_id, "Decline", 
05641                            ia_na_match_decline, ia_na_nomatch_decline);
05642 
05643         data_string_forget(&server_id, MDL);
05644         data_string_forget(&client_id, MDL);
05645 
05646         TRACE(DHCPD_6_DECLINE_DONE());
05647 }
05648 
05649 static void
05650 ia_na_match_release(const struct data_string *client_id,
05651                     const struct data_string *iaaddr,
05652                     struct iasubopt *lease)
05653 {
05654         char tmp_addr[INET6_ADDRSTRLEN];
05655 
05656         log_info("Client %s releases address %s",
05657                  print_hex_1(client_id->len, client_id->data, 60),
05658                  inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
05659         if (lease != NULL) {
05660                 release_lease6(lease->ipv6_pool, lease);
05661                 lease->ia->cltt = cur_time;
05662                 write_ia(lease->ia);
05663         }
05664 }
05665 
05666 static void
05667 ia_na_nomatch_release(const struct data_string *client_id,
05668                       const struct data_string *iaaddr,
05669                       u_int32_t *ia_na_id,
05670                       struct packet *packet,
05671                       char *reply_data,
05672                       int *reply_ofs,
05673                       int reply_len)
05674 {
05675         char tmp_addr[INET6_ADDRSTRLEN];
05676         struct option_state *host_opt_state;
05677         int len;
05678 
05679         log_info("Client %s releases address %s, which is not leased to it.",
05680                  print_hex_1(client_id->len, client_id->data, 60),
05681                  inet_ntop(AF_INET6, iaaddr->data, tmp_addr, sizeof(tmp_addr)));
05682 
05683         /*
05684          * Create state for this IA_NA.
05685          */
05686         host_opt_state = NULL;
05687         if (!option_state_allocate(&host_opt_state, MDL)) {
05688                 log_error("ia_na_nomatch_release: out of memory "
05689                           "allocating option_state.");
05690                 goto exit;
05691         }
05692 
05693         if (!set_status_code(STATUS_NoBinding, 
05694                              "Release for non-leased address.",
05695                              host_opt_state)) {
05696                 goto exit;
05697         }
05698 
05699         /*
05700          * Insure we have enough space
05701          */
05702         if (reply_len < (*reply_ofs + 16)) {
05703                 log_error("ia_na_nomatch_release: "
05704                           "out of space for reply packet.");
05705                 goto exit;
05706         }
05707 
05708         /*
05709          * Put our status code into the reply packet.
05710          */
05711         len = store_options6(reply_data+(*reply_ofs)+16,
05712                              reply_len-(*reply_ofs)-16,
05713                              host_opt_state, packet,
05714                              required_opts_STATUS_CODE, NULL);
05715 
05716         /*
05717          * Store the non-encapsulated option data for this 
05718          * IA_NA into our reply packet. Defined in RFC 3315, 
05719          * section 22.4.  
05720          */
05721         /* option number */
05722         putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_NA);
05723         /* option length */
05724         putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
05725         /* IA_NA, copied from the client */
05726         memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
05727         /* t1 and t2, odd that we need them, but here it is */
05728         putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
05729         putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
05730 
05731         /*
05732          * Get ready for next IA_NA.
05733          */
05734         *reply_ofs += (len + 16);
05735 
05736 exit:
05737         option_state_dereference(&host_opt_state, MDL);
05738 }
05739 
05740 static void
05741 ia_pd_match_release(const struct data_string *client_id,
05742                     const struct data_string *iapref,
05743                     struct iasubopt *prefix)
05744 {
05745         char tmp_addr[INET6_ADDRSTRLEN];
05746 
05747         log_info("Client %s releases prefix %s/%u",
05748                  print_hex_1(client_id->len, client_id->data, 60),
05749                  inet_ntop(AF_INET6, iapref->data + 9,
05750                            tmp_addr, sizeof(tmp_addr)),
05751                  (unsigned) getUChar(iapref->data + 8));
05752         if (prefix != NULL) {
05753                 release_lease6(prefix->ipv6_pool, prefix);
05754                 prefix->ia->cltt = cur_time;
05755                 write_ia(prefix->ia);
05756         }
05757 }
05758 
05759 static void
05760 ia_pd_nomatch_release(const struct data_string *client_id,
05761                       const struct data_string *iapref,
05762                       u_int32_t *ia_pd_id,
05763                       struct packet *packet,
05764                       char *reply_data,
05765                       int *reply_ofs,
05766                       int reply_len)
05767 {
05768         char tmp_addr[INET6_ADDRSTRLEN];
05769         struct option_state *host_opt_state;
05770         int len;
05771 
05772         log_info("Client %s releases prefix %s/%u, which is not leased to it.",
05773                  print_hex_1(client_id->len, client_id->data, 60),
05774                  inet_ntop(AF_INET6, iapref->data + 9,
05775                            tmp_addr, sizeof(tmp_addr)),
05776                  (unsigned) getUChar(iapref->data + 8));
05777 
05778         /*
05779          * Create state for this IA_PD.
05780          */
05781         host_opt_state = NULL;
05782         if (!option_state_allocate(&host_opt_state, MDL)) {
05783                 log_error("ia_pd_nomatch_release: out of memory "
05784                           "allocating option_state.");
05785                 goto exit;
05786         }
05787 
05788         if (!set_status_code(STATUS_NoBinding, 
05789                              "Release for non-leased prefix.",
05790                              host_opt_state)) {
05791                 goto exit;
05792         }
05793 
05794         /*
05795          * Insure we have enough space
05796          */
05797         if (reply_len < (*reply_ofs + 16)) {
05798                 log_error("ia_pd_nomatch_release: "
05799                           "out of space for reply packet.");
05800                 goto exit;
05801         }
05802 
05803         /*
05804          * Put our status code into the reply packet.
05805          */
05806         len = store_options6(reply_data+(*reply_ofs)+16,
05807                              reply_len-(*reply_ofs)-16,
05808                              host_opt_state, packet,
05809                              required_opts_STATUS_CODE, NULL);
05810 
05811         /*
05812          * Store the non-encapsulated option data for this 
05813          * IA_PD into our reply packet. Defined in RFC 3315, 
05814          * section 22.4.  
05815          */
05816         /* option number */
05817         putUShort((unsigned char *)reply_data+(*reply_ofs), D6O_IA_PD);
05818         /* option length */
05819         putUShort((unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
05820         /* IA_PD, copied from the client */
05821         memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
05822         /* t1 and t2, odd that we need them, but here it is */
05823         putULong((unsigned char *)reply_data+(*reply_ofs)+8, 0);
05824         putULong((unsigned char *)reply_data+(*reply_ofs)+12, 0);
05825 
05826         /*
05827          * Get ready for next IA_PD.
05828          */
05829         *reply_ofs += (len + 16);
05830 
05831 exit:
05832         option_state_dereference(&host_opt_state, MDL);
05833 }
05834 
05835 static void
05836 iterate_over_ia_pd(struct data_string *reply_ret, 
05837                    struct packet *packet,
05838                    const struct data_string *client_id,
05839                    const struct data_string *server_id,
05840                    const char *packet_type,
05841                    void (*ia_pd_match)(),
05842                    void (*ia_pd_nomatch)())
05843 {
05844         struct data_string reply_new;
05845         int reply_len;
05846         struct option_state *opt_state;
05847         struct host_decl *packet_host;
05848         struct option_cache *ia;
05849         struct option_cache *oc;
05850         /* cli_enc_... variables come from the IA_PD options */
05851         struct data_string cli_enc_opt_data;
05852         struct option_state *cli_enc_opt_state;
05853         struct host_decl *host;
05854         struct option_state *host_opt_state;
05855         struct data_string iaprefix;
05856         char reply_data[65536];
05857         int reply_ofs;
05858         struct iasubopt *prefix;
05859         struct ia_xx *existing_ia_pd;
05860         int i;
05861         struct data_string key;
05862         u_int32_t iaid;
05863 
05864         /*
05865          * Initialize to empty values, in case we have to exit early.
05866          */
05867         memset(&reply_new, 0, sizeof(reply_new));
05868         opt_state = NULL;
05869         memset(&cli_enc_opt_data, 0, sizeof(cli_enc_opt_data));
05870         cli_enc_opt_state = NULL;
05871         memset(&iaprefix, 0, sizeof(iaprefix));
05872         host_opt_state = NULL;
05873         prefix = NULL;
05874 
05875         /*
05876          * Compute the available length for the reply.
05877          */
05878         reply_len = sizeof(reply_data) - reply_ret->len;
05879         reply_ofs = 0;
05880 
05881         /* 
05882          * Find the host record that matches from the packet, if any.
05883          */
05884         packet_host = NULL;
05885         if (!find_hosts_by_uid(&packet_host, 
05886                                client_id->data, client_id->len, MDL)) {
05887                 packet_host = NULL;
05888                 /* 
05889                  * Note: In general, we don't expect a client to provide
05890                  *       enough information to match by option for these
05891                  *       types of messages, but if we don't have a UID
05892                  *       match we can check anyway.
05893                  */
05894                 if (!find_hosts_by_option(&packet_host, 
05895                                           packet, packet->options, MDL)) {
05896                         packet_host = NULL;
05897 
05898                         if (!find_hosts_by_duid_chaddr(&packet_host,
05899                                                        client_id))
05900                                 packet_host = NULL;
05901                 }
05902         }
05903 
05904         /*
05905          * Build our option state for reply.
05906          */
05907         opt_state = NULL;
05908         if (!option_state_allocate(&opt_state, MDL)) {
05909                 log_error("iterate_over_ia_pd: no memory for option_state.");
05910                 goto exit;
05911         }
05912         execute_statements_in_scope(NULL, packet, NULL, NULL, 
05913                                     packet->options, opt_state, 
05914                                     &global_scope, root_group, NULL, NULL);
05915 
05916         /*
05917          * Loop through the IA_PD reported by the client, and deal with
05918          * prefixes reported as already in use.
05919          */
05920         for (ia = lookup_option(&dhcpv6_universe, packet->options, D6O_IA_PD);
05921              ia != NULL; ia = ia->next) {
05922 
05923             if (!get_encapsulated_IA_state(&cli_enc_opt_state,
05924                                            &cli_enc_opt_data,
05925                                            packet, ia, IA_PD_OFFSET)) {
05926                 goto exit;
05927             }
05928 
05929             iaid = getULong(cli_enc_opt_data.data);
05930 
05931             oc = lookup_option(&dhcpv6_universe, cli_enc_opt_state, 
05932                                D6O_IAPREFIX);
05933             if (oc == NULL) {
05934                 /* no prefix given for this IA_PD, ignore */
05935                 option_state_dereference(&cli_enc_opt_state, MDL);
05936                 data_string_forget(&cli_enc_opt_data, MDL);
05937                 continue;
05938             }
05939 
05940             for (; oc != NULL; oc = oc->next) {
05941                 memset(&iaprefix, 0, sizeof(iaprefix));
05942                 if (!evaluate_option_cache(&iaprefix, packet, NULL, NULL, 
05943                                            packet->options, NULL,
05944                                            &global_scope, oc, MDL)) {
05945                         log_error("iterate_over_ia_pd: "
05946                                   "error evaluating IAPREFIX.");
05947                         goto exit;
05948                 }
05949 
05950                 /* 
05951                  * Now we need to figure out which host record matches
05952                  * this IA_PD and IAPREFIX (encapsulated option contents
05953                  * matching a host record by option).
05954                  *
05955                  * XXX: We don't currently track IA_PD separately, but
05956                  *      we will need to do this!
05957                  */
05958                 host = NULL;
05959                 if (!find_hosts_by_option(&host, packet, 
05960                                           cli_enc_opt_state, MDL)) { 
05961                         if (packet_host != NULL) {
05962                                 host = packet_host;
05963                         } else {
05964                                 host = NULL;
05965                         }
05966                 }
05967                 while (host != NULL) {
05968                         if (host->fixed_prefix != NULL) {
05969                                 struct iaddrcidrnetlist *l;
05970                                 int plen = (int) getUChar(iaprefix.data + 8);
05971 
05972                                 for (l = host->fixed_prefix; l != NULL;
05973                                      l = l->next) {
05974                                         if (plen != l->cidrnet.bits)
05975                                                 continue;
05976                                         if (memcmp(iaprefix.data + 9,
05977                                                    l->cidrnet.lo_addr.iabuf,
05978                                                    16) == 0)
05979                                                 break;
05980                                 }
05981                                 if ((l != NULL) && (iaprefix.len >= 17))
05982                                         break;
05983                         }
05984                         host = host->n_ipaddr;
05985                 }
05986 
05987                 if ((host == NULL) && (iaprefix.len >= IAPREFIX_OFFSET)) {
05988                         /*
05989                          * Find existing IA_PD.
05990                          */
05991                         if (ia_make_key(&key, iaid, 
05992                                         (char *)client_id->data,
05993                                         client_id->len, 
05994                                         MDL) != ISC_R_SUCCESS) {
05995                                 log_fatal("iterate_over_ia_pd: no memory for "
05996                                           "key.");
05997                         }
05998 
05999                         existing_ia_pd = NULL;
06000                         if (ia_hash_lookup(&existing_ia_pd, ia_pd_active, 
06001                                            (unsigned char *)key.data, 
06002                                            key.len, MDL)) {
06003                                 /* 
06004                                  * Make sure this prefix is in the IA_PD.
06005                                  */
06006                                 for (i = 0;
06007                                      i < existing_ia_pd->num_iasubopt;
06008                                      i++) {
06009                                         struct iasubopt *tmp;
06010                                         u_int8_t plen;
06011 
06012                                         plen = getUChar(iaprefix.data + 8);
06013                                         tmp = existing_ia_pd->iasubopt[i];
06014                                         if ((tmp->plen == plen) &&
06015                                             (memcmp(&tmp->addr,
06016                                                     iaprefix.data + 9,
06017                                                     16) == 0)) {
06018                                                 iasubopt_reference(&prefix,
06019                                                                    tmp, MDL);
06020                                                 break;
06021                                         }
06022                                 }
06023                         }
06024 
06025                         data_string_forget(&key, MDL);
06026                 }
06027 
06028                 if ((host != NULL) || (prefix != NULL)) {
06029                         ia_pd_match(client_id, &iaprefix, prefix);
06030                 } else {
06031                         ia_pd_nomatch(client_id, &iaprefix, 
06032                                       (u_int32_t *)cli_enc_opt_data.data, 
06033                                       packet, reply_data, &reply_ofs, 
06034                                       reply_len - reply_ofs);
06035                 }
06036 
06037                 if (prefix != NULL) {
06038                         iasubopt_dereference(&prefix, MDL);
06039                 }
06040 
06041                 data_string_forget(&iaprefix, MDL);
06042             }
06043 
06044             option_state_dereference(&cli_enc_opt_state, MDL);
06045             data_string_forget(&cli_enc_opt_data, MDL);
06046         }
06047 
06048         /* 
06049          * Return our reply to the caller.
06050          * The IA_NA routine has already filled at least the header.
06051          */
06052         reply_new.len = reply_ret->len + reply_ofs;
06053         if (!buffer_allocate(&reply_new.buffer, reply_new.len, MDL)) {
06054                 log_fatal("No memory to store reply.");
06055         }
06056         reply_new.data = reply_new.buffer->data;
06057         memcpy(reply_new.buffer->data,
06058                reply_ret->buffer->data, reply_ret->len);
06059         memcpy(reply_new.buffer->data + reply_ret->len,
06060                reply_data, reply_ofs);
06061         data_string_forget(reply_ret, MDL);
06062         data_string_copy(reply_ret, &reply_new, MDL);
06063         data_string_forget(&reply_new, MDL);
06064 
06065 exit:
06066         if (prefix != NULL) {
06067                 iasubopt_dereference(&prefix, MDL);
06068         }
06069         if (host_opt_state != NULL) {
06070                 option_state_dereference(&host_opt_state, MDL);
06071         }
06072         if (iaprefix.buffer != NULL) {
06073                 data_string_forget(&iaprefix, MDL);
06074         }
06075         if (cli_enc_opt_state != NULL) {
06076                 option_state_dereference(&cli_enc_opt_state, MDL);
06077         }
06078         if (cli_enc_opt_data.buffer != NULL) {
06079                 data_string_forget(&cli_enc_opt_data, MDL);
06080         }
06081         if (opt_state != NULL) {
06082                 option_state_dereference(&opt_state, MDL);
06083         }
06084 }
06085 
06086 /*
06087  * Release means a client is done with the leases.
06088  */
06089 
06090 static void
06091 dhcpv6_release(struct data_string *reply, struct packet *packet) {
06092         struct data_string client_id;
06093         struct data_string server_id;
06094 
06095         TRACE(DHCPD_6_RELEASE_START());
06096 
06097         /* 
06098          * Validate our input.
06099          */
06100         if (!valid_client_resp(packet, &client_id, &server_id)) {
06101                 return;
06102         }
06103 
06104         /*
06105          * And operate on each IA_NA in this packet.
06106          */
06107         iterate_over_ia_na(reply, packet, &client_id, &server_id, "Release", 
06108                            ia_na_match_release, ia_na_nomatch_release);
06109 
06110         /*
06111          * And operate on each IA_PD in this packet.
06112          */
06113         iterate_over_ia_pd(reply, packet, &client_id, &server_id, "Release",
06114                            ia_pd_match_release, ia_pd_nomatch_release);
06115 
06116         data_string_forget(&server_id, MDL);
06117         data_string_forget(&client_id, MDL);
06118 
06119         TRACE(DHCPD_6_RELEASE_DONE());
06120 }
06121 
06122 /*
06123  * Information-Request is used by clients who have obtained an address
06124  * from other means, but want configuration information from the server.
06125  */
06126 
06127 static void
06128 dhcpv6_information_request(struct data_string *reply, struct packet *packet) {
06129         struct data_string client_id;
06130         struct data_string server_id;
06131 
06132         TRACE(DHCPD_6_INFORMATION_REQUEST_START());
06133 
06134         /*
06135          * Validate our input.
06136          */
06137         if (!valid_client_info_req(packet, &server_id)) {
06138                 return;
06139         }
06140 
06141         /*
06142          * Get our client ID, if there is one.
06143          */
06144         memset(&client_id, 0, sizeof(client_id));
06145         if (get_client_id(packet, &client_id) != ISC_R_SUCCESS) {
06146                 data_string_forget(&client_id, MDL);
06147         }
06148 
06149         /*
06150          * Use the lease_to_client() function. This will work fine, 
06151          * because the valid_client_info_req() insures that we 
06152          * don't have any IA that would cause us to allocate
06153          * resources to the client.
06154          */
06155         lease_to_client(reply, packet, &client_id,
06156                         server_id.data != NULL ? &server_id : NULL);
06157 
06158         /*
06159          * Cleanup.
06160          */
06161         if (client_id.data != NULL) {
06162                 data_string_forget(&client_id, MDL);
06163         }
06164         data_string_forget(&server_id, MDL);
06165 
06166         TRACE(DHCPD_6_INFORMATION_REQUEST_DONE());
06167 }
06168 
06169 /* 
06170  * The Relay-forw message is sent by relays. It typically contains a
06171  * single option, which encapsulates an entire packet.
06172  *
06173  * We need to build an encapsulated reply.
06174  */
06175 
06176 /* XXX: this is very, very similar to do_packet6(), and should probably
06177         be combined in a clever way */
06178 static void
06179 dhcpv6_relay_forw(struct data_string *reply_ret, struct packet *packet) {
06180         struct option_cache *oc;
06181         struct data_string enc_opt_data;
06182         struct packet *enc_packet;
06183         unsigned char msg_type;
06184         const struct dhcpv6_packet *msg;
06185         const struct dhcpv6_relay_packet *relay;
06186         struct data_string enc_reply;
06187         char link_addr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
06188         char peer_addr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
06189         struct data_string a_opt, packet_ero;
06190         struct option_state *opt_state;
06191         static char reply_data[65536];
06192         struct dhcpv6_relay_packet *reply;
06193         int reply_ofs;
06194 
06195         TRACE(DHCPD_6_RELAY_FORW_START());
06196 
06197         /* 
06198          * Initialize variables for early exit.
06199          */
06200         opt_state = NULL;
06201         memset(&a_opt, 0, sizeof(a_opt));
06202         memset(&packet_ero, 0, sizeof(packet_ero));
06203         memset(&enc_reply, 0, sizeof(enc_reply));
06204         memset(&enc_opt_data, 0, sizeof(enc_opt_data));
06205         enc_packet = NULL;
06206 
06207         /*
06208          * Get our encapsulated relay message.
06209          */
06210         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_RELAY_MSG);
06211         if (oc == NULL) {
06212                 inet_ntop(AF_INET6, &packet->dhcpv6_link_address,
06213                           link_addr, sizeof(link_addr));
06214                 inet_ntop(AF_INET6, &packet->dhcpv6_peer_address,
06215                           peer_addr, sizeof(peer_addr));
06216                 log_info("Relay-forward from %s with link address=%s and "
06217                          "peer address=%s missing Relay Message option.",
06218                           piaddr(packet->client_addr), link_addr, peer_addr);
06219                 goto exit;
06220         }
06221 
06222         if (!evaluate_option_cache(&enc_opt_data, NULL, NULL, NULL, 
06223                                    NULL, NULL, &global_scope, oc, MDL)) {
06224                 log_error("dhcpv6_forw_relay: error evaluating "
06225                           "relayed message.");
06226                 goto exit;
06227         }
06228 
06229         if (!packet6_len_okay((char *)enc_opt_data.data, enc_opt_data.len)) {
06230                 log_error("dhcpv6_forw_relay: encapsulated packet too short.");
06231                 goto exit;
06232         }
06233 
06234         /*
06235          * Build a packet structure from this encapsulated packet.
06236          */
06237         enc_packet = NULL;
06238         if (!packet_allocate(&enc_packet, MDL)) {
06239                 log_error("dhcpv6_forw_relay: "
06240                           "no memory for encapsulated packet.");
06241                 goto exit;
06242         }
06243 
06244         if (!option_state_allocate(&enc_packet->options, MDL)) {
06245                 log_error("dhcpv6_forw_relay: "
06246                           "no memory for encapsulated packet's options.");
06247                 goto exit;
06248         }
06249 
06250         enc_packet->client_port = packet->client_port;
06251         enc_packet->client_addr = packet->client_addr;
06252         interface_reference(&enc_packet->interface, packet->interface, MDL);
06253         enc_packet->dhcpv6_container_packet = packet;
06254 
06255         msg_type = enc_opt_data.data[0];
06256         if ((msg_type == DHCPV6_RELAY_FORW) ||
06257             (msg_type == DHCPV6_RELAY_REPL)) {
06258                 int relaylen = (int)(offsetof(struct dhcpv6_relay_packet, options));
06259                 relay = (struct dhcpv6_relay_packet *)enc_opt_data.data;
06260                 enc_packet->dhcpv6_msg_type = relay->msg_type;
06261 
06262                 /* relay-specific data */
06263                 enc_packet->dhcpv6_hop_count = relay->hop_count;
06264                 memcpy(&enc_packet->dhcpv6_link_address,
06265                        relay->link_address, sizeof(relay->link_address));
06266                 memcpy(&enc_packet->dhcpv6_peer_address,
06267                        relay->peer_address, sizeof(relay->peer_address));
06268 
06269                 if (!parse_option_buffer(enc_packet->options,
06270                                          relay->options, 
06271                                          enc_opt_data.len - relaylen,
06272                                          &dhcpv6_universe)) {
06273                         /* no logging here, as parse_option_buffer() logs all
06274                            cases where it fails */
06275                         goto exit;
06276                 }
06277         } else {
06278                 int msglen = (int)(offsetof(struct dhcpv6_packet, options));
06279                 msg = (struct dhcpv6_packet *)enc_opt_data.data;
06280                 enc_packet->dhcpv6_msg_type = msg->msg_type;
06281 
06282                 /* message-specific data */
06283                 memcpy(enc_packet->dhcpv6_transaction_id,
06284                        msg->transaction_id,
06285                        sizeof(enc_packet->dhcpv6_transaction_id));
06286 
06287                 if (!parse_option_buffer(enc_packet->options,
06288                                          msg->options, 
06289                                          enc_opt_data.len - msglen,
06290                                          &dhcpv6_universe)) {
06291                         /* no logging here, as parse_option_buffer() logs all
06292                            cases where it fails */
06293                         goto exit;
06294                 }
06295         }
06296 
06297         /*
06298          * This is recursive. It is possible to exceed maximum packet size.
06299          * XXX: This will cause the packet send to fail.
06300          */
06301         build_dhcpv6_reply(&enc_reply, enc_packet);
06302 
06303         /*
06304          * If we got no encapsulated data, then it is discarded, and
06305          * our reply-forw is also discarded.
06306          */
06307         if (enc_reply.data == NULL) {
06308                 goto exit;
06309         }
06310 
06311         /*
06312          * Now we can use the reply_data buffer.
06313          * Packet header stuff all comes from the forward message.
06314          */
06315         reply = (struct dhcpv6_relay_packet *)reply_data;
06316         reply->msg_type = DHCPV6_RELAY_REPL;
06317         reply->hop_count = packet->dhcpv6_hop_count;
06318         memcpy(reply->link_address, &packet->dhcpv6_link_address,
06319                sizeof(reply->link_address));
06320         memcpy(reply->peer_address, &packet->dhcpv6_peer_address,
06321                sizeof(reply->peer_address));
06322         reply_ofs = (int)(offsetof(struct dhcpv6_relay_packet, options));
06323 
06324         /*
06325          * Get the reply option state.
06326          */
06327         opt_state = NULL;
06328         if (!option_state_allocate(&opt_state, MDL)) {
06329                 log_error("dhcpv6_relay_forw: no memory for option state.");
06330                 goto exit;
06331         }
06332 
06333         /*
06334          * Append the interface-id if present.
06335          */
06336         oc = lookup_option(&dhcpv6_universe, packet->options,
06337                            D6O_INTERFACE_ID);
06338         if (oc != NULL) {
06339                 if (!evaluate_option_cache(&a_opt, packet,
06340                                            NULL, NULL, 
06341                                            packet->options, NULL,
06342                                            &global_scope, oc, MDL)) {
06343                         log_error("dhcpv6_relay_forw: error evaluating "
06344                                   "Interface ID.");
06345                         goto exit;
06346                 }
06347                 if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
06348                                         (unsigned char *)a_opt.data,
06349                                         a_opt.len,
06350                                         D6O_INTERFACE_ID, 0)) {
06351                         log_error("dhcpv6_relay_forw: error saving "
06352                                   "Interface ID.");
06353                         goto exit;
06354                 }
06355                 data_string_forget(&a_opt, MDL);
06356         }
06357 
06358         /* 
06359          * Append our encapsulated stuff for caller.
06360          */
06361         if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
06362                                 (unsigned char *)enc_reply.data,
06363                                 enc_reply.len,
06364                                 D6O_RELAY_MSG, 0)) {
06365                 log_error("dhcpv6_relay_forw: error saving Relay MSG.");
06366                 goto exit;
06367         }
06368 
06369         /*
06370          * Get the ERO if any.
06371          */
06372         oc = lookup_option(&dhcpv6_universe, packet->options, D6O_ERO);
06373         if (oc != NULL) {
06374                 unsigned req;
06375                 int i;
06376 
06377                 if (!evaluate_option_cache(&packet_ero, packet,
06378                                            NULL, NULL,
06379                                            packet->options, NULL,
06380                                            &global_scope, oc, MDL) ||
06381                         (packet_ero.len & 1)) {
06382                         log_error("dhcpv6_relay_forw: error evaluating ERO.");
06383                         goto exit;
06384                 }
06385 
06386                 /* Decode and apply the ERO. */
06387                 for (i = 0; i < packet_ero.len; i += 2) {
06388                         req = getUShort(packet_ero.data + i);
06389                         /* Already in the reply? */
06390                         oc = lookup_option(&dhcpv6_universe, opt_state, req);
06391                         if (oc != NULL)
06392                                 continue;
06393                         /* Get it from the packet if present. */
06394                         oc = lookup_option(&dhcpv6_universe,
06395                                            packet->options,
06396                                            req);
06397                         if (oc == NULL)
06398                                 continue;
06399                         if (!evaluate_option_cache(&a_opt, packet,
06400                                                    NULL, NULL,
06401                                                    packet->options, NULL,
06402                                                    &global_scope, oc, MDL)) {
06403                                 log_error("dhcpv6_relay_forw: error "
06404                                           "evaluating option %u.", req);
06405                                 goto exit;
06406                         }
06407                         if (!save_option_buffer(&dhcpv6_universe,
06408                                                 opt_state,
06409                                                 NULL,
06410                                                 (unsigned char *)a_opt.data,
06411                                                 a_opt.len,
06412                                                 req,
06413                                                 0)) {
06414                                 log_error("dhcpv6_relay_forw: error saving "
06415                                           "option %u.", req);
06416                                 goto exit;
06417                         }
06418                         data_string_forget(&a_opt, MDL);
06419                 }
06420         }
06421 
06422         reply_ofs += store_options6(reply_data + reply_ofs,
06423                                     sizeof(reply_data) - reply_ofs,
06424                                     opt_state, packet,
06425                                     required_opts_agent, &packet_ero);
06426 
06427         /*
06428          * Return our reply to the caller.
06429          */
06430         reply_ret->len = reply_ofs;
06431         reply_ret->buffer = NULL;
06432         if (!buffer_allocate(&reply_ret->buffer, reply_ret->len, MDL)) {
06433                 log_fatal("No memory to store reply.");
06434         }
06435         reply_ret->data = reply_ret->buffer->data;
06436         memcpy(reply_ret->buffer->data, reply_data, reply_ofs);
06437 
06438 exit:
06439         if (opt_state != NULL)
06440                 option_state_dereference(&opt_state, MDL);
06441         if (a_opt.data != NULL) {
06442                 data_string_forget(&a_opt, MDL);
06443         }
06444         if (packet_ero.data != NULL) {
06445                 data_string_forget(&packet_ero, MDL);
06446         }
06447         if (enc_reply.data != NULL) {
06448                 data_string_forget(&enc_reply, MDL);
06449         }
06450         if (enc_opt_data.data != NULL) {
06451                 data_string_forget(&enc_opt_data, MDL);
06452         }
06453         if (enc_packet != NULL) {
06454                 packet_dereference(&enc_packet, MDL);
06455         }
06456 
06457         TRACE(DHCPD_6_RELAY_FORW_DONE());
06458 }
06459 
06460 static void
06461 dhcpv6_discard(struct packet *packet) {
06462         /* INSIST(packet->msg_type > 0); */
06463         /* INSIST(packet->msg_type < dhcpv6_type_name_max); */
06464 
06465         log_debug("Discarding %s from %s; message type not handled by server", 
06466                   dhcpv6_type_names[packet->dhcpv6_msg_type],
06467                   piaddr(packet->client_addr));
06468 }
06469 
06470 static void 
06471 build_dhcpv6_reply(struct data_string *reply, struct packet *packet) {
06472         memset(reply, 0, sizeof(*reply));
06473 
06474         /* I would like to classify the client once here, but
06475          * as I don't want to classify all of the incoming packets
06476          * I need to do it before handling specific types.
06477          * We don't need to classify if we are tossing the packet
06478          * or if it is a relay - the classification step will get
06479          * done when we process the inner client packet.
06480          */
06481 
06482         switch (packet->dhcpv6_msg_type) {
06483                 case DHCPV6_SOLICIT:
06484                         classify_client(packet);
06485                         dhcpv6_solicit(reply, packet);
06486                         break;
06487                 case DHCPV6_ADVERTISE:
06488                         dhcpv6_discard(packet);
06489                         break;
06490                 case DHCPV6_REQUEST:
06491                         classify_client(packet);
06492                         dhcpv6_request(reply, packet);
06493                         break;
06494                 case DHCPV6_CONFIRM:
06495                         classify_client(packet);
06496                         dhcpv6_confirm(reply, packet);
06497                         break;
06498                 case DHCPV6_RENEW:
06499                         classify_client(packet);
06500                         dhcpv6_renew(reply, packet);
06501                         break;
06502                 case DHCPV6_REBIND:
06503                         classify_client(packet);
06504                         dhcpv6_rebind(reply, packet);
06505                         break;
06506                 case DHCPV6_REPLY:
06507                         dhcpv6_discard(packet);
06508                         break;
06509                 case DHCPV6_RELEASE:
06510                         classify_client(packet);
06511                         dhcpv6_release(reply, packet);
06512                         break;
06513                 case DHCPV6_DECLINE:
06514                         classify_client(packet);
06515                         dhcpv6_decline(reply, packet);
06516                         break;
06517                 case DHCPV6_RECONFIGURE:
06518                         dhcpv6_discard(packet);
06519                         break;
06520                 case DHCPV6_INFORMATION_REQUEST:
06521                         classify_client(packet);
06522                         dhcpv6_information_request(reply, packet);
06523                         break;
06524                 case DHCPV6_RELAY_FORW:
06525                         dhcpv6_relay_forw(reply, packet);
06526                         break;
06527                 case DHCPV6_RELAY_REPL:
06528                         dhcpv6_discard(packet);
06529                         break;
06530                 case DHCPV6_LEASEQUERY:
06531                         classify_client(packet);
06532                         dhcpv6_leasequery(reply, packet);
06533                         break;
06534                 case DHCPV6_LEASEQUERY_REPLY:
06535                         dhcpv6_discard(packet);
06536                         break;
06537                 default:
06538                         /* XXX: would be nice if we had "notice" level, 
06539                                 as syslog, for this */
06540                         log_info("Discarding unknown DHCPv6 message type %d "
06541                                  "from %s", packet->dhcpv6_msg_type, 
06542                                  piaddr(packet->client_addr));
06543         }
06544 }
06545 
06546 static void
06547 log_packet_in(const struct packet *packet) {
06548         struct data_string s;
06549         u_int32_t tid;
06550         char tmp_addr[INET6_ADDRSTRLEN];
06551         const void *addr;
06552 
06553         memset(&s, 0, sizeof(s));
06554 
06555         if (packet->dhcpv6_msg_type < dhcpv6_type_name_max) {
06556                 data_string_sprintfa(&s, "%s message from %s port %d",
06557                                      dhcpv6_type_names[packet->dhcpv6_msg_type],
06558                                      piaddr(packet->client_addr),
06559                                      ntohs(packet->client_port));
06560         } else {
06561                 data_string_sprintfa(&s, 
06562                                      "Unknown message type %d from %s port %d",
06563                                      packet->dhcpv6_msg_type,
06564                                      piaddr(packet->client_addr),
06565                                      ntohs(packet->client_port));
06566         }
06567         if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) || 
06568             (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
06569                 addr = &packet->dhcpv6_link_address;
06570                 data_string_sprintfa(&s, ", link address %s", 
06571                                      inet_ntop(AF_INET6, addr, 
06572                                                tmp_addr, sizeof(tmp_addr)));
06573                 addr = &packet->dhcpv6_peer_address;
06574                 data_string_sprintfa(&s, ", peer address %s", 
06575                                      inet_ntop(AF_INET6, addr, 
06576                                                tmp_addr, sizeof(tmp_addr)));
06577         } else {
06578                 tid = 0;
06579                 memcpy(((char *)&tid)+1, packet->dhcpv6_transaction_id, 3);
06580                 data_string_sprintfa(&s, ", transaction ID 0x%06X", tid);
06581 
06582 /*
06583                 oc = lookup_option(&dhcpv6_universe, packet->options, 
06584                                    D6O_CLIENTID);
06585                 if (oc != NULL) {
06586                         memset(&tmp_ds, 0, sizeof(tmp_ds_));
06587                         if (!evaluate_option_cache(&tmp_ds, packet, NULL, NULL, 
06588                                                    packet->options, NULL,
06589                                                    &global_scope, oc, MDL)) {
06590                                 log_error("Error evaluating Client Identifier");
06591                         } else {
06592                                 data_strint_sprintf(&s, ", client ID %s",
06593 
06594                                 data_string_forget(&tmp_ds, MDL);
06595                         }
06596                 }
06597 */
06598 
06599         }
06600         log_info("%s", s.data);
06601 
06602         data_string_forget(&s, MDL);
06603 }
06604 
06605 void 
06606 dhcpv6(struct packet *packet) {
06607         struct data_string reply;
06608         struct sockaddr_in6 to_addr;
06609         int send_ret;
06610 
06611         /* 
06612          * Log a message that we received this packet.
06613          */
06614         log_packet_in(packet); 
06615 
06616         /*
06617          * Build our reply packet.
06618          */
06619         build_dhcpv6_reply(&reply, packet);
06620 
06621         if (reply.data != NULL) {
06622                 /* 
06623                  * Send our reply, if we have one.
06624                  */
06625                 memset(&to_addr, 0, sizeof(to_addr));
06626                 to_addr.sin6_family = AF_INET6;
06627                 if ((packet->dhcpv6_msg_type == DHCPV6_RELAY_FORW) || 
06628                     (packet->dhcpv6_msg_type == DHCPV6_RELAY_REPL)) {
06629                         to_addr.sin6_port = local_port;
06630                 } else {
06631                         to_addr.sin6_port = remote_port;
06632                 }
06633 
06634 #if defined (REPLY_TO_SOURCE_PORT)
06635                 /*
06636                  * This appears to have been included for testing so we would
06637                  * not need a root client, but was accidently left in the
06638                  * final code.  We continue to include it in case
06639                  * some users have come to rely upon it, but leave
06640                  * it off by default as it's a bad idea.
06641                  */
06642                 to_addr.sin6_port = packet->client_port;
06643 #endif
06644 
06645                 memcpy(&to_addr.sin6_addr, packet->client_addr.iabuf, 
06646                        sizeof(to_addr.sin6_addr));
06647 
06648                 log_info("Sending %s to %s port %d", 
06649                          dhcpv6_type_names[reply.data[0]],
06650                          piaddr(packet->client_addr),
06651                          ntohs(to_addr.sin6_port));
06652 
06653                 send_ret = send_packet6(packet->interface, 
06654                                         reply.data, reply.len, &to_addr);
06655                 if (send_ret != reply.len) {
06656                         log_error("dhcpv6: send_packet6() sent %d of %d bytes",
06657                                   send_ret, reply.len);
06658                 }
06659                 data_string_forget(&reply, MDL);
06660         }
06661 }
06662 
06663 static void
06664 seek_shared_host(struct host_decl **hp, struct shared_network *shared) {
06665         struct host_decl *nofixed = NULL;
06666         struct host_decl *seek, *hold = NULL;
06667 
06668         /*
06669          * Seek forward through fixed addresses for the right link.
06670          *
06671          * Note: how to do this for fixed prefixes???
06672          */
06673         host_reference(&hold, *hp, MDL);
06674         host_dereference(hp, MDL);
06675         seek = hold;
06676         while (seek != NULL) {
06677                 if (seek->fixed_addr == NULL)
06678                         nofixed = seek;
06679                 else if (fixed_matches_shared(seek, shared))
06680                         break;
06681 
06682                 seek = seek->n_ipaddr;
06683         }
06684 
06685         if ((seek == NULL) && (nofixed != NULL))
06686                 seek = nofixed;
06687 
06688         if (seek != NULL)
06689                 host_reference(hp, seek, MDL);
06690 }
06691 
06692 static isc_boolean_t
06693 fixed_matches_shared(struct host_decl *host, struct shared_network *shared) {
06694         struct subnet *subnet;
06695         struct data_string addr;
06696         isc_boolean_t matched;
06697         struct iaddr fixed;
06698 
06699         if (host->fixed_addr == NULL)
06700                 return ISC_FALSE;
06701 
06702         memset(&addr, 0, sizeof(addr));
06703         if (!evaluate_option_cache(&addr, NULL, NULL, NULL, NULL, NULL,
06704                                    &global_scope, host->fixed_addr, MDL))
06705                 return ISC_FALSE;
06706 
06707         if (addr.len < 16) {
06708                 data_string_forget(&addr, MDL);
06709                 return ISC_FALSE;
06710         }
06711 
06712         fixed.len = 16;
06713         memcpy(fixed.iabuf, addr.data, 16);
06714 
06715         matched = ISC_FALSE;
06716         for (subnet = shared->subnets ; subnet != NULL ;
06717              subnet = subnet->next_sibling) {
06718                 if (addr_eq(subnet_number(fixed, subnet->netmask),
06719                             subnet->net)) {
06720                         matched = ISC_TRUE;
06721                         break;
06722                 }
06723         }
06724 
06725         data_string_forget(&addr, MDL);
06726         return matched;
06727 }
06728 
06729 /*
06730  * find_host_by_duid_chaddr() synthesizes a DHCPv4-like 'hardware'
06731  * parameter from a DHCPv6 supplied DUID (client-identifier option),
06732  * and may seek to use client or relay supplied hardware addresses.
06733  */
06734 static int
06735 find_hosts_by_duid_chaddr(struct host_decl **host,
06736                           const struct data_string *client_id) {
06737         static int once_htype;
06738         int htype, hlen;
06739         const unsigned char *chaddr;
06740 
06741         /*
06742          * The DUID-LL and DUID-LLT must have a 2-byte DUID type and 2-byte
06743          * htype.
06744          */
06745         if (client_id->len < 4)
06746                 return 0;
06747 
06748         /*
06749          * The third and fourth octets of the DUID-LL and DUID-LLT
06750          * is the hardware type, but in 16 bits.
06751          */
06752         htype = getUShort(client_id->data + 2);
06753         hlen = 0;
06754         chaddr = NULL;
06755 
06756         /* The first two octets of the DUID identify the type. */
06757         switch(getUShort(client_id->data)) {
06758               case DUID_LLT:
06759                 if (client_id->len > 8) {
06760                         hlen = client_id->len - 8;
06761                         chaddr = client_id->data + 8;
06762                 }
06763                 break;
06764 
06765               case DUID_LL:
06766                 /*
06767                  * Note that client_id->len must be greater than or equal
06768                  * to four to get to this point in the function.
06769                  */
06770                 hlen = client_id->len - 4;
06771                 chaddr = client_id->data + 4;
06772                 break;
06773 
06774               default:
06775                 break;
06776         }
06777 
06778         if ((hlen == 0) || (hlen > HARDWARE_ADDR_LEN)) 
06779                 return 0;
06780 
06781         /*
06782          * XXX: DHCPv6 gives a 16-bit field for the htype.  DHCPv4 gives an
06783          * 8-bit field.  To change the semantics of the generic 'hardware'
06784          * structure, we would have to adjust many DHCPv4 sources (from
06785          * interface to DHCPv4 lease code), and we would have to update the
06786          * 'hardware' config directive (probably being reverse compatible and
06787          * providing a new upgrade/replacement primitive).  This is a little
06788          * too much to change for now.  Hopefully we will revisit this before
06789          * hardware types exceeding 8 bits are assigned.
06790          */
06791         if ((htype & 0xFF00) && !once_htype) {
06792                 once_htype = 1;
06793                 log_error("Attention: At least one client advertises a "
06794                           "hardware type of %d, which exceeds the software "
06795                           "limitation of 255.", htype);
06796         }
06797 
06798         return find_hosts_by_haddr(host, htype, chaddr, hlen, MDL);
06799 }
06800 
06801 #endif /* DHCPv6 */
06802 

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1