57 unsigned client_resources;
58 isc_boolean_t resources_included;
59 isc_boolean_t static_lease;
60 unsigned static_prefixes;
77 u_int32_t client_valid, client_prefer;
80 u_int32_t send_valid, send_prefer;
92 unsigned char data[65536];
100 static int get_encapsulated_IA_state(
struct option_state **enc_opt_state,
106 static isc_result_t shared_network_from_packet6(
struct shared_network **shared,
108 static void seek_shared_host(
struct host_decl **hp,
110 static isc_boolean_t fixed_matches_shared(
struct host_decl *host,
112 static isc_result_t reply_process_ia_na(
struct reply_state *reply,
114 static isc_result_t reply_process_ia_ta(
struct reply_state *reply,
116 static isc_result_t reply_process_addr(
struct reply_state *reply,
118 static isc_boolean_t address_is_owned(
struct reply_state *reply,
120 static isc_boolean_t temporary_is_available(
struct reply_state *reply,
122 static isc_result_t find_client_temporaries(
struct reply_state *reply);
123 static isc_result_t reply_process_try_addr(
struct reply_state *reply,
125 static isc_result_t find_client_address(
struct reply_state *reply);
126 static isc_result_t reply_process_is_addressed(
struct reply_state *reply,
129 static isc_result_t reply_process_send_addr(
struct reply_state *reply,
133 static isc_result_t reply_process_ia_pd(
struct reply_state *reply,
135 static isc_result_t reply_process_prefix(
struct reply_state *reply,
137 static isc_boolean_t prefix_is_owned(
struct reply_state *reply,
139 static isc_result_t find_client_prefix(
struct reply_state *reply);
140 static isc_result_t reply_process_try_prefix(
struct reply_state *reply,
142 static isc_result_t reply_process_is_prefixed(
struct reply_state *reply,
145 static isc_result_t reply_process_send_prefix(
struct reply_state *reply,
147 static struct iasubopt *prefix_compare(
struct reply_state *reply,
150 static int find_hosts_by_duid_chaddr(
struct host_decl **host,
152 static void schedule_lease_timeout_reply(
struct reply_state *reply);
160 schedule_lease_timeout_reply(
struct reply_state *reply) {
165 if ((reply == NULL) || (reply->ia == NULL) || (reply->ia->iasubopt == NULL))
169 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
170 tmp = reply->ia->iasubopt[i];
180 duid_time(time_t when) {
217 return (server_duid.data != NULL);
255 isc_result_t ret_val;
268 ret_val = ISC_R_NOTFOUND;
270 memset(&option_duid, 0,
sizeof(option_duid));
274 ret_val = ISC_R_UNEXPECTED;
278 ret_val = ISC_R_SUCCESS;
297 static int server_duid_type =
DUID_LLT;
304 server_duid_type = type;
321 log_error(
"Invalid DUID type %d specified, "
322 "only LL and LLT types supported", server_duid_type);
335 log_error(
"Can not generate DUID from interfaces which do not have hardware addresses, please configure server-duid!");
339 return ISC_R_UNEXPECTED;
345 memset(&generated_duid, 0,
sizeof(generated_duid));
347 time_val = duid_time(time(NULL));
350 generated_duid.len,
MDL)) {
353 generated_duid.data = generated_duid.buffer->data;
355 putUShort(generated_duid.buffer->data + 2,
357 putULong(generated_duid.buffer->data + 4, time_val);
358 memcpy(generated_duid.buffer->data + 8,
360 }
else if (server_duid_type ==
DUID_LL) {
363 generated_duid.len,
MDL)) {
366 generated_duid.data = generated_duid.buffer->data;
368 putUShort(generated_duid.buffer->data + 2,
370 memcpy(generated_duid.buffer->data + 4,
373 log_fatal(
"Unsupported server DUID type %d.", server_duid_type);
379 return ISC_R_SUCCESS;
385 static isc_boolean_t unicast_option_defined;
391 static isc_boolean_t unicast_option_parsed = ISC_FALSE;
398 is_unicast_option_defined(
void) {
405 if (unicast_option_parsed == ISC_FALSE) {
406 unicast_option_parsed = ISC_TRUE;
409 log_fatal(
"No memory for option state.");
416 unicast_option_defined = (oc != NULL);
421 return (unicast_option_defined);
434 if ((client_id->
data != NULL) || (client_id->
len != 0)) {
440 return ISC_R_NOTFOUND;
446 return ISC_R_FAILURE;
449 return ISC_R_SUCCESS;
460 valid_client_msg(
struct packet *packet,
struct data_string *client_id) {
466 memset(client_id, 0,
sizeof(*client_id));
474 "client identifier missing",
479 log_error(
"Error processing %s from %s; "
480 "unable to evaluate Client Identifier",
490 log_debug(
"Discarding %s from %s; packet sent unicast "
505 "server identifier found "
506 "(CLIENTID %s, SERVERID %s)",
510 client_id->
data, 60),
515 "server identifier found "
519 client_id->
data, 60),
533 if (client_id->
len > 0) {
553 valid_client_resp(
struct packet *packet,
563 memset(client_id, 0,
sizeof(*client_id));
564 memset(server_id, 0,
sizeof(*server_id));
571 "client identifier missing",
576 log_error(
"Error processing %s from %s; "
577 "unable to evaluate Client Identifier",
586 "server identifier missing (CLIENTID %s)",
595 log_error(
"Error processing %s from %s; "
596 "unable to evaluate Server Identifier (CLIENTID %s)",
602 if ((server_duid.len != server_id->
len) ||
603 (memcmp(server_duid.data, server_id->
data, server_duid.len) != 0)) {
605 "not our server identifier "
606 "(CLIENTID %s, SERVERID %s, server DUID %s)",
611 print_hex_3(server_duid.len, server_duid.data, 60));
620 if (server_id->
len > 0) {
623 if (client_id->
len > 0) {
642 valid_client_info_req(
struct packet *packet,
struct data_string *server_id) {
646 char client_id_str[80];
650 memset(server_id, 0,
sizeof(*server_id));
651 memset(&client_id, 0,
sizeof(client_id));
662 snprintf(client_id_str,
sizeof(client_id_str),
" (CLIENTID %s)",
666 client_id_str[0] =
'\0';
673 log_debug(
"Discarding %s from %s; packet sent unicast%s",
682 "IA_NA option present%s",
690 "IA_TA option present%s",
698 "IA_PD option present%s",
709 log_error(
"Error processing %s from %s; "
710 "unable to evaluate Server Identifier%s",
715 if ((server_duid.len != server_id->
len) ||
716 (memcmp(server_duid.data, server_id->
data,
717 server_duid.len) != 0)) {
719 "not our server identifier "
720 "(SERVERID %s, server DUID %s)%s",
724 server_id->
data, 60),
726 server_duid.data, 60),
737 if (server_id->
len > 0) {
748 static const int required_opts[] = {
755 static const int required_opts_NAA[] = {
761 static const int required_opts_solicit[] = {
773 static const int required_opts_agent[] = {
778 static const int required_opts_IA[] = {
783 static const int required_opts_IA_PD[] = {
788 static const int required_opts_STATUS_CODE[] = {
800 get_encapsulated_IA_state(
struct option_state **enc_opt_state,
802 struct packet *packet,
809 memset(enc_opt_data, 0,
sizeof(*enc_opt_data));
811 NULL, NULL, packet->
options, NULL,
814 "error evaluating raw option.");
817 if (enc_opt_data->
len < offset) {
818 log_error(
"get_encapsulated_IA_state: raw option too small.");
827 *enc_opt_state = NULL;
829 log_error(
"get_encapsulated_IA_state: no memory for options.");
834 enc_opt_data->
data + offset,
835 enc_opt_data->
len - offset,
837 log_error(
"get_encapsulated_IA_state: error parsing options.");
847 set_status_code(u_int16_t status_code,
const char *status_message,
853 memset(&d, 0,
sizeof(d));
854 d.len =
sizeof(status_code) + strlen(status_message);
856 log_fatal(
"set_status_code: no memory for status code.");
858 d.data = d.buffer->data;
860 memcpy(d.buffer->data +
sizeof(status_code),
861 status_message, d.len -
sizeof(status_code));
863 d.buffer, (
unsigned char *)d.data, d.len,
865 log_error(
"set_status_code: error saving status code.");
874 void check_pool6_threshold(
struct reply_state *reply,
878 int used, count, high_threshold, poolhigh = 0, poollow = 0;
879 char *shared_name =
"no name";
880 char tmp_addr[INET6_ADDRSTRLEN];
903 log_error(
"Pool threshold reset - shared subnet: %s; "
904 "address: %s; low threshold %d/%d.",
906 inet_ntop(AF_INET6, &lease->
addr,
907 tmp_addr,
sizeof(tmp_addr)),
915 NULL, reply->packet->options, reply->opt_state,
916 reply->opt_state, &lease->
scope,
923 if ((poolhigh <= 0) || (poolhigh > 100)) {
930 if (used < high_threshold) {
940 log_error(
"Pool threshold exceeded - shared subnet: %s; "
941 "address: %s; high threshold %d%% %d/%d.",
943 inet_ntop(AF_INET6, &lease->
addr, tmp_addr,
sizeof(tmp_addr)),
944 poolhigh, used, count);
949 NULL, reply->packet->options, reply->opt_state,
950 reply->opt_state, &lease->
scope,
961 if (poollow < poolhigh) {
972 start_reply(
struct packet *packet,
979 const unsigned char *server_id_data;
987 log_error(
"start_reply: no memory for option_state.");
1055 if (server_id == NULL) {
1056 server_id_data = server_duid.data;
1057 server_id_len = server_duid.len;
1059 server_id_data = server_id->
data;
1060 server_id_len = server_id->
len;
1063 NULL, (
unsigned char *)server_id_data,
1066 "error saving server identifier.");
1071 if (client_id->
buffer != NULL) {
1074 (
unsigned char *)client_id->
data,
1078 "client identifier.");
1094 NULL, (
unsigned char *)
"", 0,
1097 "error saving RECONF_ACCEPT option.");
1115 try_client_v6_address(
struct iasubopt **addr,
1119 struct in6_addr tmp_addr;
1120 isc_result_t result;
1122 if (requested_addr->
len <
sizeof(tmp_addr)) {
1125 memcpy(&tmp_addr, requested_addr->
data,
sizeof(tmp_addr));
1126 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
1127 return ISC_R_FAILURE;
1135 return ISC_R_ADDRNOTAVAIL;
1139 return ISC_R_ADDRINUSE;
1142 result = iasubopt_allocate(addr,
MDL);
1143 if (result != ISC_R_SUCCESS) {
1146 (*addr)->addr = tmp_addr;
1151 if (result != ISC_R_SUCCESS) {
1180 pick_v6_address(
struct reply_state *reply)
1186 unsigned int attempts;
1187 char tmp_buf[INET6_ADDRSTRLEN];
1188 struct iasubopt **addr = &reply->lease;
1194 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1198 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1208 log_debug(
"Unable to pick client address: "
1209 "no IPv6 pools on this shared network");
1210 return ISC_R_NORESOURCES;
1224 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1237 &reply->ia->iaid_duid,
1238 cur_time + 120) == ISC_R_SUCCESS)) {
1252 inet_ntop(AF_INET6, &((*addr)->addr),
1253 tmp_buf,
sizeof(tmp_buf)));
1254 return (ISC_R_SUCCESS);
1261 }
while (i != start_pool);
1268 log_debug(
"Unable to pick client address: no addresses available");
1269 return ISC_R_NORESOURCES;
1281 try_client_v6_prefix(
struct iasubopt **pref,
1286 struct in6_addr tmp_pref;
1288 isc_result_t result;
1290 if (requested_pref->
len <
sizeof(tmp_plen) +
sizeof(tmp_pref)) {
1293 tmp_plen = (
int) requested_pref->
data[0];
1294 if ((tmp_plen < 3) || (tmp_plen > 128) ||
1295 ((
int)tmp_plen != pool->
units)) {
1296 return ISC_R_FAILURE;
1298 memcpy(&tmp_pref, requested_pref->
data + 1,
sizeof(tmp_pref));
1299 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
1300 return ISC_R_FAILURE;
1303 memcpy(&ia.iabuf, &tmp_pref, 16);
1305 return ISC_R_FAILURE;
1309 return ISC_R_ADDRNOTAVAIL;
1313 return ISC_R_ADDRINUSE;
1316 result = iasubopt_allocate(pref,
MDL);
1317 if (result != ISC_R_SUCCESS) {
1320 (*pref)->addr = tmp_pref;
1321 (*pref)->plen = tmp_plen;
1325 if (result != ISC_R_SUCCESS) {
1354 pick_v6_prefix(
struct reply_state *reply)
1359 unsigned int attempts;
1360 char tmp_buf[INET6_ADDRSTRLEN];
1361 struct iasubopt **pref = &reply->lease;
1367 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1371 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1381 log_debug(
"Unable to pick client prefix: "
1382 "no IPv6 pools on this shared network");
1383 return ISC_R_NORESOURCES;
1394 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1401 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1409 if ((reply->preflen >= 0) && (p->
units != reply->preflen)) {
1414 cur_time + 120) == ISC_R_SUCCESS) {
1416 inet_ntop(AF_INET6, &((*pref)->addr),
1417 tmp_buf,
sizeof(tmp_buf)),
1418 (
unsigned) (*pref)->plen);
1420 return (ISC_R_SUCCESS);
1429 log_debug(
"Unable to pick client prefix: no prefixes available");
1430 return ISC_R_NORESOURCES;
1470 struct packet *packet,
1474 static struct reply_state reply;
1479 memset(&packet_oro, 0,
sizeof(packet_oro));
1482 if (shared_network_from_packet6(&reply.shared,
1483 packet) != ISC_R_SUCCESS)
1492 if (!start_reply(packet, client_id, server_id, &reply.opt_state,
1508 log_error(
"lease_to_client: error evaluating ORO.");
1520 seek_shared_host(&reply.host, reply.shared);
1523 if ((reply.host == NULL) &&
1526 seek_shared_host(&reply.host, reply.shared);
1533 if ((reply.host == NULL) &&
1534 find_hosts_by_duid_chaddr(&reply.host, client_id)) {
1536 seek_shared_host(&reply.host, reply.shared);
1543 for (; oc != NULL ; oc = oc->
next) {
1544 isc_result_t status;
1547 reply.client_resources = 0;
1548 reply.resources_included = ISC_FALSE;
1550 status = reply_process_ia_na(&reply, oc);
1556 if ((status != ISC_R_SUCCESS) &&
1557 (status != ISC_R_NORESOURCES))
1561 for (; oc != NULL ; oc = oc->
next) {
1562 isc_result_t status;
1565 reply.client_resources = 0;
1566 reply.resources_included = ISC_FALSE;
1568 status = reply_process_ia_ta(&reply, oc);
1574 if ((status != ISC_R_SUCCESS) &&
1575 (status != ISC_R_NORESOURCES))
1582 for (; oc != NULL ; oc = oc->
next) {
1583 isc_result_t status;
1586 reply.client_resources = 0;
1587 reply.resources_included = ISC_FALSE;
1589 status = reply_process_ia_pd(&reply, oc);
1595 if ((status != ISC_R_SUCCESS) &&
1596 (status != ISC_R_NORESOURCES))
1604 if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
1605 if (reply.packet->dhcpv6_msg_type !=
1615 reply.packet->options,
1621 for (i = reply.packet->class_count; i > 0; i--) {
1624 reply.packet->options,
1627 reply.packet->classes[i - 1]->group,
1628 reply.shared->group, NULL);
1632 if (reply.host != NULL)
1635 reply.packet->options,
1639 reply.shared->group, NULL);
1643 if ((packet->
unicast == ISC_TRUE) && !is_unicast_option_defined())
1666 "Unicast not allowed by server.",
1668 log_error(
"lease_to_client: Unable to set "
1669 "UseMulticast status code.");
1687 reply.opt_state, reply.packet,
1725 reply.cursor +=
store_options6((
char *)reply.buf.data + reply.cursor,
1726 sizeof(reply.buf) - reply.cursor,
1727 reply.opt_state, reply.packet,
1728 required_opts_solicit,
1732 reply_ret->
len = reply.cursor;
1733 reply_ret->
buffer = NULL;
1737 memcpy(reply_ret->
buffer->
data, reply.buf.data, reply.cursor);
1745 if (reply.shared != NULL)
1746 shared_network_dereference(&reply.shared,
MDL);
1747 if (reply.host != NULL)
1748 host_dereference(&reply.host,
MDL);
1749 if (reply.opt_state != NULL)
1751 if (reply.packet != NULL)
1753 if (reply.client_id.data != NULL)
1755 if (packet_oro.buffer != NULL)
1757 reply.renew = reply.rebind = reply.prefer = reply.valid = 0;
1765 reply_process_ia_na(
struct reply_state *reply,
struct option_cache *ia) {
1766 isc_result_t status = ISC_R_SUCCESS;
1775 memset(&ia_data, 0,
sizeof(ia_data));
1782 if ((reply->cursor +
IA_NA_OFFSET + 4) >
sizeof(reply->buf)) {
1783 log_error(
"reply_process_ia_na: Reply too long for IA.");
1784 return ISC_R_NOSPACE;
1789 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
1791 log_error(
"reply_process_ia_na: error evaluating ia");
1792 status = ISC_R_FAILURE;
1798 reply->renew =
getULong(ia_data.data + 4);
1799 reply->rebind =
getULong(ia_data.data + 8);
1802 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
1803 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
1804 log_error(
"reply_process_ia_na: no memory for ia.");
1805 status = ISC_R_NOMEMORY;
1812 (
unsigned char *)reply->ia->iaid_duid.data,
1813 reply->ia->iaid_duid.len,
MDL);
1820 status = ISC_R_NOMEMORY;
1825 if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
1826 struct iaddr tmp_addr;
1830 reply->host->fixed_addr,
MDL)) {
1831 log_error(
"reply_process_ia_na: unable to evaluate "
1833 status = ISC_R_FAILURE;
1837 if (reply->fixed.len < 16) {
1838 log_error(
"reply_process_ia_na: invalid fixed address.");
1845 memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
1848 tmp_addr,
MDL) == 0)
1851 reply->static_lease = ISC_TRUE;
1853 reply->static_lease = ISC_FALSE;
1861 ia_cursor = reply->cursor;
1868 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
1872 putULong(reply->buf.data + reply->cursor, iaid);
1876 putULong(reply->buf.data + reply->cursor, reply->renew);
1880 putULong(reply->buf.data + reply->cursor, reply->rebind);
1893 reply->valid = reply->prefer = 0xffffffff;
1894 reply->client_valid = reply->client_prefer = 0;
1895 for (; oc != NULL ; oc = oc->
next) {
1896 status = reply_process_addr(reply, oc);
1904 if (status == ISC_R_CANCELED)
1907 if ((status != ISC_R_SUCCESS) &&
1908 (status != ISC_R_ADDRINUSE) &&
1909 (status != ISC_R_ADDRNOTAVAIL))
1919 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
1920 status = find_client_address(reply);
1922 if (status == ISC_R_NORESOURCES) {
1923 switch (reply->packet->dhcpv6_msg_type) {
1946 "memory for option state "
1948 status = ISC_R_NOMEMORY;
1953 "No addresses available "
1954 "for this interface.",
1956 log_error(
"reply_process_ia_na: Unable "
1957 "to set NoAddrsAvail status "
1959 status = ISC_R_FAILURE;
1963 status = ISC_R_SUCCESS;
1983 if (reply->resources_included)
1984 status = ISC_R_SUCCESS;
1991 if (status != ISC_R_SUCCESS)
1995 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
1996 sizeof(reply->buf) - reply->cursor,
1997 reply->reply_ia, reply->packet,
1998 required_opts_IA, NULL);
2001 putUShort(reply->buf.data + ia_cursor + 2,
2002 reply->cursor - (ia_cursor + 4));
2015 reply->packet->options,
2021 reply->renew =
getULong(data.data);
2024 if (data.data != NULL)
2027 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
2035 reply->packet->options,
2041 reply->rebind =
getULong(data.data);
2044 if (data.data != NULL)
2047 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
2053 if (status == ISC_R_CANCELED)
2060 if (reply->static_lease) {
2061 char tmp_addr[INET6_ADDRSTRLEN];
2062 log_info(
"%s NA: address %s to client with duid %s iaid = %d "
2065 inet_ntop(AF_INET6, reply->fixed.data, tmp_addr,
2068 reply->client_id.data, 60),
2072 (reply->on_star.on_commit != NULL)) {
2074 reply->packet->options,
2075 reply->opt_state, NULL,
2076 reply->on_star.on_commit, NULL);
2078 (&reply->on_star.on_commit,
MDL);
2086 if (reply->ia->num_iasubopt != 0) {
2089 char tmp_addr[INET6_ADDRSTRLEN];
2091 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2092 tmp = reply->ia->iasubopt[i];
2094 log_info(
"%s NA: address %s to client with duid %s "
2095 "iaid = %d valid for %d seconds",
2097 inet_ntop(AF_INET6, &tmp->
addr,
2098 tmp_addr,
sizeof(tmp_addr)),
2100 reply->client_id.data, 60),
2114 if ((reply->ia->num_iasubopt != 0) &&
2120 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2121 tmp = reply->ia->iasubopt[i];
2123 if (tmp->
ia != NULL)
2135 reply->packet->options,
2144 #if defined (NSUPDATE)
2153 reply->packet->options,
2158 tmp, NULL, reply->opt_state);
2162 check_pool6_threshold(reply, tmp);
2166 if (reply->old_ia != NULL) {
2167 ia_id = &reply->old_ia->iaid_duid;
2169 (
unsigned char *)ia_id->
data,
2176 ia_id = &reply->ia->iaid_duid;
2178 ia_id->
len, reply->ia,
MDL);
2182 schedule_lease_timeout_reply(reply);
2186 if (packet_ia != NULL)
2188 if (reply->reply_ia != NULL)
2190 if (ia_data.data != NULL)
2192 if (
data.data != NULL)
2194 if (reply->ia != NULL)
2196 if (reply->old_ia != NULL)
2198 if (reply->lease != NULL)
2200 if (reply->fixed.data != NULL)
2202 if (reply->subnet != NULL)
2203 subnet_dereference(&reply->subnet,
MDL);
2204 if (reply->on_star.on_expiry != NULL)
2206 (&reply->on_star.on_expiry,
MDL);
2207 if (reply->on_star.on_release != NULL)
2209 (&reply->on_star.on_release,
MDL);
2216 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2226 reply_process_addr(
struct reply_state *reply,
struct option_cache *addr) {
2227 u_int32_t pref_life, valid_life;
2231 struct iaddr tmp_addr;
2234 isc_result_t status = ISC_R_SUCCESS;
2237 memset(&iaaddr, 0,
sizeof(iaaddr));
2245 if ((reply->cursor + 28) >
sizeof(reply->buf)) {
2246 log_error(
"reply_process_addr: Out of room for address.");
2247 return ISC_R_NOSPACE;
2255 log_error(
"reply_process_addr: error evaluating IAADDR.");
2256 status = ISC_R_FAILURE;
2261 pref_life =
getULong(iaaddr.data + 16);
2262 valid_life =
getULong(iaaddr.data + 20);
2264 if ((reply->client_valid == 0) ||
2265 (reply->client_valid > valid_life))
2266 reply->client_valid = valid_life;
2268 if ((reply->client_prefer == 0) ||
2269 (reply->client_prefer > pref_life))
2270 reply->client_prefer = pref_life;
2277 memset(tmp_addr.iabuf, 0, 16);
2278 if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
2284 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2289 for (subnet = reply->shared->subnets ; subnet != NULL ;
2297 if (subnet == NULL) {
2322 log_error(
"reply_process_addr: No memory for "
2323 "option state wipe.");
2324 status = ISC_R_NOMEMORY;
2330 "Address not for use on this "
2331 "link.", reply->reply_ia)) {
2332 log_error(
"reply_process_addr: Failure "
2333 "setting status code.");
2334 status = ISC_R_FAILURE;
2339 status = ISC_R_CANCELED;
2351 if ((reply->packet->dhcpv6_msg_type !=
DHCPV6_RENEW) &&
2353 log_error(
"It is impossible to lease a client that is "
2354 "not sending a solicit, request, renew, or "
2356 status = ISC_R_FAILURE;
2360 reply->send_prefer = reply->send_valid = 0;
2365 if (!address_is_owned(reply, &tmp_addr)) {
2376 status = reply_process_try_addr(reply, &tmp_addr);
2383 if ((status != ISC_R_SUCCESS) &&
2384 (status != ISC_R_ADDRINUSE) &&
2385 (status != ISC_R_ADDRNOTAVAIL))
2393 if (reply->lease == NULL) {
2394 if (reply->packet->dhcpv6_msg_type ==
2396 reply->send_prefer = 0;
2397 reply->send_valid = 0;
2414 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
2418 log_error(
"reply_process_addr: No memory for "
2419 "option state wipe.");
2420 status = ISC_R_NOMEMORY;
2426 "Address not bound to this "
2427 "interface.", reply->reply_ia)) {
2428 log_error(
"reply_process_addr: Unable to "
2429 "attach status code.");
2430 status = ISC_R_FAILURE;
2435 status = ISC_R_CANCELED;
2438 log_error(
"It is impossible to lease a client that is "
2439 "not sending a solicit, request, renew, or "
2441 status = ISC_R_FAILURE;
2446 if (reply->static_lease) {
2447 if (reply->host == NULL)
2451 group = reply->subnet->group;
2453 if (reply->lease == NULL)
2456 scope = &reply->lease->scope;
2457 group = reply->lease->ipv6_pool->ipv6_pond->group;
2466 if (reply->client_resources != 0) {
2479 reply->packet->options,
2483 log_error(
"reply_process_addr: unable to "
2484 "evaluate addrs-per-ia value.");
2485 status = ISC_R_FAILURE;
2497 if (reply->client_resources >= limit)
2501 status = reply_process_is_addressed(reply, scope, group);
2502 if (status != ISC_R_SUCCESS)
2506 status = reply_process_send_addr(reply, &tmp_addr);
2509 if (iaaddr.data != NULL)
2511 if (
data.data != NULL)
2513 if (reply->lease != NULL)
2525 static isc_boolean_t
2526 address_is_owned(
struct reply_state *reply,
struct iaddr *addr) {
2533 if (reply->static_lease) {
2534 if (reply->fixed.data == NULL)
2537 if (memcmp(addr->
iabuf, reply->fixed.data, 16) == 0)
2543 if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
2546 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2549 tmp = reply->old_ia->iasubopt[i];
2551 if (memcmp(addr->
iabuf, &tmp->
addr, 16) == 0) {
2576 reply_process_ia_ta(
struct reply_state *reply,
struct option_cache *ia) {
2577 isc_result_t status = ISC_R_SUCCESS;
2584 u_int32_t pref_life, valid_life;
2585 struct iaddr tmp_addr;
2589 memset(&ia_data, 0,
sizeof(ia_data));
2590 memset(&data, 0,
sizeof(data));
2591 memset(&iaaddr, 0,
sizeof(iaaddr));
2594 if ((reply->cursor +
IA_TA_OFFSET + 4) >
sizeof(reply->buf)) {
2595 log_error(
"reply_process_ia_ta: Reply too long for IA.");
2596 return ISC_R_NOSPACE;
2601 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2603 log_error(
"reply_process_ia_ta: error evaluating ia");
2604 status = ISC_R_FAILURE;
2612 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
2613 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
2614 log_error(
"reply_process_ia_ta: no memory for ia.");
2615 status = ISC_R_NOMEMORY;
2622 (
unsigned char *)reply->ia->iaid_duid.data,
2623 reply->ia->iaid_duid.len,
MDL);
2630 status = ISC_R_NOMEMORY;
2637 reply->static_lease = ISC_FALSE;
2645 ia_cursor = reply->cursor;
2652 putUShort(reply->buf.data + reply->cursor, 0x04u);
2656 putULong(reply->buf.data + reply->cursor, iaid);
2663 reply->valid = reply->prefer = 0xffffffff;
2664 reply->client_valid = reply->client_prefer = 0;
2666 for (; oc != NULL; oc = oc->
next) {
2667 memset(&iaaddr, 0,
sizeof(iaaddr));
2670 reply->packet->options, NULL,
2674 "evaluating IAADDR.");
2675 status = ISC_R_FAILURE;
2679 pref_life =
getULong(iaaddr.data + 16);
2680 valid_life =
getULong(iaaddr.data + 20);
2682 if ((reply->client_valid == 0) ||
2683 (reply->client_valid > valid_life))
2684 reply->client_valid = valid_life;
2686 if ((reply->client_prefer == 0) ||
2687 (reply->client_prefer > pref_life))
2688 reply->client_prefer = pref_life;
2691 if (status == ISC_R_CANCELED)
2695 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2696 if (!temporary_is_available(reply, &tmp_addr))
2698 status = reply_process_is_addressed(reply,
2699 &reply->lease->scope,
2700 reply->lease->ipv6_pool->ipv6_pond->group);
2701 if (status != ISC_R_SUCCESS)
2703 status = reply_process_send_addr(reply, &tmp_addr);
2704 if (status != ISC_R_SUCCESS)
2706 if (reply->lease != NULL)
2714 status = ISC_R_NOMEMORY;
2717 status = ISC_R_CANCELED;
2718 reply->client_resources = 0;
2719 reply->resources_included = ISC_FALSE;
2720 if (reply->lease != NULL)
2728 if (reply->client_resources != 0)
2730 status = find_client_temporaries(reply);
2731 if (status == ISC_R_NORESOURCES) {
2732 switch (reply->packet->dhcpv6_msg_type) {
2753 "memory for option state wipe.");
2754 status = ISC_R_NOMEMORY;
2759 "No addresses available "
2760 "for this interface.",
2762 log_error(
"reply_process_ia_ta: Unable "
2763 "to set NoAddrsAvail status code.");
2764 status = ISC_R_FAILURE;
2768 status = ISC_R_SUCCESS;
2777 if (reply->resources_included)
2778 status = ISC_R_SUCCESS;
2783 }
else if (status != ISC_R_SUCCESS)
2787 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2788 sizeof(reply->buf) - reply->cursor,
2789 reply->reply_ia, reply->packet,
2790 required_opts_IA, NULL);
2793 putUShort(reply->buf.data + ia_cursor + 2,
2794 reply->cursor - (ia_cursor + 4));
2800 if (status == ISC_R_CANCELED)
2806 if (reply->ia->num_iasubopt != 0) {
2809 char tmp_addr[INET6_ADDRSTRLEN];
2811 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2812 tmp = reply->ia->iasubopt[i];
2814 log_info(
"%s TA: address %s to client with duid %s "
2815 "iaid = %d valid for %d seconds",
2817 inet_ntop(AF_INET6, &tmp->
addr,
2818 tmp_addr,
sizeof(tmp_addr)),
2820 reply->client_id.data, 60),
2834 if ((reply->ia->num_iasubopt != 0) &&
2840 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2841 tmp = reply->ia->iasubopt[i];
2843 if (tmp->
ia != NULL)
2855 reply->packet->options,
2864 #if defined (NSUPDATE)
2873 reply->packet->options,
2878 tmp, NULL, reply->opt_state);
2882 check_pool6_threshold(reply, tmp);
2886 if (reply->old_ia != NULL) {
2887 ia_id = &reply->old_ia->iaid_duid;
2889 (
unsigned char *)ia_id->
data,
2896 ia_id = &reply->ia->iaid_duid;
2898 ia_id->
len, reply->ia,
MDL);
2902 schedule_lease_timeout_reply(reply);
2906 if (packet_ia != NULL)
2908 if (iaaddr.data != NULL)
2910 if (reply->reply_ia != NULL)
2912 if (ia_data.data != NULL)
2914 if (
data.data != NULL)
2916 if (reply->ia != NULL)
2918 if (reply->old_ia != NULL)
2920 if (reply->lease != NULL)
2928 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2934 static isc_boolean_t
2935 temporary_is_available(
struct reply_state *reply,
struct iaddr *addr) {
2936 struct in6_addr tmp_addr;
2937 struct subnet *subnet;
2942 memcpy(&tmp_addr, addr->
iabuf,
sizeof(tmp_addr));
2948 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
2954 for (subnet = reply->shared->subnets ; subnet != NULL ;
2968 if (address_is_owned(reply, addr))
2974 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
2981 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
2997 if (iasubopt_allocate(&reply->lease,
MDL) != ISC_R_SUCCESS)
2999 reply->lease->addr = tmp_addr;
3000 reply->lease->plen = 0;
3012 find_client_temporaries(
struct reply_state *reply) {
3016 isc_result_t status = ISC_R_NORESOURCES;;
3017 unsigned int attempts;
3018 struct iaddr send_addr;
3024 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3028 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3038 log_debug(
"Unable to get client addresses: "
3039 "no IPv6 pools on this shared network");
3040 return ISC_R_NORESOURCES;
3050 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3057 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3066 &reply->client_id,
cur_time + 120);
3067 if (status != ISC_R_SUCCESS) {
3068 log_debug(
"Unable to get a temporary address.");
3072 status = reply_process_is_addressed(reply,
3073 &reply->lease->scope,
3075 if (status != ISC_R_SUCCESS) {
3079 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3080 status = reply_process_send_addr(reply, &send_addr);
3081 if (status != ISC_R_SUCCESS) {
3093 if (reply->lease != NULL) {
3104 reply_process_try_addr(
struct reply_state *reply,
struct iaddr *addr) {
3105 isc_result_t status = ISC_R_ADDRNOTAVAIL;
3111 if ((reply == NULL) || (reply->shared == NULL) ||
3112 (addr == NULL) || (reply->lease != NULL))
3119 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3123 for (i = 0; ; i++) {
3125 if ((pool == NULL) ||
3135 return (ISC_R_ADDRNOTAVAIL);
3138 memset(&data_addr, 0,
sizeof(data_addr));
3139 data_addr.len = addr->
len;
3140 data_addr.data = addr->
iabuf;
3153 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3160 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
3164 status = try_client_v6_address(&reply->lease, pool,
3166 if (status == ISC_R_SUCCESS)
3170 if (status == ISC_R_SUCCESS)
3185 find_client_address(
struct reply_state *reply) {
3186 struct iaddr send_addr;
3187 isc_result_t status = ISC_R_NORESOURCES;
3188 struct iasubopt *lease, *best_lease = NULL;
3190 struct group *group;
3193 if (reply->static_lease) {
3194 if (reply->host == NULL)
3198 memcpy(send_addr.iabuf, reply->fixed.data, 16);
3201 group = reply->subnet->group;
3205 if (reply->old_ia != NULL) {
3206 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
3210 lease = reply->old_ia->iasubopt[i];
3219 if ((candidate_shared != reply->shared) ||
3229 best_lease = lease_compare(lease, best_lease);
3237 status = pick_v6_address(reply);
3238 }
else if (best_lease != NULL) {
3240 status = ISC_R_SUCCESS;
3244 if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
3246 log_error(
"Reclaiming abandoned addresses is not yet "
3247 "supported. Treating this as an out of space "
3253 if (status != ISC_R_SUCCESS)
3256 if (reply->lease == NULL)
3263 scope = &reply->lease->scope;
3264 group = reply->lease->ipv6_pool->ipv6_pond->group;
3267 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3270 status = reply_process_is_addressed(reply, scope, group);
3271 if (status != ISC_R_SUCCESS)
3274 status = reply_process_send_addr(reply, &send_addr);
3283 reply_process_is_addressed(
struct reply_state *reply,
3286 isc_result_t status = ISC_R_SUCCESS;
3294 memset(&data, 0,
sizeof(data));
3303 on_star = &reply->lease->on_star;
3305 on_star = &reply->on_star;
3315 reply->packet->options, tmp_options,
3318 if (tmp_options != NULL) {
3328 reply->packet->options, reply->opt_state,
3332 for (i = reply->packet->class_count; i > 0; i--) {
3334 reply->packet->options,
3335 reply->opt_state, scope,
3336 reply->packet->classes[i - 1]->group,
3345 if (reply->host != NULL)
3347 reply->packet->options,
3348 reply->opt_state, scope,
3349 reply->host->group, group,
3353 if (reply->client_valid == 0)
3356 reply->send_valid = reply->client_valid;
3362 reply->packet->options,
3366 log_error(
"reply_process_is_addressed: unable to "
3367 "evaluate default lease time");
3368 status = ISC_R_FAILURE;
3372 reply->send_valid =
getULong(data.data);
3376 if (reply->client_prefer == 0)
3377 reply->send_prefer = reply->send_valid;
3379 reply->send_prefer = reply->client_prefer;
3381 if (reply->send_prefer >= reply->send_valid)
3382 reply->send_prefer = (reply->send_valid / 2) +
3383 (reply->send_valid / 8);
3389 reply->packet->options,
3393 log_error(
"reply_process_is_addressed: unable to "
3394 "evaluate preferred lease time");
3395 status = ISC_R_FAILURE;
3399 reply->send_prefer =
getULong(data.data);
3404 if (reply->prefer > reply->send_prefer)
3405 reply->prefer = reply->send_prefer;
3407 if (reply->valid > reply->send_valid)
3408 reply->valid = reply->send_valid;
3420 if (reply->host != NULL)
3422 reply->client_id->len);
3426 if (reply->lease != NULL) {
3428 reply->lease->prefer = reply->send_prefer;
3429 reply->lease->valid = reply->send_valid;
3433 reply->lease->soft_lifetime_end_time =
3439 if (status != ISC_R_SUCCESS) {
3440 log_fatal(
"reply_process_is_addressed: Unable to "
3441 "attach lease to new IA: %s",
3442 isc_result_totext(status));
3448 if (reply->lease->ia == NULL) {
3455 reply->packet->options, reply->reply_ia,
3459 for (i = reply->packet->class_count; i > 0; i--) {
3461 reply->packet->options,
3462 reply->reply_ia, scope,
3463 reply->packet->classes[i - 1]->group,
3471 if (reply->host != NULL)
3473 reply->packet->options,
3474 reply->reply_ia, scope,
3475 reply->host->group, group, NULL);
3478 if (data.data != NULL)
3481 if (status == ISC_R_SUCCESS)
3482 reply->client_resources++;
3489 reply_process_send_addr(
struct reply_state *reply,
struct iaddr *addr) {
3490 isc_result_t status = ISC_R_SUCCESS;
3498 log_error(
"reply_process_send_addr: out of memory"
3499 "allocating new IAADDR buffer.");
3500 status = ISC_R_NOMEMORY;
3505 memcpy(
data.buffer->data, addr->
iabuf, 16);
3512 log_error(
"reply_process_send_addr: unable "
3513 "to save IAADDR option");
3514 status = ISC_R_FAILURE;
3518 reply->resources_included = ISC_TRUE;
3521 if (
data.data != NULL)
3535 switch(alpha->
state) {
3537 switch(beta->
state) {
3558 switch (beta->
state) {
3584 switch (beta->
state) {
3604 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
3612 reply_process_ia_pd(
struct reply_state *reply,
struct option_cache *ia) {
3613 isc_result_t status = ISC_R_SUCCESS;
3622 memset(&ia_data, 0,
sizeof(ia_data));
3629 if ((reply->cursor +
IA_PD_OFFSET + 4) >
sizeof(reply->buf)) {
3630 log_error(
"reply_process_ia_pd: Reply too long for IA.");
3631 return ISC_R_NOSPACE;
3636 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
3638 log_error(
"reply_process_ia_pd: error evaluating ia");
3639 status = ISC_R_FAILURE;
3645 reply->renew =
getULong(ia_data.data + 4);
3646 reply->rebind =
getULong(ia_data.data + 8);
3649 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
3650 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
3651 log_error(
"reply_process_ia_pd: no memory for ia.");
3652 status = ISC_R_NOMEMORY;
3659 (
unsigned char *)reply->ia->iaid_duid.data,
3660 reply->ia->iaid_duid.len,
MDL);
3667 status = ISC_R_NOMEMORY;
3672 reply->static_prefixes = 0;
3673 if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
3676 for (fp = reply->host->fixed_prefix; fp != NULL;
3678 reply->static_prefixes += 1;
3688 ia_cursor = reply->cursor;
3695 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
3699 putULong(reply->buf.data + reply->cursor, iaid);
3703 putULong(reply->buf.data + reply->cursor, reply->renew);
3707 putULong(reply->buf.data + reply->cursor, reply->rebind);
3714 reply->valid = reply->prefer = 0xffffffff;
3715 reply->client_valid = reply->client_prefer = 0;
3716 reply->preflen = -1;
3717 for (; oc != NULL ; oc = oc->
next) {
3718 status = reply_process_prefix(reply, oc);
3726 if (status == ISC_R_CANCELED)
3729 if ((status != ISC_R_SUCCESS) &&
3730 (status != ISC_R_ADDRINUSE) &&
3731 (status != ISC_R_ADDRNOTAVAIL))
3741 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
3742 status = find_client_prefix(reply);
3744 if (status == ISC_R_NORESOURCES) {
3745 switch (reply->packet->dhcpv6_msg_type) {
3760 "memory for option state "
3762 status = ISC_R_NOMEMORY;
3767 "No prefixes available "
3768 "for this interface.",
3772 "NoPrefixAvail status "
3774 status = ISC_R_FAILURE;
3778 status = ISC_R_SUCCESS;
3782 if (reply->resources_included)
3783 status = ISC_R_SUCCESS;
3790 if (status != ISC_R_SUCCESS)
3794 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
3795 sizeof(reply->buf) - reply->cursor,
3796 reply->reply_ia, reply->packet,
3797 required_opts_IA_PD, NULL);
3800 putUShort(reply->buf.data + ia_cursor + 2,
3801 reply->cursor - (ia_cursor + 4));
3814 reply->packet->options,
3820 reply->renew =
getULong(data.data);
3823 if (data.data != NULL)
3826 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
3834 reply->packet->options,
3840 reply->rebind =
getULong(data.data);
3843 if (data.data != NULL)
3846 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
3852 if (status == ISC_R_CANCELED)
3859 if (reply->static_prefixes != 0) {
3860 char tmp_addr[INET6_ADDRSTRLEN];
3861 log_info(
"%s PD: address %s/%d to client with duid %s "
3864 inet_ntop(AF_INET6, reply->fixed_pref.lo_addr.iabuf,
3865 tmp_addr,
sizeof(tmp_addr)),
3866 reply->fixed_pref.bits,
3868 reply->client_id.data, 60),
3871 (reply->on_star.on_commit != NULL)) {
3873 reply->packet->options,
3875 NULL, reply->on_star.on_commit,
3878 (&reply->on_star.on_commit,
MDL);
3886 if (reply->ia->num_iasubopt != 0) {
3889 char tmp_addr[INET6_ADDRSTRLEN];
3891 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3892 tmp = reply->ia->iasubopt[i];
3894 log_info(
"%s PD: address %s/%d to client with duid %s"
3895 " iaid = %d valid for %d seconds",
3897 inet_ntop(AF_INET6, &tmp->
addr,
3898 tmp_addr,
sizeof(tmp_addr)),
3901 reply->client_id.data, 60),
3915 (reply->ia->num_iasubopt != 0)) {
3920 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3921 tmp = reply->ia->iasubopt[i];
3923 if (tmp->
ia != NULL)
3935 reply->packet->options,
3945 check_pool6_threshold(reply, tmp);
3949 if (reply->old_ia != NULL) {
3950 ia_id = &reply->old_ia->iaid_duid;
3952 (
unsigned char *)ia_id->
data,
3959 ia_id = &reply->ia->iaid_duid;
3961 ia_id->
len, reply->ia,
MDL);
3965 schedule_lease_timeout_reply(reply);
3969 if (packet_ia != NULL)
3971 if (reply->reply_ia != NULL)
3973 if (ia_data.data != NULL)
3975 if (
data.data != NULL)
3977 if (reply->ia != NULL)
3979 if (reply->old_ia != NULL)
3981 if (reply->lease != NULL)
3983 if (reply->on_star.on_expiry != NULL)
3985 (&reply->on_star.on_expiry,
MDL);
3986 if (reply->on_star.on_release != NULL)
3988 (&reply->on_star.on_release,
MDL);
3995 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
4005 reply_process_prefix(
struct reply_state *reply,
struct option_cache *pref) {
4006 u_int32_t pref_life, valid_life;
4011 isc_result_t status = ISC_R_SUCCESS;
4012 struct group *group;
4015 memset(&iapref, 0,
sizeof(iapref));
4016 memset(&data, 0,
sizeof(data));
4023 if ((reply->cursor + 29) >
sizeof(reply->buf)) {
4024 log_error(
"reply_process_prefix: Out of room for prefix.");
4025 return ISC_R_NOSPACE;
4033 log_error(
"reply_process_prefix: error evaluating IAPREFIX.");
4034 status = ISC_R_FAILURE;
4043 valid_life =
getULong(iapref.data + 4);
4045 if ((reply->client_valid == 0) ||
4046 (reply->client_valid > valid_life))
4047 reply->client_valid = valid_life;
4049 if ((reply->client_prefer == 0) ||
4050 (reply->client_prefer > pref_life))
4051 reply->client_prefer = pref_life;
4057 tmp_pref.lo_addr.len = 16;
4058 memset(tmp_pref.lo_addr.iabuf, 0, 16);
4059 if ((iapref.data[8] == 0) &&
4060 (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
4069 tmp_pref.bits = (
int) iapref.data[8];
4070 if (reply->preflen < 0) {
4072 reply->preflen = tmp_pref.bits;
4074 if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
4078 memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
4081 if (!prefix_is_owned(reply, &tmp_pref)) {
4086 status = reply_process_try_prefix(reply, &tmp_pref);
4089 if ((status != ISC_R_SUCCESS) &&
4090 (status != ISC_R_ADDRINUSE) &&
4091 (status != ISC_R_ADDRNOTAVAIL))
4094 if (reply->lease == NULL) {
4095 if (reply->packet->dhcpv6_msg_type ==
4097 reply->send_prefer = 0;
4098 reply->send_valid = 0;
4117 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
4121 log_error(
"reply_process_prefix: No memory "
4122 "for option state wipe.");
4123 status = ISC_R_NOMEMORY;
4129 "Prefix not bound to this "
4130 "interface.", reply->reply_ia)) {
4131 log_error(
"reply_process_prefix: Unable to "
4132 "attach status code.");
4133 status = ISC_R_FAILURE;
4138 status = ISC_R_CANCELED;
4141 log_error(
"It is impossible to lease a client that is "
4142 "not sending a solicit, request, renew, or "
4144 status = ISC_R_FAILURE;
4149 if (reply->static_prefixes > 0) {
4150 if (reply->host == NULL)
4157 tmp_pref.lo_addr,
MDL) == 0)
4159 group = reply->subnet->group;
4160 subnet_dereference(&reply->subnet,
MDL);
4163 memcpy(&reply->fixed_pref, &tmp_pref,
sizeof(tmp_pref));
4165 if (reply->lease == NULL)
4168 scope = &reply->lease->scope;
4169 group = reply->lease->ipv6_pool->ipv6_pond->group;
4178 if (reply->client_resources != 0) {
4191 reply->packet->options,
4195 log_error(
"reply_process_prefix: unable to "
4196 "evaluate prefs-per-ia value.");
4197 status = ISC_R_FAILURE;
4209 if (reply->client_resources >= limit)
4213 status = reply_process_is_prefixed(reply, scope, group);
4214 if (status != ISC_R_SUCCESS)
4218 status = reply_process_send_prefix(reply, &tmp_pref);
4221 if (iapref.data != NULL)
4223 if (data.data != NULL)
4225 if (reply->lease != NULL)
4237 static isc_boolean_t
4238 prefix_is_owned(
struct reply_state *reply,
struct iaddrcidrnet *pref) {
4246 if (reply->static_prefixes > 0) {
4247 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4256 if ((reply->old_ia == NULL) ||
4257 (reply->old_ia->num_iasubopt == 0))
4260 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4263 tmp = reply->old_ia->iasubopt[i];
4265 if ((pref->
bits == (
int) tmp->
plen) &&
4291 reply_process_try_prefix(
struct reply_state *reply,
4293 isc_result_t status = ISC_R_ADDRNOTAVAIL;
4299 if ((reply == NULL) || (reply->shared == NULL) ||
4300 (pref == NULL) || (reply->lease != NULL))
4307 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4311 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4321 return (ISC_R_ADDRNOTAVAIL);
4324 memset(&data_pref, 0,
sizeof(data_pref));
4327 log_error(
"reply_process_try_prefix: out of memory.");
4328 return (ISC_R_NOMEMORY);
4330 data_pref.data = data_pref.buffer->data;
4331 data_pref.buffer->data[0] = (u_int8_t) pref->
bits;
4332 memcpy(data_pref.buffer->data + 1, pref->
lo_addr.
iabuf, 16);
4342 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4349 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4354 status = try_client_v6_prefix(&reply->lease, pool,
4358 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4361 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4375 find_client_prefix(
struct reply_state *reply) {
4377 isc_result_t status = ISC_R_NORESOURCES;
4378 struct iasubopt *prefix, *best_prefix = NULL;
4381 struct group *group;
4383 if (reply->static_prefixes > 0) {
4386 if (reply->host == NULL)
4389 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4398 l = reply->host->fixed_prefix;
4400 memcpy(&send_pref, &l->
cidrnet,
sizeof(send_pref));
4406 send_pref.lo_addr,
MDL) == 0)
4408 group = reply->subnet->group;
4409 subnet_dereference(&reply->subnet,
MDL);
4412 memcpy(&reply->fixed_pref, &l->
cidrnet,
sizeof(send_pref));
4417 if (reply->old_ia != NULL) {
4418 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4422 prefix = reply->old_ia->iasubopt[i];
4431 if (((candidate_shared != NULL) &&
4432 (candidate_shared != reply->shared)) ||
4446 best_prefix = prefix_compare(reply, prefix,
4455 status = pick_v6_prefix(reply);
4456 }
else if (best_prefix != NULL) {
4458 status = ISC_R_SUCCESS;
4462 if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
4464 log_error(
"Reclaiming abandoned prefixes is not yet "
4465 "supported. Treating this as an out of space "
4471 if (status != ISC_R_SUCCESS)
4474 if (reply->lease == NULL)
4477 scope = &reply->lease->scope;
4478 group = reply->lease->ipv6_pool->ipv6_pond->group;
4480 send_pref.lo_addr.len = 16;
4481 memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
4482 send_pref.bits = (
int) reply->lease->plen;
4485 status = reply_process_is_prefixed(reply, scope, group);
4486 if (status != ISC_R_SUCCESS)
4489 status = reply_process_send_prefix(reply, &send_pref);
4498 reply_process_is_prefixed(
struct reply_state *reply,
4501 isc_result_t status = ISC_R_SUCCESS;
4505 struct on_star *on_star;
4509 memset(&data, 0,
sizeof(data));
4518 on_star = &reply->lease->on_star;
4520 on_star = &reply->on_star;
4530 reply->packet->options, tmp_options,
4533 if (tmp_options != NULL) {
4543 reply->packet->options, reply->opt_state,
4547 for (i = reply->packet->class_count; i > 0; i--) {
4549 reply->packet->options,
4550 reply->opt_state, scope,
4551 reply->packet->classes[i - 1]->group,
4560 if (reply->host != NULL)
4562 reply->packet->options,
4563 reply->opt_state, scope,
4564 reply->host->group, group,
4568 if (reply->client_valid == 0)
4571 reply->send_valid = reply->client_valid;
4577 reply->packet->options,
4581 log_error(
"reply_process_is_prefixed: unable to "
4582 "evaluate default prefix time");
4583 status = ISC_R_FAILURE;
4587 reply->send_valid =
getULong(data.data);
4591 if (reply->client_prefer == 0)
4592 reply->send_prefer = reply->send_valid;
4594 reply->send_prefer = reply->client_prefer;
4596 if (reply->send_prefer >= reply->send_valid)
4597 reply->send_prefer = (reply->send_valid / 2) +
4598 (reply->send_valid / 8);
4604 reply->packet->options,
4608 log_error(
"reply_process_is_prefixed: unable to "
4609 "evaluate preferred prefix time");
4610 status = ISC_R_FAILURE;
4614 reply->send_prefer =
getULong(data.data);
4619 if (reply->prefer > reply->send_prefer)
4620 reply->prefer = reply->send_prefer;
4622 if (reply->valid > reply->send_valid)
4623 reply->valid = reply->send_valid;
4626 if (reply->lease != NULL) {
4628 reply->lease->prefer = reply->send_prefer;
4629 reply->lease->valid = reply->send_valid;
4633 reply->lease->soft_lifetime_end_time =
4639 if (status != ISC_R_SUCCESS) {
4640 log_fatal(
"reply_process_is_prefixed: Unable to "
4641 "attach prefix to new IA_PD: %s",
4642 isc_result_totext(status));
4648 if (reply->lease->ia == NULL) {
4655 reply->packet->options, reply->reply_ia,
4659 for (i = reply->packet->class_count; i > 0; i--) {
4661 reply->packet->options,
4662 reply->reply_ia, scope,
4663 reply->packet->classes[i - 1]->group,
4671 if (reply->host != NULL)
4673 reply->packet->options,
4674 reply->reply_ia, scope,
4675 reply->host->group, group, NULL);
4678 if (data.data != NULL)
4681 if (status == ISC_R_SUCCESS)
4682 reply->client_resources++;
4689 reply_process_send_prefix(
struct reply_state *reply,
4691 isc_result_t status = ISC_R_SUCCESS;
4699 log_error(
"reply_process_send_prefix: out of memory"
4700 "allocating new IAPREFIX buffer.");
4701 status = ISC_R_NOMEMORY;
4714 log_error(
"reply_process_send_prefix: unable "
4715 "to save IAPREFIX option");
4716 status = ISC_R_FAILURE;
4720 reply->resources_included = ISC_TRUE;
4723 if (
data.data != NULL)
4731 prefix_compare(
struct reply_state *reply,
4738 if (reply->preflen >= 0) {
4739 if ((alpha->
plen == reply->preflen) &&
4740 (beta->
plen != reply->preflen))
4742 if ((beta->
plen == reply->preflen) &&
4743 (alpha->
plen != reply->preflen))
4747 switch(alpha->
state) {
4749 switch(beta->
state) {
4770 switch (beta->
state) {
4796 switch (beta->
state) {
4816 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
4830 dhcpv6_solicit(
struct data_string *reply_ret,
struct packet *packet) {
4838 if (!valid_client_msg(packet, &client_id)) {
4842 lease_to_client(reply_ret, packet, &client_id, NULL);
4859 dhcpv6_request(
struct data_string *reply_ret,
struct packet *packet) {
4868 if (!valid_client_resp(packet, &client_id, &server_id)) {
4875 lease_to_client(reply_ret, packet, &client_id, &server_id);
4890 struct packet *packet)
4892 const struct packet *chk_packet;
4893 const struct in6_addr *link_addr, *first_link_addr;
4894 struct iaddr tmp_addr;
4895 struct subnet *subnet;
4896 isc_result_t status;
4898 if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
4905 first_link_addr = NULL;
4907 while (chk_packet != NULL) {
4909 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
4910 !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
4911 first_link_addr = link_addr;
4922 if (first_link_addr != NULL) {
4923 tmp_addr.len =
sizeof(*first_link_addr);
4924 memcpy(tmp_addr.iabuf,
4925 first_link_addr,
sizeof(*first_link_addr));
4928 log_debug(
"No subnet found for link-address %s.",
4930 return ISC_R_NOTFOUND;
4932 status = shared_network_reference(shared,
4934 subnet_dereference(&subnet,
MDL);
4941 status = shared_network_reference(shared,
4945 log_info(
"[L2 Relay] No link address in relay packet "
4946 "assuming L2 relay and using receiving "
4956 log_error(
"No interface and no link address "
4957 "can't determine pool");
4983 dhcpv6_confirm(
struct data_string *reply_ret,
struct packet *packet) {
4985 struct subnet *subnet;
4987 struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
4989 struct iaddr cli_addr;
4991 isc_boolean_t inappropriate, has_addrs;
4992 char reply_data[65536];
5001 memset(&client_id, 0,
sizeof(client_id));
5002 if (!valid_client_msg(packet, &client_id)) {
5011 if ((ia == NULL) && (ta == NULL))
5022 opt_state = cli_enc_opt_state = NULL;
5023 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5024 memset(&iaaddr, 0,
sizeof(iaaddr));
5025 memset(&packet_oro, 0,
sizeof(packet_oro));
5032 if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
5044 has_addrs = inappropriate = ISC_FALSE;
5046 while(!inappropriate) {
5050 if ((pass ==
D6O_IA_NA) && (ia == NULL)) {
5060 !get_encapsulated_IA_state(&cli_enc_opt_state,
5064 !get_encapsulated_IA_state(&cli_enc_opt_state,
5073 for ( ; oc != NULL ; oc = oc->
next) {
5079 "error evaluating IAADDR.");
5085 memcpy(cli_addr.iabuf, iaaddr.data, 16);
5090 has_addrs = ISC_TRUE;
5093 for (subnet = shared->
subnets ; subnet != NULL ;
5108 if (subnet == NULL) {
5109 inappropriate = ISC_TRUE;
5128 if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
5135 if (inappropriate) {
5137 "Some of the addresses are not on link.",
5143 "All addresses still on link.",
5153 sizeof(reply_data)-reply_ofs,
5155 required_opts, &packet_oro);
5160 reply_ret->
len = reply_ofs;
5161 reply_ret->
buffer = NULL;
5166 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5170 if (cli_enc_opt_data.buffer != NULL)
5172 if (iaaddr.buffer != NULL)
5174 if (client_id.
buffer != NULL)
5176 if (packet_oro.buffer != NULL)
5180 if (cli_enc_opt_state != NULL)
5182 if (opt_state != NULL)
5196 dhcpv6_renew(
struct data_string *reply,
struct packet *packet) {
5205 if (!valid_client_resp(packet, &client_id, &server_id)) {
5212 lease_to_client(reply, packet, &client_id, &server_id);
5231 dhcpv6_rebind(
struct data_string *reply,
struct packet *packet) {
5236 if (!valid_client_msg(packet, &client_id)) {
5240 lease_to_client(reply, packet, &client_id, NULL);
5248 ia_na_match_decline(
const struct data_string *client_id,
5252 char tmp_addr[INET6_ADDRSTRLEN];
5254 log_error(
"Client %s reports address %s is "
5255 "already in use by another host!",
5257 inet_ntop(AF_INET6, iaaddr->
data,
5258 tmp_addr,
sizeof(tmp_addr)));
5259 if (lease != NULL) {
5267 ia_na_nomatch_decline(
const struct data_string *client_id,
5269 u_int32_t *ia_na_id,
5270 struct packet *packet,
5275 char tmp_addr[INET6_ADDRSTRLEN];
5279 log_info(
"Client %s declines address %s, which is not offered to it.",
5281 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5286 host_opt_state = NULL;
5288 log_error(
"ia_na_nomatch_decline: out of memory "
5289 "allocating option_state.");
5301 if (reply_len < (*reply_ofs + 16)) {
5303 "out of space for reply packet.");
5311 reply_len-(*reply_ofs)-16,
5312 host_opt_state, packet,
5313 required_opts_STATUS_CODE, NULL);
5323 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5325 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5327 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5328 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5333 *reply_ofs += (len + 16);
5341 struct packet *packet,
5344 const char *packet_type,
5345 void (*ia_na_match)(),
5346 void (*ia_na_nomatch)())
5359 char reply_data[65536];
5362 char status_msg[32];
5364 struct ia_xx *existing_ia_na;
5373 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5374 cli_enc_opt_state = NULL;
5375 memset(&iaaddr, 0,
sizeof(iaaddr));
5376 memset(&fixed_addr, 0,
sizeof(fixed_addr));
5377 host_opt_state = NULL;
5397 if (!find_hosts_by_duid_chaddr(&packet_host,
5415 log_error(
"iterate_over_ia_na: no memory for option_state.");
5428 (
unsigned char *)server_duid.data,
5431 "error saving server identifier.");
5438 (
unsigned char *)client_id->
data,
5442 "error saving client identifier.");
5447 if ((packet->
unicast == ISC_TRUE) && !is_unicast_option_defined()) {
5467 snprintf(status_msg,
sizeof(status_msg),
5468 "%s received unicast.", packet_type);
5481 sizeof(reply_data)-reply_ofs,
5483 required_opts_NAA, NULL);
5487 snprintf(status_msg,
sizeof(status_msg),
"%s received.", packet_type);
5496 sizeof(reply_data)-reply_ofs,
5498 required_opts, NULL);
5506 ia != NULL; ia = ia->
next) {
5508 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5514 iaid =
getULong(cli_enc_opt_data.data);
5532 memset(&iaaddr, 0,
sizeof(iaaddr));
5537 "error evaluating IAADDR.");
5551 cli_enc_opt_state,
MDL)) {
5552 if (packet_host != NULL) {
5558 while (host != NULL) {
5566 "evaluating host address.");
5569 if ((iaaddr.
len >= 16) &&
5570 !memcmp(fixed_addr.data, iaaddr.
data, 16)) {
5584 (
char *)client_id->
data,
5586 MDL) != ISC_R_SUCCESS) {
5587 log_fatal(
"iterate_over_ia_na: no memory for "
5591 existing_ia_na = NULL;
5593 (
unsigned char *)key.data,
5600 struct in6_addr *in6_addr;
5603 in6_addr = &tmp->
addr;
5604 if (memcmp(in6_addr,
5605 iaaddr.
data, 16) == 0) {
5616 if ((host != NULL) || (lease != NULL)) {
5617 ia_na_match(client_id, &iaaddr, lease);
5619 ia_na_nomatch(client_id, &iaaddr,
5620 (u_int32_t *)cli_enc_opt_data.
data,
5621 packet, reply_data, &reply_ofs,
5622 sizeof(reply_data));
5625 if (lease != NULL) {
5638 reply_ret->
len = reply_ofs;
5639 reply_ret->
buffer = NULL;
5644 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5647 if (lease != NULL) {
5650 if (host_opt_state != NULL) {
5653 if (fixed_addr.buffer != NULL) {
5656 if (iaaddr.
buffer != NULL) {
5659 if (cli_enc_opt_state != NULL) {
5662 if (cli_enc_opt_data.buffer != NULL) {
5665 if (opt_state != NULL) {
5685 dhcpv6_decline(
struct data_string *reply,
struct packet *packet) {
5694 if (!valid_client_resp(packet, &client_id, &server_id)) {
5706 iterate_over_ia_na(reply, packet, &client_id, &server_id,
"Decline",
5707 ia_na_match_decline, ia_na_nomatch_decline);
5716 ia_na_match_release(
const struct data_string *client_id,
5720 char tmp_addr[INET6_ADDRSTRLEN];
5722 log_info(
"Client %s releases address %s",
5724 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5725 if (lease != NULL) {
5733 ia_na_nomatch_release(
const struct data_string *client_id,
5735 u_int32_t *ia_na_id,
5736 struct packet *packet,
5741 char tmp_addr[INET6_ADDRSTRLEN];
5745 log_info(
"Client %s releases address %s, which is not leased to it.",
5747 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5752 host_opt_state = NULL;
5754 log_error(
"ia_na_nomatch_release: out of memory "
5755 "allocating option_state.");
5760 "Release for non-leased address.",
5768 if (reply_len < (*reply_ofs + 16)) {
5770 "out of space for reply packet.");
5778 reply_len-(*reply_ofs)-16,
5779 host_opt_state, packet,
5780 required_opts_STATUS_CODE, NULL);
5790 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5792 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5794 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5795 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5800 *reply_ofs += (len + 16);
5807 ia_pd_match_release(
const struct data_string *client_id,
5811 char tmp_addr[INET6_ADDRSTRLEN];
5813 log_info(
"Client %s releases prefix %s/%u",
5815 inet_ntop(AF_INET6, iapref->
data + 9,
5816 tmp_addr,
sizeof(tmp_addr)),
5818 if (prefix != NULL) {
5826 ia_pd_nomatch_release(
const struct data_string *client_id,
5828 u_int32_t *ia_pd_id,
5829 struct packet *packet,
5834 char tmp_addr[INET6_ADDRSTRLEN];
5838 log_info(
"Client %s releases prefix %s/%u, which is not leased to it.",
5840 inet_ntop(AF_INET6, iapref->
data + 9,
5841 tmp_addr,
sizeof(tmp_addr)),
5847 host_opt_state = NULL;
5849 log_error(
"ia_pd_nomatch_release: out of memory "
5850 "allocating option_state.");
5855 "Release for non-leased prefix.",
5863 if (reply_len < (*reply_ofs + 16)) {
5865 "out of space for reply packet.");
5873 reply_len-(*reply_ofs)-16,
5874 host_opt_state, packet,
5875 required_opts_STATUS_CODE, NULL);
5885 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5887 memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
5889 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5890 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5895 *reply_ofs += (len + 16);
5903 struct packet *packet,
5906 const char *packet_type,
5907 void (*ia_pd_match)(),
5908 void (*ia_pd_nomatch)())
5922 char reply_data[65536];
5925 struct ia_xx *existing_ia_pd;
5933 memset(&reply_new, 0,
sizeof(reply_new));
5935 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5936 cli_enc_opt_state = NULL;
5937 memset(&iaprefix, 0,
sizeof(iaprefix));
5938 host_opt_state = NULL;
5944 reply_len =
sizeof(reply_data) - reply_ret->
len;
5964 if (!find_hosts_by_duid_chaddr(&packet_host,
5975 log_error(
"iterate_over_ia_pd: no memory for option_state.");
5987 ia != NULL; ia = ia->
next) {
5989 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5995 iaid =
getULong(cli_enc_opt_data.data);
6006 for (; oc != NULL; oc = oc->
next) {
6007 memset(&iaprefix, 0,
sizeof(iaprefix));
6012 "error evaluating IAPREFIX.");
6026 cli_enc_opt_state,
MDL)) {
6027 if (packet_host != NULL) {
6033 while (host != NULL) {
6042 if (memcmp(iaprefix.data + 9,
6047 if ((l != NULL) && (iaprefix.len >= 17))
6058 (
char *)client_id->
data,
6060 MDL) != ISC_R_SUCCESS) {
6061 log_fatal(
"iterate_over_ia_pd: no memory for "
6065 existing_ia_pd = NULL;
6067 (
unsigned char *)key.data,
6078 plen =
getUChar(iaprefix.data + 8);
6080 if ((tmp->
plen == plen) &&
6094 if ((host != NULL) || (prefix != NULL)) {
6095 ia_pd_match(client_id, &iaprefix, prefix);
6097 ia_pd_nomatch(client_id, &iaprefix,
6098 (u_int32_t *)cli_enc_opt_data.
data,
6099 packet, reply_data, &reply_ofs,
6100 reply_len - reply_ofs);
6103 if (prefix != NULL) {
6118 reply_new.len = reply_ret->
len + reply_ofs;
6122 reply_new.data = reply_new.buffer->data;
6123 memcpy(reply_new.buffer->data,
6125 memcpy(reply_new.buffer->data + reply_ret->
len,
6126 reply_data, reply_ofs);
6132 if (prefix != NULL) {
6135 if (host_opt_state != NULL) {
6138 if (iaprefix.buffer != NULL) {
6141 if (cli_enc_opt_state != NULL) {
6144 if (cli_enc_opt_data.buffer != NULL) {
6147 if (opt_state != NULL) {
6157 dhcpv6_release(
struct data_string *reply,
struct packet *packet) {
6166 if (!valid_client_resp(packet, &client_id, &server_id)) {
6173 iterate_over_ia_na(reply, packet, &client_id, &server_id,
"Release",
6174 ia_na_match_release, ia_na_nomatch_release);
6179 iterate_over_ia_pd(reply, packet, &client_id, &server_id,
"Release",
6180 ia_pd_match_release, ia_pd_nomatch_release);
6194 dhcpv6_information_request(
struct data_string *reply,
struct packet *packet) {
6203 if (!valid_client_info_req(packet, &server_id)) {
6210 memset(&client_id, 0,
sizeof(client_id));
6221 lease_to_client(reply, packet, &client_id,
6222 server_id.
data != NULL ? &server_id : NULL);
6227 if (client_id.
data != NULL) {
6245 dhcpv6_relay_forw(
struct data_string *reply_ret,
struct packet *packet) {
6248 struct packet *enc_packet;
6249 unsigned char msg_type;
6253 char link_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6254 char peer_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6257 static char reply_data[65536];
6267 memset(&a_opt, 0,
sizeof(a_opt));
6268 memset(&packet_ero, 0,
sizeof(packet_ero));
6269 memset(&enc_reply, 0,
sizeof(enc_reply));
6270 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6279 link_addr,
sizeof(link_addr));
6281 peer_addr,
sizeof(peer_addr));
6282 log_info(
"Relay-forward from %s with link address=%s and "
6283 "peer address=%s missing Relay Message option.",
6290 log_error(
"dhcpv6_forw_relay: error evaluating "
6291 "relayed message.");
6296 log_error(
"dhcpv6_forw_relay: encapsulated packet too short.");
6306 "no memory for encapsulated packet.");
6312 "no memory for encapsulated packet's options.");
6321 msg_type = enc_opt_data.
data[0];
6337 enc_opt_data.
len - relaylen,
6355 enc_opt_data.
len - msglen,
6367 build_dhcpv6_reply(&enc_reply, enc_packet);
6373 if (enc_reply.data == NULL) {
6395 log_error(
"dhcpv6_relay_forw: no memory for option state.");
6409 log_error(
"dhcpv6_relay_forw: error evaluating "
6414 (
unsigned char *)a_opt.data,
6417 log_error(
"dhcpv6_relay_forw: error saving "
6428 (
unsigned char *)enc_reply.data,
6431 log_error(
"dhcpv6_relay_forw: error saving Relay MSG.");
6447 (packet_ero.len & 1)) {
6448 log_error(
"dhcpv6_relay_forw: error evaluating ERO.");
6453 for (i = 0; i < packet_ero.len; i += 2) {
6470 "evaluating option %u.", req);
6476 (
unsigned char *)a_opt.data,
6480 log_error(
"dhcpv6_relay_forw: error saving "
6489 sizeof(reply_data) - reply_ofs,
6491 required_opts_agent, &packet_ero);
6496 reply_ret->
len = reply_ofs;
6497 reply_ret->
buffer = NULL;
6502 memcpy(reply_ret->
buffer->
data, reply_data, reply_ofs);
6505 if (opt_state != NULL)
6507 if (a_opt.data != NULL) {
6510 if (packet_ero.data != NULL) {
6513 if (enc_reply.data != NULL) {
6516 if (enc_opt_data.
data != NULL) {
6519 if (enc_packet != NULL) {
6527 dhcpv6_discard(
struct packet *packet) {
6531 log_debug(
"Discarding %s from %s; message type not handled by server",
6537 build_dhcpv6_reply(
struct data_string *reply,
struct packet *packet) {
6538 memset(reply, 0,
sizeof(*reply));
6551 dhcpv6_solicit(reply, packet);
6554 dhcpv6_discard(packet);
6558 dhcpv6_request(reply, packet);
6562 dhcpv6_confirm(reply, packet);
6566 dhcpv6_renew(reply, packet);
6570 dhcpv6_rebind(reply, packet);
6573 dhcpv6_discard(packet);
6577 dhcpv6_release(reply, packet);
6581 dhcpv6_decline(reply, packet);
6584 dhcpv6_discard(packet);
6588 dhcpv6_information_request(reply, packet);
6591 dhcpv6_relay_forw(reply, packet);
6594 dhcpv6_discard(packet);
6601 dhcpv6_discard(packet);
6606 log_info(
"Discarding unknown DHCPv6 message type %d "
6613 log_packet_in(
const struct packet *packet) {
6616 char tmp_addr[INET6_ADDRSTRLEN];
6619 memset(&s, 0,
sizeof(s));
6628 "Unknown message type %d from %s port %d",
6637 inet_ntop(AF_INET6, addr,
6638 tmp_addr,
sizeof(tmp_addr)));
6641 inet_ntop(AF_INET6, addr,
6642 tmp_addr,
sizeof(tmp_addr)));
6672 dhcpv6(
struct packet *packet) {
6674 struct sockaddr_in6 to_addr;
6680 log_packet_in(packet);
6685 build_dhcpv6_reply(&reply, packet);
6687 if (reply.
data != NULL) {
6691 memset(&to_addr, 0,
sizeof(to_addr));
6692 to_addr.sin6_family = AF_INET6;
6700 #if defined (REPLY_TO_SOURCE_PORT)
6712 sizeof(to_addr.sin6_addr));
6714 log_info(
"Sending %s to %s port %d",
6717 ntohs(to_addr.sin6_port));
6720 reply.
data, reply.
len, &to_addr);
6721 if (send_ret != reply.
len) {
6722 log_error(
"dhcpv6: send_packet6() sent %d of %d bytes",
6723 send_ret, reply.
len);
6739 host_reference(&hold, *hp,
MDL);
6740 host_dereference(hp,
MDL);
6742 while (seek != NULL) {
6745 else if (fixed_matches_shared(seek, shared))
6751 if ((seek == NULL) && (nofixed != NULL))
6755 host_reference(hp, seek,
MDL);
6758 static isc_boolean_t
6760 struct subnet *subnet;
6762 isc_boolean_t matched;
6768 memset(&addr, 0,
sizeof(addr));
6773 if (addr.len < 16) {
6779 memcpy(fixed.iabuf, addr.data, 16);
6781 matched = ISC_FALSE;
6782 for (subnet = shared->
subnets ; subnet != NULL ;
6801 find_hosts_by_duid_chaddr(
struct host_decl **host,
6803 static int once_htype;
6805 const unsigned char *chaddr;
6811 if (client_id->
len < 4)
6825 if (client_id->
len > 8) {
6826 hlen = client_id->
len - 8;
6827 chaddr = client_id->
data + 8;
6836 hlen = client_id->
len - 4;
6837 chaddr = client_id->
data + 4;
6857 if ((htype & 0xFF00) && !once_htype) {
6859 log_error(
"Attention: At least one client advertises a "
6860 "hardware type of %d, which exceeds the software "
6861 "limitation of 255.", htype);
struct iaddrcidrnet cidrnet
#define DHCPD_SIX_RELAY_FORW_DONE()
isc_result_t renew_lease6(struct ipv6_pool *pool, struct iasubopt *lease)
Renew a lease in the pool.
int find_grouped_subnet(struct subnet **, struct shared_network *, struct iaddr, const char *, int)
unsigned char peer_address[16]
#define DHCPD_SIX_INFORMATION_REQUEST_START()
struct binding_scope * global_scope
isc_result_t add_lease6(struct ipv6_pool *pool, struct iasubopt *lease, time_t valid_lifetime_end_time)
#define DHCPD_SIX_SOLICIT_DONE()
isc_result_t ia_make_key(struct data_string *key, u_int32_t iaid, const char *duid, unsigned int duid_len, const char *file, int line)
int executable_statement_dereference(struct executable_statement **ptr, const char *file, int line)
struct shared_network * shared_network
const char * piaddr(const struct iaddr addr)
unsigned char dhcpv6_transaction_id[3]
isc_boolean_t server_duid_isset(void)
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
void dhcpv6_leasequery(struct data_string *, struct packet *)
isc_result_t ia_dereference(struct ia_xx **ia, const char *file, int line)
#define DHCPD_SIX_RELAY_FORW_START()
int data_string_sprintfa(struct data_string *ds, const char *fmt,...)
struct universe server_universe
int execute_statements(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct executable_statement *statements, struct on_star *on_star)
isc_boolean_t lease6_usable(struct iasubopt *lease)
Check if address is available to a lease.
int find_hosts_by_option(struct host_decl **, struct packet *, struct option_state *, const char *, int)
#define print_hex_1(len, data, limit)
#define DHCP_R_INVALIDARG
#define STATUS_NoAddrsAvail
#define DHCPD_SIX_RELEASE_DONE()
const char * dhcpv6_type_names[]
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
#define DHCPV6_RECONFIGURE
#define SV_PREFER_LIFETIME
struct universe dhcp_universe
void data_string_forget(struct data_string *data, const char *file, int line)
struct option_cache * next
#define FIND_PERCENT(count, percent)
struct shared_network * shared_network
#define DHCPD_SIX_RENEW_DONE()
#define DHCPD_SIX_DECLINE_DONE()
struct option_cache * fixed_addr
struct group * root_group
void delete_option(struct universe *universe, struct option_state *options, int code)
int log_error(const char *,...) __attribute__((__format__(__printf__
struct binding_scope * scope
struct ipv6_pond * ipv6_pond
void copy_server_duid(struct data_string *ds, const char *file, int line)
#define DHO_DHCP_REBINDING_TIME
int find_hosts_by_haddr(struct host_decl **, int, const unsigned char *, unsigned, const char *, int)
#define DHCPD_SIX_RENEW_START()
#define DHCPD_SIX_SOLICIT_START()
struct permit * prohibit_list
#define DHCPD_SIX_REBIND_DONE()
struct option_state * options
unsigned char dhcpv6_hop_count
unsigned char link_address[16]
unsigned char dhcpv6_msg_type
isc_boolean_t lease6_exists(const struct ipv6_pool *pool, const struct in6_addr *addr)
void log_fatal(const char *,...) __attribute__((__format__(__printf__
#define DHCPV6_RELAY_REPL
#define DHCPV6_LEASEQUERY
int parse_option_buffer(struct option_state *options, const unsigned char *buffer, unsigned length, struct universe *universe)
#define SV_LOG_THRESHOLD_HIGH
#define DHCPD_SIX_DECLINE_START()
#define DHCPD_SIX_REQUEST_DONE()
isc_result_t decline_lease6(struct ipv6_pool *pool, struct iasubopt *lease)
struct iaddr subnet_number(struct iaddr addr, struct iaddr mask)
int find_subnet(struct subnet **sp, struct iaddr addr, const char *file, int line)
void execute_statements_in_scope(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct group *group, struct group *limiting_group, struct on_star *on_star)
void change_host_uid(struct host_decl *host, const char *data, int len)
isc_result_t release_lease6(struct ipv6_pool *pool, struct iasubopt *lease)
void schedule_lease_timeout(struct ipv6_pool *pool)
int option_state_allocate(struct option_state **ptr, const char *file, int line)
time_t hard_lifetime_end_time
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
#define STATUS_NoPrefixAvail
int packet_reference(struct packet **ptr, struct packet *bp, const char *file, int line)
struct ipv6_pool * ipv6_pool
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
struct interface_info * interface
ssize_t send_packet6(struct interface_info *, const unsigned char *, size_t, struct sockaddr_in6 *)
void putULong(unsigned char *, u_int32_t)
struct iaddrcidrnetlist * next
#define DEFAULT_DEFAULT_LEASE_TIME
#define DHCPV6_RELAY_FORW
int save_option_buffer(struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, unsigned code, int terminatep)
u_int32_t getUShort(const unsigned char *)
void set_server_duid(struct data_string *new_duid)
isc_result_t create_lease6(struct ipv6_pool *pool, struct iasubopt **addr, unsigned int *attempts, const struct data_string *uid, time_t soft_lifetime_end_time)
struct host_decl * n_ipaddr
struct hardware hw_address
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
#define print_hex_3(len, data, limit)
int permitted(struct packet *, struct permit *)
void set_server_duid_type(int type)
int int log_info(const char *,...) __attribute__((__format__(__printf__
struct ipv6_pool ** ipv6_pools
int packet6_len_okay(const char *packet, int len)
struct interface_info * interfaces
u_int32_t getULong(const unsigned char *)
struct shared_network * shared_network
int find_hosts_by_uid(struct host_decl **, const unsigned char *, unsigned, const char *, int)
int addr_eq(struct iaddr addr1, struct iaddr addr2)
isc_boolean_t ipv6_in_pool(const struct in6_addr *addr, const struct ipv6_pool *pool)
#define DHCPV6_LEASEQUERY_REPLY
isc_result_t get_client_id(struct packet *, struct data_string *)
int store_options6(char *buf, int buflen, struct option_state *opt_state, struct packet *packet, const int *required_opts, struct data_string *oro)
int append_option_buffer(struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, unsigned code, int terminatep)
u_int32_t getUChar(const unsigned char *)
struct iaddrcidrnetlist * fixed_prefix
int option_state_dereference(struct option_state **ptr, const char *file, int line)
void dhcpv6(struct packet *)
int commit_leases_timed(void)
const int dhcpv6_type_name_max
isc_boolean_t is_cidr_mask_valid(const struct iaddr *addr, int bits)
#define DHCPD_SIX_CONFIRM_START()
struct interface_info * next
struct universe dhcpv6_universe
isc_boolean_t prefix6_exists(const struct ipv6_pool *pool, const struct in6_addr *pref, u_int8_t plen)
int evaluate_boolean_option_cache(int *ignorep, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
#define print_hex_2(len, data, limit)
int packet_dereference(struct packet **ptr, const char *file, int line)
int ddns_updates(struct packet *, struct lease *, struct lease *, struct iasubopt *, struct iasubopt *, struct option_state *)
int packet_allocate(struct packet **ptr, const char *file, int line)
isc_result_t iasubopt_dereference(struct iasubopt **iasubopt, const char *file, int line)
#define DHCPD_SIX_REQUEST_START()
#define SV_LOG_THRESHOLD_LOW
isc_result_t set_server_duid_from_option(void)
isc_result_t ia_allocate(struct ia_xx **ia, u_int32_t iaid, const char *duid, unsigned int duid_len, const char *file, int line)
struct subnet * next_sibling
isc_result_t ia_add_iasubopt(struct ia_xx *ia, struct iasubopt *iasubopt, const char *file, int line)
unsigned char transaction_id[3]
time_t soft_lifetime_end_time
#define DHCPD_SIX_INFORMATION_REQUEST_DONE()
#define SV_DEFAULT_LEASE_TIME
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
#define HARDWARE_ADDR_LEN
#define DHCPD_SIX_CONFIRM_DONE()
#define REPLY_OPTIONS_INDEX
struct iasubopt ** iasubopt
int write_ia(const struct ia_xx *)
#define DHO_DHCP_RENEWAL_TIME
struct in6_addr dhcpv6_peer_address
void putUShort(unsigned char *, u_int32_t)
isc_result_t create_prefix6(struct ipv6_pool *pool, struct iasubopt **pref, unsigned int *attempts, const struct data_string *uid, time_t soft_lifetime_end_time)
#define DHCPD_SIX_RELEASE_START()
#define DHCPD_SIX_REBIND_START()
struct shared_network * shared_network
isc_result_t ia_reference(struct ia_xx **ia, struct ia_xx *src, const char *file, int line)
struct executable_statement * on_commit
#define SV_LIMIT_ADDRS_PER_IA
const unsigned char * data
int get_option_int(int *result, struct universe *universe, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct option_state *options, struct binding_scope **scope, unsigned code, const char *file, int line)
isc_result_t generate_new_server_duid(void)
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
struct permit * permit_list
#define D6O_RECONF_ACCEPT
#define DHCPV6_INFORMATION_REQUEST
struct in6_addr dhcpv6_link_address
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
void classify_client(struct packet *)
#define SV_LIMIT_PREFS_PER_IA
#define STATUS_UseMulticast
struct packet * dhcpv6_container_packet
isc_result_t iasubopt_reference(struct iasubopt **iasubopt, struct iasubopt *src, const char *file, int line)