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);
154 static int eval_prefix_mode(
int thislen,
int preflen,
int prefix_mode);
155 static isc_result_t pick_v6_prefix_helper(
struct reply_state *reply,
164 schedule_lease_timeout_reply(
struct reply_state *reply) {
169 if ((reply == NULL) || (reply->ia == NULL) || (reply->ia->iasubopt == NULL))
173 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
174 tmp = reply->ia->iasubopt[i];
184 duid_time(time_t when) {
221 return (server_duid.data != NULL);
259 isc_result_t ret_val;
272 ret_val = ISC_R_NOTFOUND;
274 memset(&option_duid, 0,
sizeof(option_duid));
278 ret_val = ISC_R_UNEXPECTED;
282 ret_val = ISC_R_SUCCESS;
301 static int server_duid_type =
DUID_LLT;
308 server_duid_type = type;
325 log_error(
"Invalid DUID type %d specified, "
326 "only LL and LLT types supported", server_duid_type);
339 log_error(
"Can not generate DUID from interfaces which do not have hardware addresses, please configure server-duid!");
343 return ISC_R_UNEXPECTED;
349 memset(&generated_duid, 0,
sizeof(generated_duid));
351 time_val = duid_time(time(NULL));
354 generated_duid.len,
MDL)) {
357 generated_duid.data = generated_duid.buffer->data;
359 putUShort(generated_duid.buffer->data + 2,
361 putULong(generated_duid.buffer->data + 4, time_val);
362 memcpy(generated_duid.buffer->data + 8,
364 }
else if (server_duid_type ==
DUID_LL) {
367 generated_duid.len,
MDL)) {
370 generated_duid.data = generated_duid.buffer->data;
372 putUShort(generated_duid.buffer->data + 2,
374 memcpy(generated_duid.buffer->data + 4,
377 log_fatal(
"Unsupported server DUID type %d.", server_duid_type);
383 return ISC_R_SUCCESS;
389 static isc_boolean_t unicast_option_defined;
395 static isc_boolean_t unicast_option_parsed = ISC_FALSE;
402 is_unicast_option_defined(
void) {
409 if (unicast_option_parsed == ISC_FALSE) {
410 unicast_option_parsed = ISC_TRUE;
413 log_fatal(
"No memory for option state.");
420 unicast_option_defined = (oc != NULL);
425 return (unicast_option_defined);
438 if ((client_id->
data != NULL) || (client_id->
len != 0)) {
444 return ISC_R_NOTFOUND;
450 return ISC_R_FAILURE;
453 return ISC_R_SUCCESS;
464 valid_client_msg(
struct packet *packet,
struct data_string *client_id) {
470 memset(client_id, 0,
sizeof(*client_id));
478 "client identifier missing",
483 log_error(
"Error processing %s from %s; "
484 "unable to evaluate Client Identifier",
494 log_debug(
"Discarding %s from %s; packet sent unicast "
509 "server identifier found "
510 "(CLIENTID %s, SERVERID %s)",
514 client_id->
data, 60),
519 "server identifier found "
523 client_id->
data, 60),
537 if (client_id->
len > 0) {
557 valid_client_resp(
struct packet *packet,
567 memset(client_id, 0,
sizeof(*client_id));
568 memset(server_id, 0,
sizeof(*server_id));
575 "client identifier missing",
580 log_error(
"Error processing %s from %s; "
581 "unable to evaluate Client Identifier",
590 "server identifier missing (CLIENTID %s)",
599 log_error(
"Error processing %s from %s; "
600 "unable to evaluate Server Identifier (CLIENTID %s)",
606 if ((server_duid.len != server_id->
len) ||
607 (memcmp(server_duid.data, server_id->
data, server_duid.len) != 0)) {
609 "not our server identifier "
610 "(CLIENTID %s, SERVERID %s, server DUID %s)",
615 print_hex_3(server_duid.len, server_duid.data, 60));
624 if (server_id->
len > 0) {
627 if (client_id->
len > 0) {
646 valid_client_info_req(
struct packet *packet,
struct data_string *server_id) {
650 char client_id_str[80];
654 memset(server_id, 0,
sizeof(*server_id));
655 memset(&client_id, 0,
sizeof(client_id));
666 snprintf(client_id_str,
sizeof(client_id_str),
" (CLIENTID %s)",
670 client_id_str[0] =
'\0';
677 log_debug(
"Discarding %s from %s; packet sent unicast%s",
686 "IA_NA option present%s",
694 "IA_TA option present%s",
702 "IA_PD option present%s",
713 log_error(
"Error processing %s from %s; "
714 "unable to evaluate Server Identifier%s",
719 if ((server_duid.len != server_id->
len) ||
720 (memcmp(server_duid.data, server_id->
data,
721 server_duid.len) != 0)) {
723 "not our server identifier "
724 "(SERVERID %s, server DUID %s)%s",
728 server_id->
data, 60),
730 server_duid.data, 60),
741 if (server_id->
len > 0) {
752 static const int required_opts[] = {
759 static const int required_opts_NAA[] = {
765 static const int required_opts_solicit[] = {
777 static const int required_opts_agent[] = {
782 static const int required_opts_IA[] = {
787 static const int required_opts_IA_PD[] = {
792 static const int required_opts_STATUS_CODE[] = {
804 get_encapsulated_IA_state(
struct option_state **enc_opt_state,
806 struct packet *packet,
813 memset(enc_opt_data, 0,
sizeof(*enc_opt_data));
815 NULL, NULL, packet->
options, NULL,
818 "error evaluating raw option.");
821 if (enc_opt_data->
len < offset) {
822 log_error(
"get_encapsulated_IA_state: raw option too small.");
831 *enc_opt_state = NULL;
833 log_error(
"get_encapsulated_IA_state: no memory for options.");
838 enc_opt_data->
data + offset,
839 enc_opt_data->
len - offset,
841 log_error(
"get_encapsulated_IA_state: error parsing options.");
851 set_status_code(u_int16_t status_code,
const char *status_message,
857 memset(&d, 0,
sizeof(d));
858 d.len =
sizeof(status_code) + strlen(status_message);
860 log_fatal(
"set_status_code: no memory for status code.");
862 d.data = d.buffer->data;
864 memcpy(d.buffer->data +
sizeof(status_code),
865 status_message, d.len -
sizeof(status_code));
867 d.buffer, (
unsigned char *)d.data, d.len,
869 log_error(
"set_status_code: error saving status code.");
878 void check_pool6_threshold(
struct reply_state *reply,
882 isc_uint64_t used, count, high_threshold;
883 int poolhigh = 0, poollow = 0;
884 char *shared_name =
"no name";
885 char tmp_addr[INET6_ADDRSTRLEN];
919 log_error(
"Pool threshold reset - shared subnet: %s; "
920 "address: %s; low threshold %llu/%llu.",
922 inet_ntop(AF_INET6, &lease->
addr,
923 tmp_addr,
sizeof(tmp_addr)),
931 NULL, reply->packet->options, reply->opt_state,
932 reply->opt_state, &lease->
scope,
939 if ((poolhigh <= 0) || (poolhigh > 100)) {
946 if (used < high_threshold) {
952 log_error(
"Pool threshold exceeded - shared subnet: %s; "
953 "address: %s; high threshold %d%% %llu/%llu.",
955 inet_ntop(AF_INET6, &lease->
addr, tmp_addr,
sizeof(tmp_addr)),
956 poolhigh, used, count);
961 NULL, reply->packet->options, reply->opt_state,
962 reply->opt_state, &lease->
scope,
973 if (poollow < poolhigh) {
984 start_reply(
struct packet *packet,
991 const unsigned char *server_id_data;
999 log_error(
"start_reply: no memory for option_state.");
1067 if (server_id == NULL) {
1068 server_id_data = server_duid.data;
1069 server_id_len = server_duid.len;
1071 server_id_data = server_id->
data;
1072 server_id_len = server_id->
len;
1075 NULL, (
unsigned char *)server_id_data,
1078 "error saving server identifier.");
1083 if (client_id->
buffer != NULL) {
1086 (
unsigned char *)client_id->
data,
1090 "client identifier.");
1106 NULL, (
unsigned char *)
"", 0,
1109 "error saving RECONF_ACCEPT option.");
1127 try_client_v6_address(
struct iasubopt **addr,
1131 struct in6_addr tmp_addr;
1132 isc_result_t result;
1134 if (requested_addr->
len <
sizeof(tmp_addr)) {
1137 memcpy(&tmp_addr, requested_addr->
data,
sizeof(tmp_addr));
1138 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
1139 return ISC_R_FAILURE;
1147 return ISC_R_ADDRNOTAVAIL;
1151 return ISC_R_ADDRINUSE;
1154 result = iasubopt_allocate(addr,
MDL);
1155 if (result != ISC_R_SUCCESS) {
1158 (*addr)->addr = tmp_addr;
1163 if (result != ISC_R_SUCCESS) {
1192 pick_v6_address(
struct reply_state *reply)
1198 unsigned int attempts;
1199 char tmp_buf[INET6_ADDRSTRLEN];
1200 struct iasubopt **addr = &reply->lease;
1201 isc_uint64_t total = 0;
1202 isc_uint64_t active = 0;
1203 isc_uint64_t abandoned = 0;
1204 int jumbo_range = 0;
1205 char *shared_name = (reply->shared->name ?
1206 reply->shared->name :
"(no name)");
1212 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1216 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1226 log_debug(
"Unable to pick client address: "
1227 "no IPv6 pools on this shared network");
1228 return ISC_R_NORESOURCES;
1242 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1243 isc_result_t result = ISC_R_FAILURE;
1257 &reply->ia->iaid_duid,
1259 if (result == ISC_R_SUCCESS) {
1277 tmp_buf,
sizeof(tmp_buf)));
1278 return (ISC_R_SUCCESS);
1286 }
while (i != start_pool);
1288 if (result == ISC_R_NORESOURCES) {
1300 if (jumbo_range != 0) {
1301 log_debug(
"Unable to pick client address: "
1302 "no addresses available - shared network %s: "
1303 " 2^64-1 < total, %llu active, %llu abandoned",
1304 shared_name, active - abandoned, abandoned);
1306 log_debug(
"Unable to pick client address: "
1307 "no addresses available - shared network %s: "
1308 "%llu total, %llu active, %llu abandoned",
1309 shared_name, total, active - abandoned, abandoned);
1312 return ISC_R_NORESOURCES;
1324 try_client_v6_prefix(
struct iasubopt **pref,
1329 struct in6_addr tmp_pref;
1331 isc_result_t result;
1333 if (requested_pref->
len <
sizeof(tmp_plen) +
sizeof(tmp_pref)) {
1336 tmp_plen = (
int) requested_pref->
data[0];
1337 if ((tmp_plen < 3) || (tmp_plen > 128) ||
1338 ((
int)tmp_plen != pool->
units)) {
1339 return ISC_R_FAILURE;
1341 memcpy(&tmp_pref, requested_pref->
data + 1,
sizeof(tmp_pref));
1342 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
1343 return ISC_R_FAILURE;
1346 memcpy(&ia.iabuf, &tmp_pref, 16);
1348 return ISC_R_FAILURE;
1352 return ISC_R_ADDRNOTAVAIL;
1356 return ISC_R_ADDRINUSE;
1359 result = iasubopt_allocate(pref,
MDL);
1360 if (result != ISC_R_SUCCESS) {
1363 (*pref)->addr = tmp_pref;
1364 (*pref)->plen = tmp_plen;
1368 if (result != ISC_R_SUCCESS) {
1414 pick_v6_prefix(
struct reply_state *reply) {
1418 isc_result_t result;
1424 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1428 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1438 log_debug(
"Unable to pick client prefix: "
1439 "no IPv6 pools on this shared network");
1440 return ISC_R_NORESOURCES;
1443 if (reply->preflen <= 0) {
1446 result = pick_v6_prefix_helper(reply,
PLM_IGNORE);
1452 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1453 if (result != ISC_R_SUCCESS) {
1454 result = pick_v6_prefix_helper(reply,
1461 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1468 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1469 if (result != ISC_R_SUCCESS) {
1470 result = pick_v6_prefix_helper(reply,
1477 result = pick_v6_prefix_helper(reply,
PLM_IGNORE);
1482 if (result == ISC_R_SUCCESS) {
1483 char tmp_buf[INET6_ADDRSTRLEN];
1486 inet_ntop(AF_INET6, &(reply->lease->addr),
1487 tmp_buf,
sizeof(tmp_buf)),
1488 (
unsigned)(reply->lease->plen));
1489 return (ISC_R_SUCCESS);
1496 log_debug(
"Unable to pick client prefix: no prefixes available");
1497 return ISC_R_NORESOURCES;
1524 pick_v6_prefix_helper(
struct reply_state *reply,
int prefix_mode) {
1528 unsigned int attempts;
1529 struct iasubopt **pref = &reply->lease;
1531 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1538 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1540 (eval_prefix_mode(p->
units, reply->preflen,
1541 prefix_mode) == 1) &&
1543 &reply->ia->iaid_duid,
1544 cur_time + 120) == ISC_R_SUCCESS)) {
1545 return (ISC_R_SUCCESS);
1550 return ISC_R_NORESOURCES;
1568 eval_prefix_mode(
int len,
int preflen,
int prefix_mode) {
1570 switch (prefix_mode) {
1572 use_it = (len == preflen);
1576 use_it = (len >= preflen);
1580 use_it = (len <= preflen);
1589 "len %d, preflen %d, mode %s, use_it %d",
1634 struct packet *packet,
1638 static struct reply_state reply;
1643 memset(&packet_oro, 0,
sizeof(packet_oro));
1646 if (shared_network_from_packet6(&reply.shared,
1647 packet) != ISC_R_SUCCESS)
1656 if (!start_reply(packet, client_id, server_id, &reply.opt_state,
1672 log_error(
"lease_to_client: error evaluating ORO.");
1684 seek_shared_host(&reply.host, reply.shared);
1687 if ((reply.host == NULL) &&
1690 seek_shared_host(&reply.host, reply.shared);
1697 if ((reply.host == NULL) &&
1698 find_hosts_by_duid_chaddr(&reply.host, client_id)) {
1700 seek_shared_host(&reply.host, reply.shared);
1707 for (; oc != NULL ; oc = oc->
next) {
1708 isc_result_t status;
1711 reply.client_resources = 0;
1712 reply.resources_included = ISC_FALSE;
1714 status = reply_process_ia_na(&reply, oc);
1720 if ((status != ISC_R_SUCCESS) &&
1721 (status != ISC_R_NORESOURCES))
1725 for (; oc != NULL ; oc = oc->
next) {
1726 isc_result_t status;
1729 reply.client_resources = 0;
1730 reply.resources_included = ISC_FALSE;
1732 status = reply_process_ia_ta(&reply, oc);
1738 if ((status != ISC_R_SUCCESS) &&
1739 (status != ISC_R_NORESOURCES))
1746 for (; oc != NULL ; oc = oc->
next) {
1747 isc_result_t status;
1750 reply.client_resources = 0;
1751 reply.resources_included = ISC_FALSE;
1753 status = reply_process_ia_pd(&reply, oc);
1759 if ((status != ISC_R_SUCCESS) &&
1760 (status != ISC_R_NORESOURCES))
1768 if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
1769 if (reply.packet->dhcpv6_msg_type !=
1779 reply.packet->options,
1785 for (i = reply.packet->class_count; i > 0; i--) {
1788 reply.packet->options,
1791 reply.packet->classes[i - 1]->group,
1792 reply.shared->group, NULL);
1796 if (reply.host != NULL)
1799 reply.packet->options,
1803 reply.shared->group, NULL);
1807 if ((packet->
unicast == ISC_TRUE) && !is_unicast_option_defined())
1830 "Unicast not allowed by server.",
1832 log_error(
"lease_to_client: Unable to set "
1833 "UseMulticast status code.");
1851 reply.opt_state, reply.packet,
1889 reply.cursor +=
store_options6((
char *)reply.buf.data + reply.cursor,
1890 sizeof(reply.buf) - reply.cursor,
1891 reply.opt_state, reply.packet,
1892 required_opts_solicit,
1896 reply_ret->
len = reply.cursor;
1897 reply_ret->
buffer = NULL;
1901 memcpy(reply_ret->
buffer->
data, reply.buf.data, reply.cursor);
1909 if (reply.shared != NULL)
1910 shared_network_dereference(&reply.shared,
MDL);
1911 if (reply.host != NULL)
1912 host_dereference(&reply.host,
MDL);
1913 if (reply.opt_state != NULL)
1915 if (reply.packet != NULL)
1917 if (reply.client_id.data != NULL)
1919 if (packet_oro.buffer != NULL)
1921 reply.renew = reply.rebind = reply.prefer = reply.valid = 0;
1929 reply_process_ia_na(
struct reply_state *reply,
struct option_cache *ia) {
1930 isc_result_t status = ISC_R_SUCCESS;
1939 memset(&ia_data, 0,
sizeof(ia_data));
1946 if ((reply->cursor +
IA_NA_OFFSET + 4) >
sizeof(reply->buf)) {
1947 log_error(
"reply_process_ia_na: Reply too long for IA.");
1948 return ISC_R_NOSPACE;
1953 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
1955 log_error(
"reply_process_ia_na: error evaluating ia");
1956 status = ISC_R_FAILURE;
1962 reply->renew =
getULong(ia_data.data + 4);
1963 reply->rebind =
getULong(ia_data.data + 8);
1966 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
1967 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
1968 log_error(
"reply_process_ia_na: no memory for ia.");
1969 status = ISC_R_NOMEMORY;
1976 (
unsigned char *)reply->ia->iaid_duid.data,
1977 reply->ia->iaid_duid.len,
MDL);
1984 status = ISC_R_NOMEMORY;
1989 if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
1990 struct iaddr tmp_addr;
1994 reply->host->fixed_addr,
MDL)) {
1995 log_error(
"reply_process_ia_na: unable to evaluate "
1997 status = ISC_R_FAILURE;
2001 if (reply->fixed.len < 16) {
2002 log_error(
"reply_process_ia_na: invalid fixed address.");
2009 memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
2012 tmp_addr,
MDL) == 0)
2015 reply->static_lease = ISC_TRUE;
2017 reply->static_lease = ISC_FALSE;
2025 ia_cursor = reply->cursor;
2032 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
2036 putULong(reply->buf.data + reply->cursor, iaid);
2040 putULong(reply->buf.data + reply->cursor, reply->renew);
2044 putULong(reply->buf.data + reply->cursor, reply->rebind);
2057 reply->valid = reply->prefer = 0xffffffff;
2058 reply->client_valid = reply->client_prefer = 0;
2059 for (; oc != NULL ; oc = oc->
next) {
2060 status = reply_process_addr(reply, oc);
2068 if (status == ISC_R_CANCELED)
2071 if ((status != ISC_R_SUCCESS) &&
2072 (status != ISC_R_ADDRINUSE) &&
2073 (status != ISC_R_ADDRNOTAVAIL))
2083 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
2084 status = find_client_address(reply);
2086 if (status == ISC_R_NORESOURCES) {
2087 switch (reply->packet->dhcpv6_msg_type) {
2110 "memory for option state "
2112 status = ISC_R_NOMEMORY;
2117 "No addresses available "
2118 "for this interface.",
2120 log_error(
"reply_process_ia_na: Unable "
2121 "to set NoAddrsAvail status "
2123 status = ISC_R_FAILURE;
2127 status = ISC_R_SUCCESS;
2147 if (reply->resources_included)
2148 status = ISC_R_SUCCESS;
2155 if (status != ISC_R_SUCCESS)
2159 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2160 sizeof(reply->buf) - reply->cursor,
2161 reply->reply_ia, reply->packet,
2162 required_opts_IA, NULL);
2165 putUShort(reply->buf.data + ia_cursor + 2,
2166 reply->cursor - (ia_cursor + 4));
2179 reply->packet->options,
2185 reply->renew =
getULong(data.data);
2188 if (data.data != NULL)
2191 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
2199 reply->packet->options,
2205 reply->rebind =
getULong(data.data);
2208 if (data.data != NULL)
2211 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
2217 if (status == ISC_R_CANCELED)
2224 if (reply->static_lease) {
2225 char tmp_addr[INET6_ADDRSTRLEN];
2226 log_info(
"%s NA: address %s to client with duid %s iaid = %d "
2229 inet_ntop(AF_INET6, reply->fixed.data, tmp_addr,
2232 reply->client_id.data, 60),
2236 (reply->on_star.on_commit != NULL)) {
2238 reply->packet->options,
2239 reply->opt_state, NULL,
2240 reply->on_star.on_commit, NULL);
2242 (&reply->on_star.on_commit,
MDL);
2250 if (reply->ia->num_iasubopt != 0) {
2253 char tmp_addr[INET6_ADDRSTRLEN];
2255 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2256 tmp = reply->ia->iasubopt[i];
2258 log_info(
"%s NA: address %s to client with duid %s "
2259 "iaid = %d valid for %d seconds",
2261 inet_ntop(AF_INET6, &tmp->
addr,
2262 tmp_addr,
sizeof(tmp_addr)),
2264 reply->client_id.data, 60),
2278 if ((reply->ia->num_iasubopt != 0) &&
2284 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2285 tmp = reply->ia->iasubopt[i];
2287 if (tmp->
ia != NULL)
2299 reply->packet->options,
2308 #if defined (NSUPDATE)
2317 reply->packet->options,
2322 tmp, NULL, reply->opt_state);
2326 check_pool6_threshold(reply, tmp);
2330 if (reply->old_ia != NULL) {
2331 ia_id = &reply->old_ia->iaid_duid;
2333 (
unsigned char *)ia_id->
data,
2340 ia_id = &reply->ia->iaid_duid;
2342 ia_id->
len, reply->ia,
MDL);
2346 schedule_lease_timeout_reply(reply);
2350 if (packet_ia != NULL)
2352 if (reply->reply_ia != NULL)
2354 if (ia_data.data != NULL)
2356 if (
data.data != NULL)
2358 if (reply->ia != NULL)
2360 if (reply->old_ia != NULL)
2362 if (reply->lease != NULL)
2364 if (reply->fixed.data != NULL)
2366 if (reply->subnet != NULL)
2367 subnet_dereference(&reply->subnet,
MDL);
2368 if (reply->on_star.on_expiry != NULL)
2370 (&reply->on_star.on_expiry,
MDL);
2371 if (reply->on_star.on_release != NULL)
2373 (&reply->on_star.on_release,
MDL);
2380 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2390 reply_process_addr(
struct reply_state *reply,
struct option_cache *addr) {
2391 u_int32_t pref_life, valid_life;
2395 struct iaddr tmp_addr;
2398 isc_result_t status = ISC_R_SUCCESS;
2401 memset(&iaaddr, 0,
sizeof(iaaddr));
2409 if ((reply->cursor + 28) >
sizeof(reply->buf)) {
2410 log_error(
"reply_process_addr: Out of room for address.");
2411 return ISC_R_NOSPACE;
2419 log_error(
"reply_process_addr: error evaluating IAADDR.");
2420 status = ISC_R_FAILURE;
2425 pref_life =
getULong(iaaddr.data + 16);
2426 valid_life =
getULong(iaaddr.data + 20);
2428 if ((reply->client_valid == 0) ||
2429 (reply->client_valid > valid_life))
2430 reply->client_valid = valid_life;
2432 if ((reply->client_prefer == 0) ||
2433 (reply->client_prefer > pref_life))
2434 reply->client_prefer = pref_life;
2441 memset(tmp_addr.iabuf, 0, 16);
2442 if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
2448 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2453 for (subnet = reply->shared->subnets ; subnet != NULL ;
2461 if (subnet == NULL) {
2486 log_error(
"reply_process_addr: No memory for "
2487 "option state wipe.");
2488 status = ISC_R_NOMEMORY;
2494 "Address not for use on this "
2495 "link.", reply->reply_ia)) {
2496 log_error(
"reply_process_addr: Failure "
2497 "setting status code.");
2498 status = ISC_R_FAILURE;
2503 status = ISC_R_CANCELED;
2515 if ((reply->packet->dhcpv6_msg_type !=
DHCPV6_RENEW) &&
2517 log_error(
"It is impossible to lease a client that is "
2518 "not sending a solicit, request, renew, or "
2520 status = ISC_R_FAILURE;
2524 reply->send_prefer = reply->send_valid = 0;
2529 if (!address_is_owned(reply, &tmp_addr)) {
2540 status = reply_process_try_addr(reply, &tmp_addr);
2547 if ((status != ISC_R_SUCCESS) &&
2548 (status != ISC_R_ADDRINUSE) &&
2549 (status != ISC_R_ADDRNOTAVAIL))
2557 if (reply->lease == NULL) {
2558 if (reply->packet->dhcpv6_msg_type ==
2560 reply->send_prefer = 0;
2561 reply->send_valid = 0;
2578 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
2582 log_error(
"reply_process_addr: No memory for "
2583 "option state wipe.");
2584 status = ISC_R_NOMEMORY;
2590 "Address not bound to this "
2591 "interface.", reply->reply_ia)) {
2592 log_error(
"reply_process_addr: Unable to "
2593 "attach status code.");
2594 status = ISC_R_FAILURE;
2599 status = ISC_R_CANCELED;
2602 log_error(
"It is impossible to lease a client that is "
2603 "not sending a solicit, request, renew, or "
2605 status = ISC_R_FAILURE;
2610 if (reply->static_lease) {
2611 if (reply->host == NULL)
2615 group = reply->subnet->group;
2617 if (reply->lease == NULL)
2620 scope = &reply->lease->scope;
2621 group = reply->lease->ipv6_pool->ipv6_pond->group;
2630 if (reply->client_resources != 0) {
2643 reply->packet->options,
2647 log_error(
"reply_process_addr: unable to "
2648 "evaluate addrs-per-ia value.");
2649 status = ISC_R_FAILURE;
2661 if (reply->client_resources >= limit)
2665 status = reply_process_is_addressed(reply, scope, group);
2666 if (status != ISC_R_SUCCESS)
2670 status = reply_process_send_addr(reply, &tmp_addr);
2673 if (iaaddr.data != NULL)
2675 if (
data.data != NULL)
2677 if (reply->lease != NULL)
2689 static isc_boolean_t
2690 address_is_owned(
struct reply_state *reply,
struct iaddr *addr) {
2697 if (reply->static_lease) {
2698 if (reply->fixed.data == NULL)
2701 if (memcmp(addr->
iabuf, reply->fixed.data, 16) == 0)
2707 if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
2710 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2713 tmp = reply->old_ia->iasubopt[i];
2715 if (memcmp(addr->
iabuf, &tmp->
addr, 16) == 0) {
2740 reply_process_ia_ta(
struct reply_state *reply,
struct option_cache *ia) {
2741 isc_result_t status = ISC_R_SUCCESS;
2748 u_int32_t pref_life, valid_life;
2749 struct iaddr tmp_addr;
2753 memset(&ia_data, 0,
sizeof(ia_data));
2754 memset(&data, 0,
sizeof(data));
2755 memset(&iaaddr, 0,
sizeof(iaaddr));
2758 if ((reply->cursor +
IA_TA_OFFSET + 4) >
sizeof(reply->buf)) {
2759 log_error(
"reply_process_ia_ta: Reply too long for IA.");
2760 return ISC_R_NOSPACE;
2765 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2767 log_error(
"reply_process_ia_ta: error evaluating ia");
2768 status = ISC_R_FAILURE;
2776 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
2777 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
2778 log_error(
"reply_process_ia_ta: no memory for ia.");
2779 status = ISC_R_NOMEMORY;
2786 (
unsigned char *)reply->ia->iaid_duid.data,
2787 reply->ia->iaid_duid.len,
MDL);
2794 status = ISC_R_NOMEMORY;
2801 reply->static_lease = ISC_FALSE;
2809 ia_cursor = reply->cursor;
2816 putUShort(reply->buf.data + reply->cursor, 0x04u);
2820 putULong(reply->buf.data + reply->cursor, iaid);
2827 reply->valid = reply->prefer = 0xffffffff;
2828 reply->client_valid = reply->client_prefer = 0;
2830 for (; oc != NULL; oc = oc->
next) {
2831 memset(&iaaddr, 0,
sizeof(iaaddr));
2834 reply->packet->options, NULL,
2838 "evaluating IAADDR.");
2839 status = ISC_R_FAILURE;
2843 pref_life =
getULong(iaaddr.data + 16);
2844 valid_life =
getULong(iaaddr.data + 20);
2846 if ((reply->client_valid == 0) ||
2847 (reply->client_valid > valid_life))
2848 reply->client_valid = valid_life;
2850 if ((reply->client_prefer == 0) ||
2851 (reply->client_prefer > pref_life))
2852 reply->client_prefer = pref_life;
2855 if (status == ISC_R_CANCELED)
2859 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2860 if (!temporary_is_available(reply, &tmp_addr))
2862 status = reply_process_is_addressed(reply,
2863 &reply->lease->scope,
2864 reply->lease->ipv6_pool->ipv6_pond->group);
2865 if (status != ISC_R_SUCCESS)
2867 status = reply_process_send_addr(reply, &tmp_addr);
2868 if (status != ISC_R_SUCCESS)
2870 if (reply->lease != NULL)
2878 status = ISC_R_NOMEMORY;
2881 status = ISC_R_CANCELED;
2882 reply->client_resources = 0;
2883 reply->resources_included = ISC_FALSE;
2884 if (reply->lease != NULL)
2892 if (reply->client_resources != 0)
2894 status = find_client_temporaries(reply);
2895 if (status == ISC_R_NORESOURCES) {
2896 switch (reply->packet->dhcpv6_msg_type) {
2917 "memory for option state wipe.");
2918 status = ISC_R_NOMEMORY;
2923 "No addresses available "
2924 "for this interface.",
2926 log_error(
"reply_process_ia_ta: Unable "
2927 "to set NoAddrsAvail status code.");
2928 status = ISC_R_FAILURE;
2932 status = ISC_R_SUCCESS;
2941 if (reply->resources_included)
2942 status = ISC_R_SUCCESS;
2947 }
else if (status != ISC_R_SUCCESS)
2951 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2952 sizeof(reply->buf) - reply->cursor,
2953 reply->reply_ia, reply->packet,
2954 required_opts_IA, NULL);
2957 putUShort(reply->buf.data + ia_cursor + 2,
2958 reply->cursor - (ia_cursor + 4));
2964 if (status == ISC_R_CANCELED)
2970 if (reply->ia->num_iasubopt != 0) {
2973 char tmp_addr[INET6_ADDRSTRLEN];
2975 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2976 tmp = reply->ia->iasubopt[i];
2978 log_info(
"%s TA: address %s to client with duid %s "
2979 "iaid = %d valid for %d seconds",
2981 inet_ntop(AF_INET6, &tmp->
addr,
2982 tmp_addr,
sizeof(tmp_addr)),
2984 reply->client_id.data, 60),
2998 if ((reply->ia->num_iasubopt != 0) &&
3004 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3005 tmp = reply->ia->iasubopt[i];
3007 if (tmp->
ia != NULL)
3019 reply->packet->options,
3028 #if defined (NSUPDATE)
3037 reply->packet->options,
3042 tmp, NULL, reply->opt_state);
3046 check_pool6_threshold(reply, tmp);
3050 if (reply->old_ia != NULL) {
3051 ia_id = &reply->old_ia->iaid_duid;
3053 (
unsigned char *)ia_id->
data,
3060 ia_id = &reply->ia->iaid_duid;
3062 ia_id->
len, reply->ia,
MDL);
3066 schedule_lease_timeout_reply(reply);
3070 if (packet_ia != NULL)
3072 if (iaaddr.data != NULL)
3074 if (reply->reply_ia != NULL)
3076 if (ia_data.data != NULL)
3078 if (
data.data != NULL)
3080 if (reply->ia != NULL)
3082 if (reply->old_ia != NULL)
3084 if (reply->lease != NULL)
3092 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
3098 static isc_boolean_t
3099 temporary_is_available(
struct reply_state *reply,
struct iaddr *addr) {
3100 struct in6_addr tmp_addr;
3101 struct subnet *subnet;
3106 memcpy(&tmp_addr, addr->
iabuf,
sizeof(tmp_addr));
3112 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
3118 for (subnet = reply->shared->subnets ; subnet != NULL ;
3132 if (address_is_owned(reply, addr))
3138 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3145 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
3161 if (iasubopt_allocate(&reply->lease,
MDL) != ISC_R_SUCCESS)
3163 reply->lease->addr = tmp_addr;
3164 reply->lease->plen = 0;
3176 find_client_temporaries(
struct reply_state *reply) {
3180 isc_result_t status = ISC_R_NORESOURCES;;
3181 unsigned int attempts;
3182 struct iaddr send_addr;
3188 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3192 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3202 log_debug(
"Unable to get client addresses: "
3203 "no IPv6 pools on this shared network");
3204 return ISC_R_NORESOURCES;
3214 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3221 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3230 &reply->client_id,
cur_time + 120);
3231 if (status != ISC_R_SUCCESS) {
3232 log_debug(
"Unable to get a temporary address.");
3236 status = reply_process_is_addressed(reply,
3237 &reply->lease->scope,
3239 if (status != ISC_R_SUCCESS) {
3243 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3244 status = reply_process_send_addr(reply, &send_addr);
3245 if (status != ISC_R_SUCCESS) {
3257 if (reply->lease != NULL) {
3268 reply_process_try_addr(
struct reply_state *reply,
struct iaddr *addr) {
3269 isc_result_t status = ISC_R_ADDRNOTAVAIL;
3275 if ((reply == NULL) || (reply->shared == NULL) ||
3276 (addr == NULL) || (reply->lease != NULL))
3283 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3287 for (i = 0; ; i++) {
3289 if ((pool == NULL) ||
3299 return (ISC_R_ADDRNOTAVAIL);
3302 memset(&data_addr, 0,
sizeof(data_addr));
3303 data_addr.len = addr->
len;
3304 data_addr.data = addr->
iabuf;
3317 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3324 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
3328 status = try_client_v6_address(&reply->lease, pool,
3330 if (status == ISC_R_SUCCESS)
3334 if (status == ISC_R_SUCCESS)
3349 find_client_address(
struct reply_state *reply) {
3350 struct iaddr send_addr;
3351 isc_result_t status = ISC_R_NORESOURCES;
3352 struct iasubopt *lease, *best_lease = NULL;
3354 struct group *group;
3357 if (reply->static_lease) {
3358 if (reply->host == NULL)
3362 memcpy(send_addr.iabuf, reply->fixed.data, 16);
3365 group = reply->subnet->group;
3369 if (reply->old_ia != NULL) {
3370 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
3374 lease = reply->old_ia->iasubopt[i];
3383 if ((candidate_shared != reply->shared) ||
3393 best_lease = lease_compare(lease, best_lease);
3401 status = pick_v6_address(reply);
3402 }
else if (best_lease != NULL) {
3404 status = ISC_R_SUCCESS;
3408 if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
3410 log_error(
"Best match for DUID %s is an abandoned address,"
3411 " This may be a result of multiple clients attempting"
3412 " to use this DUID",
3414 reply->client_id.data, 60));
3419 if (status != ISC_R_SUCCESS)
3422 if (reply->lease == NULL)
3429 scope = &reply->lease->scope;
3430 group = reply->lease->ipv6_pool->ipv6_pond->group;
3433 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3436 status = reply_process_is_addressed(reply, scope, group);
3437 if (status != ISC_R_SUCCESS)
3440 status = reply_process_send_addr(reply, &send_addr);
3449 reply_process_is_addressed(
struct reply_state *reply,
3452 isc_result_t status = ISC_R_SUCCESS;
3460 memset(&data, 0,
sizeof(data));
3469 on_star = &reply->lease->on_star;
3471 on_star = &reply->on_star;
3481 reply->packet->options, tmp_options,
3484 if (tmp_options != NULL) {
3494 reply->packet->options, reply->opt_state,
3498 for (i = reply->packet->class_count; i > 0; i--) {
3500 reply->packet->options,
3501 reply->opt_state, scope,
3502 reply->packet->classes[i - 1]->group,
3511 if (reply->host != NULL)
3513 reply->packet->options,
3514 reply->opt_state, scope,
3515 reply->host->group, group,
3519 if (reply->client_valid == 0)
3522 reply->send_valid = reply->client_valid;
3528 reply->packet->options,
3532 log_error(
"reply_process_is_addressed: unable to "
3533 "evaluate default lease time");
3534 status = ISC_R_FAILURE;
3538 reply->send_valid =
getULong(data.data);
3542 if (reply->client_prefer == 0)
3543 reply->send_prefer = reply->send_valid;
3545 reply->send_prefer = reply->client_prefer;
3547 if (reply->send_prefer >= reply->send_valid)
3548 reply->send_prefer = (reply->send_valid / 2) +
3549 (reply->send_valid / 8);
3555 reply->packet->options,
3559 log_error(
"reply_process_is_addressed: unable to "
3560 "evaluate preferred lease time");
3561 status = ISC_R_FAILURE;
3565 reply->send_prefer =
getULong(data.data);
3570 if (reply->prefer > reply->send_prefer)
3571 reply->prefer = reply->send_prefer;
3573 if (reply->valid > reply->send_valid)
3574 reply->valid = reply->send_valid;
3586 if (reply->host != NULL)
3588 reply->client_id->len);
3592 if (reply->lease != NULL) {
3594 reply->lease->prefer = reply->send_prefer;
3595 reply->lease->valid = reply->send_valid;
3599 reply->lease->soft_lifetime_end_time =
3605 if (status != ISC_R_SUCCESS) {
3606 log_fatal(
"reply_process_is_addressed: Unable to "
3607 "attach lease to new IA: %s",
3608 isc_result_totext(status));
3614 if (reply->lease->ia == NULL) {
3621 reply->packet->options, reply->reply_ia,
3625 for (i = reply->packet->class_count; i > 0; i--) {
3627 reply->packet->options,
3628 reply->reply_ia, scope,
3629 reply->packet->classes[i - 1]->group,
3637 if (reply->host != NULL)
3639 reply->packet->options,
3640 reply->reply_ia, scope,
3641 reply->host->group, group, NULL);
3644 if (data.data != NULL)
3647 if (status == ISC_R_SUCCESS)
3648 reply->client_resources++;
3655 reply_process_send_addr(
struct reply_state *reply,
struct iaddr *addr) {
3656 isc_result_t status = ISC_R_SUCCESS;
3664 log_error(
"reply_process_send_addr: out of memory"
3665 "allocating new IAADDR buffer.");
3666 status = ISC_R_NOMEMORY;
3671 memcpy(
data.buffer->data, addr->
iabuf, 16);
3678 log_error(
"reply_process_send_addr: unable "
3679 "to save IAADDR option");
3680 status = ISC_R_FAILURE;
3684 reply->resources_included = ISC_TRUE;
3687 if (
data.data != NULL)
3701 switch(alpha->
state) {
3703 switch(beta->
state) {
3724 switch (beta->
state) {
3750 switch (beta->
state) {
3772 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
3780 reply_process_ia_pd(
struct reply_state *reply,
struct option_cache *ia) {
3781 isc_result_t status = ISC_R_SUCCESS;
3790 memset(&ia_data, 0,
sizeof(ia_data));
3797 if ((reply->cursor +
IA_PD_OFFSET + 4) >
sizeof(reply->buf)) {
3798 log_error(
"reply_process_ia_pd: Reply too long for IA.");
3799 return ISC_R_NOSPACE;
3804 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
3806 log_error(
"reply_process_ia_pd: error evaluating ia");
3807 status = ISC_R_FAILURE;
3813 reply->renew =
getULong(ia_data.data + 4);
3814 reply->rebind =
getULong(ia_data.data + 8);
3817 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
3818 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
3819 log_error(
"reply_process_ia_pd: no memory for ia.");
3820 status = ISC_R_NOMEMORY;
3827 (
unsigned char *)reply->ia->iaid_duid.data,
3828 reply->ia->iaid_duid.len,
MDL);
3835 status = ISC_R_NOMEMORY;
3840 reply->static_prefixes = 0;
3841 if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
3844 for (fp = reply->host->fixed_prefix; fp != NULL;
3846 reply->static_prefixes += 1;
3856 ia_cursor = reply->cursor;
3863 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
3867 putULong(reply->buf.data + reply->cursor, iaid);
3871 putULong(reply->buf.data + reply->cursor, reply->renew);
3875 putULong(reply->buf.data + reply->cursor, reply->rebind);
3882 reply->valid = reply->prefer = 0xffffffff;
3883 reply->client_valid = reply->client_prefer = 0;
3884 reply->preflen = -1;
3885 for (; oc != NULL ; oc = oc->
next) {
3886 status = reply_process_prefix(reply, oc);
3894 if (status == ISC_R_CANCELED)
3897 if ((status != ISC_R_SUCCESS) &&
3898 (status != ISC_R_ADDRINUSE) &&
3899 (status != ISC_R_ADDRNOTAVAIL))
3909 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
3910 status = find_client_prefix(reply);
3912 if (status == ISC_R_NORESOURCES) {
3913 switch (reply->packet->dhcpv6_msg_type) {
3928 "memory for option state "
3930 status = ISC_R_NOMEMORY;
3935 "No prefixes available "
3936 "for this interface.",
3940 "NoPrefixAvail status "
3942 status = ISC_R_FAILURE;
3946 status = ISC_R_SUCCESS;
3950 if (reply->resources_included)
3951 status = ISC_R_SUCCESS;
3958 if (status != ISC_R_SUCCESS)
3962 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
3963 sizeof(reply->buf) - reply->cursor,
3964 reply->reply_ia, reply->packet,
3965 required_opts_IA_PD, NULL);
3968 putUShort(reply->buf.data + ia_cursor + 2,
3969 reply->cursor - (ia_cursor + 4));
3982 reply->packet->options,
3988 reply->renew =
getULong(data.data);
3991 if (data.data != NULL)
3994 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
4002 reply->packet->options,
4008 reply->rebind =
getULong(data.data);
4011 if (data.data != NULL)
4014 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
4020 if (status == ISC_R_CANCELED)
4027 if (reply->static_prefixes != 0) {
4028 char tmp_addr[INET6_ADDRSTRLEN];
4029 log_info(
"%s PD: address %s/%d to client with duid %s "
4032 inet_ntop(AF_INET6, reply->fixed_pref.lo_addr.iabuf,
4033 tmp_addr,
sizeof(tmp_addr)),
4034 reply->fixed_pref.bits,
4036 reply->client_id.data, 60),
4039 (reply->on_star.on_commit != NULL)) {
4041 reply->packet->options,
4043 NULL, reply->on_star.on_commit,
4046 (&reply->on_star.on_commit,
MDL);
4054 if (reply->ia->num_iasubopt != 0) {
4057 char tmp_addr[INET6_ADDRSTRLEN];
4059 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
4060 tmp = reply->ia->iasubopt[i];
4062 log_info(
"%s PD: address %s/%d to client with duid %s"
4063 " iaid = %d valid for %d seconds",
4065 inet_ntop(AF_INET6, &tmp->
addr,
4066 tmp_addr,
sizeof(tmp_addr)),
4069 reply->client_id.data, 60),
4083 (reply->ia->num_iasubopt != 0)) {
4088 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
4089 tmp = reply->ia->iasubopt[i];
4091 if (tmp->
ia != NULL)
4103 reply->packet->options,
4113 check_pool6_threshold(reply, tmp);
4117 if (reply->old_ia != NULL) {
4118 ia_id = &reply->old_ia->iaid_duid;
4120 (
unsigned char *)ia_id->
data,
4127 ia_id = &reply->ia->iaid_duid;
4129 ia_id->
len, reply->ia,
MDL);
4133 schedule_lease_timeout_reply(reply);
4137 if (packet_ia != NULL)
4139 if (reply->reply_ia != NULL)
4141 if (ia_data.data != NULL)
4143 if (
data.data != NULL)
4145 if (reply->ia != NULL)
4147 if (reply->old_ia != NULL)
4149 if (reply->lease != NULL)
4151 if (reply->on_star.on_expiry != NULL)
4153 (&reply->on_star.on_expiry,
MDL);
4154 if (reply->on_star.on_release != NULL)
4156 (&reply->on_star.on_release,
MDL);
4163 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
4173 reply_process_prefix(
struct reply_state *reply,
struct option_cache *pref) {
4174 u_int32_t pref_life, valid_life;
4179 isc_result_t status = ISC_R_SUCCESS;
4180 struct group *group;
4183 memset(&iapref, 0,
sizeof(iapref));
4184 memset(&data, 0,
sizeof(data));
4191 if ((reply->cursor + 29) >
sizeof(reply->buf)) {
4192 log_error(
"reply_process_prefix: Out of room for prefix.");
4193 return ISC_R_NOSPACE;
4201 log_error(
"reply_process_prefix: error evaluating IAPREFIX.");
4202 status = ISC_R_FAILURE;
4211 valid_life =
getULong(iapref.data + 4);
4213 if ((reply->client_valid == 0) ||
4214 (reply->client_valid > valid_life))
4215 reply->client_valid = valid_life;
4217 if ((reply->client_prefer == 0) ||
4218 (reply->client_prefer > pref_life))
4219 reply->client_prefer = pref_life;
4225 tmp_pref.lo_addr.len = 16;
4226 memset(tmp_pref.lo_addr.iabuf, 0, 16);
4227 if ((iapref.data[8] == 0) &&
4228 (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
4237 tmp_pref.bits = (
int) iapref.data[8];
4238 if (reply->preflen < 0) {
4240 reply->preflen = tmp_pref.bits;
4242 if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
4246 memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
4249 if (!prefix_is_owned(reply, &tmp_pref)) {
4254 status = reply_process_try_prefix(reply, &tmp_pref);
4257 if ((status != ISC_R_SUCCESS) &&
4258 (status != ISC_R_ADDRINUSE) &&
4259 (status != ISC_R_ADDRNOTAVAIL))
4262 if (reply->lease == NULL) {
4263 if (reply->packet->dhcpv6_msg_type ==
4265 reply->send_prefer = 0;
4266 reply->send_valid = 0;
4285 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
4289 log_error(
"reply_process_prefix: No memory "
4290 "for option state wipe.");
4291 status = ISC_R_NOMEMORY;
4297 "Prefix not bound to this "
4298 "interface.", reply->reply_ia)) {
4299 log_error(
"reply_process_prefix: Unable to "
4300 "attach status code.");
4301 status = ISC_R_FAILURE;
4306 status = ISC_R_CANCELED;
4309 log_error(
"It is impossible to lease a client that is "
4310 "not sending a solicit, request, renew, or "
4312 status = ISC_R_FAILURE;
4317 if (reply->static_prefixes > 0) {
4318 if (reply->host == NULL)
4325 tmp_pref.lo_addr,
MDL) == 0)
4327 group = reply->subnet->group;
4328 subnet_dereference(&reply->subnet,
MDL);
4331 memcpy(&reply->fixed_pref, &tmp_pref,
sizeof(tmp_pref));
4333 if (reply->lease == NULL)
4336 scope = &reply->lease->scope;
4337 group = reply->lease->ipv6_pool->ipv6_pond->group;
4346 if (reply->client_resources != 0) {
4359 reply->packet->options,
4363 log_error(
"reply_process_prefix: unable to "
4364 "evaluate prefs-per-ia value.");
4365 status = ISC_R_FAILURE;
4377 if (reply->client_resources >= limit)
4381 status = reply_process_is_prefixed(reply, scope, group);
4382 if (status != ISC_R_SUCCESS)
4386 status = reply_process_send_prefix(reply, &tmp_pref);
4389 if (iapref.data != NULL)
4391 if (data.data != NULL)
4393 if (reply->lease != NULL)
4405 static isc_boolean_t
4406 prefix_is_owned(
struct reply_state *reply,
struct iaddrcidrnet *pref) {
4414 if (reply->static_prefixes > 0) {
4415 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4424 if ((reply->old_ia == NULL) ||
4425 (reply->old_ia->num_iasubopt == 0))
4428 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4431 tmp = reply->old_ia->iasubopt[i];
4433 if ((pref->
bits == (
int) tmp->
plen) &&
4459 reply_process_try_prefix(
struct reply_state *reply,
4461 isc_result_t status = ISC_R_ADDRNOTAVAIL;
4467 if ((reply == NULL) || (reply->shared == NULL) ||
4468 (pref == NULL) || (reply->lease != NULL))
4475 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4479 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4489 return (ISC_R_ADDRNOTAVAIL);
4492 memset(&data_pref, 0,
sizeof(data_pref));
4495 log_error(
"reply_process_try_prefix: out of memory.");
4496 return (ISC_R_NOMEMORY);
4498 data_pref.data = data_pref.buffer->data;
4499 data_pref.buffer->data[0] = (u_int8_t) pref->
bits;
4500 memcpy(data_pref.buffer->data + 1, pref->
lo_addr.
iabuf, 16);
4510 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4517 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4522 status = try_client_v6_prefix(&reply->lease, pool,
4526 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4529 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4543 find_client_prefix(
struct reply_state *reply) {
4545 isc_result_t status = ISC_R_NORESOURCES;
4546 struct iasubopt *prefix, *best_prefix = NULL;
4549 struct group *group;
4551 if (reply->static_prefixes > 0) {
4554 if (reply->host == NULL)
4557 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4566 l = reply->host->fixed_prefix;
4568 memcpy(&send_pref, &l->
cidrnet,
sizeof(send_pref));
4574 send_pref.lo_addr,
MDL) == 0)
4576 group = reply->subnet->group;
4577 subnet_dereference(&reply->subnet,
MDL);
4580 memcpy(&reply->fixed_pref, &l->
cidrnet,
sizeof(send_pref));
4585 if (reply->old_ia != NULL) {
4586 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4590 prefix = reply->old_ia->iasubopt[i];
4599 if (((candidate_shared != NULL) &&
4600 (candidate_shared != reply->shared)) ||
4614 best_prefix = prefix_compare(reply, prefix,
4623 status = pick_v6_prefix(reply);
4624 }
else if (best_prefix != NULL) {
4626 status = ISC_R_SUCCESS;
4630 if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
4632 log_error(
"Reclaiming abandoned prefixes is not yet "
4633 "supported. Treating this as an out of space "
4639 if (status != ISC_R_SUCCESS)
4642 if (reply->lease == NULL)
4645 scope = &reply->lease->scope;
4646 group = reply->lease->ipv6_pool->ipv6_pond->group;
4648 send_pref.lo_addr.len = 16;
4649 memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
4650 send_pref.bits = (
int) reply->lease->plen;
4653 status = reply_process_is_prefixed(reply, scope, group);
4654 if (status != ISC_R_SUCCESS)
4657 status = reply_process_send_prefix(reply, &send_pref);
4666 reply_process_is_prefixed(
struct reply_state *reply,
4669 isc_result_t status = ISC_R_SUCCESS;
4673 struct on_star *on_star;
4677 memset(&data, 0,
sizeof(data));
4686 on_star = &reply->lease->on_star;
4688 on_star = &reply->on_star;
4698 reply->packet->options, tmp_options,
4701 if (tmp_options != NULL) {
4711 reply->packet->options, reply->opt_state,
4715 for (i = reply->packet->class_count; i > 0; i--) {
4717 reply->packet->options,
4718 reply->opt_state, scope,
4719 reply->packet->classes[i - 1]->group,
4728 if (reply->host != NULL)
4730 reply->packet->options,
4731 reply->opt_state, scope,
4732 reply->host->group, group,
4736 if (reply->client_valid == 0)
4739 reply->send_valid = reply->client_valid;
4745 reply->packet->options,
4749 log_error(
"reply_process_is_prefixed: unable to "
4750 "evaluate default prefix time");
4751 status = ISC_R_FAILURE;
4755 reply->send_valid =
getULong(data.data);
4759 if (reply->client_prefer == 0)
4760 reply->send_prefer = reply->send_valid;
4762 reply->send_prefer = reply->client_prefer;
4764 if (reply->send_prefer >= reply->send_valid)
4765 reply->send_prefer = (reply->send_valid / 2) +
4766 (reply->send_valid / 8);
4772 reply->packet->options,
4776 log_error(
"reply_process_is_prefixed: unable to "
4777 "evaluate preferred prefix time");
4778 status = ISC_R_FAILURE;
4782 reply->send_prefer =
getULong(data.data);
4787 if (reply->prefer > reply->send_prefer)
4788 reply->prefer = reply->send_prefer;
4790 if (reply->valid > reply->send_valid)
4791 reply->valid = reply->send_valid;
4794 if (reply->lease != NULL) {
4796 reply->lease->prefer = reply->send_prefer;
4797 reply->lease->valid = reply->send_valid;
4801 reply->lease->soft_lifetime_end_time =
4807 if (status != ISC_R_SUCCESS) {
4808 log_fatal(
"reply_process_is_prefixed: Unable to "
4809 "attach prefix to new IA_PD: %s",
4810 isc_result_totext(status));
4816 if (reply->lease->ia == NULL) {
4823 reply->packet->options, reply->reply_ia,
4827 for (i = reply->packet->class_count; i > 0; i--) {
4829 reply->packet->options,
4830 reply->reply_ia, scope,
4831 reply->packet->classes[i - 1]->group,
4839 if (reply->host != NULL)
4841 reply->packet->options,
4842 reply->reply_ia, scope,
4843 reply->host->group, group, NULL);
4846 if (data.data != NULL)
4849 if (status == ISC_R_SUCCESS)
4850 reply->client_resources++;
4857 reply_process_send_prefix(
struct reply_state *reply,
4859 isc_result_t status = ISC_R_SUCCESS;
4867 log_error(
"reply_process_send_prefix: out of memory"
4868 "allocating new IAPREFIX buffer.");
4869 status = ISC_R_NOMEMORY;
4882 log_error(
"reply_process_send_prefix: unable "
4883 "to save IAPREFIX option");
4884 status = ISC_R_FAILURE;
4888 reply->resources_included = ISC_TRUE;
4891 if (
data.data != NULL)
4899 prefix_compare(
struct reply_state *reply,
4906 if (reply->preflen >= 0) {
4907 if ((alpha->
plen == reply->preflen) &&
4908 (beta->
plen != reply->preflen))
4910 if ((beta->
plen == reply->preflen) &&
4911 (alpha->
plen != reply->preflen))
4915 switch(alpha->
state) {
4917 switch(beta->
state) {
4938 switch (beta->
state) {
4964 switch (beta->
state) {
4986 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
5000 dhcpv6_solicit(
struct data_string *reply_ret,
struct packet *packet) {
5008 if (!valid_client_msg(packet, &client_id)) {
5012 lease_to_client(reply_ret, packet, &client_id, NULL);
5029 dhcpv6_request(
struct data_string *reply_ret,
struct packet *packet) {
5038 if (!valid_client_resp(packet, &client_id, &server_id)) {
5045 lease_to_client(reply_ret, packet, &client_id, &server_id);
5060 struct packet *packet)
5062 const struct packet *chk_packet;
5063 const struct in6_addr *link_addr, *first_link_addr;
5064 struct iaddr tmp_addr;
5065 struct subnet *subnet;
5066 isc_result_t status;
5068 if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
5075 first_link_addr = NULL;
5077 while (chk_packet != NULL) {
5079 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
5080 !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
5081 first_link_addr = link_addr;
5092 if (first_link_addr != NULL) {
5093 tmp_addr.len =
sizeof(*first_link_addr);
5094 memcpy(tmp_addr.iabuf,
5095 first_link_addr,
sizeof(*first_link_addr));
5098 log_debug(
"No subnet found for link-address %s.",
5100 return ISC_R_NOTFOUND;
5102 status = shared_network_reference(shared,
5104 subnet_dereference(&subnet,
MDL);
5111 status = shared_network_reference(shared,
5115 log_info(
"[L2 Relay] No link address in relay packet "
5116 "assuming L2 relay and using receiving "
5126 log_error(
"No interface and no link address "
5127 "can't determine pool");
5153 dhcpv6_confirm(
struct data_string *reply_ret,
struct packet *packet) {
5155 struct subnet *subnet;
5157 struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
5159 struct iaddr cli_addr;
5161 isc_boolean_t inappropriate, has_addrs;
5162 char reply_data[65536];
5171 memset(&client_id, 0,
sizeof(client_id));
5172 if (!valid_client_msg(packet, &client_id)) {
5181 if ((ia == NULL) && (ta == NULL))
5192 opt_state = cli_enc_opt_state = NULL;
5193 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5194 memset(&iaaddr, 0,
sizeof(iaaddr));
5195 memset(&packet_oro, 0,
sizeof(packet_oro));
5202 if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
5214 has_addrs = inappropriate = ISC_FALSE;
5216 while(!inappropriate) {
5220 if ((pass ==
D6O_IA_NA) && (ia == NULL)) {
5230 !get_encapsulated_IA_state(&cli_enc_opt_state,
5234 !get_encapsulated_IA_state(&cli_enc_opt_state,
5243 for ( ; oc != NULL ; oc = oc->
next) {
5249 "error evaluating IAADDR.");
5255 memcpy(cli_addr.iabuf, iaaddr.data, 16);
5260 has_addrs = ISC_TRUE;
5263 for (subnet = shared->
subnets ; subnet != NULL ;
5278 if (subnet == NULL) {
5279 inappropriate = ISC_TRUE;
5298 if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
5305 if (inappropriate) {
5307 "Some of the addresses are not on link.",
5313 "All addresses still on link.",
5323 sizeof(reply_data)-reply_ofs,
5325 required_opts, &packet_oro);
5330 reply_ret->
len = reply_ofs;
5331 reply_ret->
buffer = NULL;
5336 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5340 if (cli_enc_opt_data.buffer != NULL)
5342 if (iaaddr.buffer != NULL)
5344 if (client_id.
buffer != NULL)
5346 if (packet_oro.buffer != NULL)
5350 if (cli_enc_opt_state != NULL)
5352 if (opt_state != NULL)
5366 dhcpv6_renew(
struct data_string *reply,
struct packet *packet) {
5375 if (!valid_client_resp(packet, &client_id, &server_id)) {
5382 lease_to_client(reply, packet, &client_id, &server_id);
5401 dhcpv6_rebind(
struct data_string *reply,
struct packet *packet) {
5406 if (!valid_client_msg(packet, &client_id)) {
5410 lease_to_client(reply, packet, &client_id, NULL);
5418 ia_na_match_decline(
const struct data_string *client_id,
5422 char tmp_addr[INET6_ADDRSTRLEN];
5424 log_error(
"Client %s reports address %s is "
5425 "already in use by another host!",
5427 inet_ntop(AF_INET6, iaaddr->
data,
5428 tmp_addr,
sizeof(tmp_addr)));
5429 if (lease != NULL) {
5437 ia_na_nomatch_decline(
const struct data_string *client_id,
5439 u_int32_t *ia_na_id,
5440 struct packet *packet,
5445 char tmp_addr[INET6_ADDRSTRLEN];
5449 log_info(
"Client %s declines address %s, which is not offered to it.",
5451 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5456 host_opt_state = NULL;
5458 log_error(
"ia_na_nomatch_decline: out of memory "
5459 "allocating option_state.");
5471 if (reply_len < (*reply_ofs + 16)) {
5473 "out of space for reply packet.");
5481 reply_len-(*reply_ofs)-16,
5482 host_opt_state, packet,
5483 required_opts_STATUS_CODE, NULL);
5493 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5495 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5497 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5498 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5503 *reply_ofs += (len + 16);
5511 struct packet *packet,
5514 const char *packet_type,
5515 void (*ia_na_match)(),
5516 void (*ia_na_nomatch)())
5529 char reply_data[65536];
5532 char status_msg[32];
5534 struct ia_xx *existing_ia_na;
5543 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5544 cli_enc_opt_state = NULL;
5545 memset(&iaaddr, 0,
sizeof(iaaddr));
5546 memset(&fixed_addr, 0,
sizeof(fixed_addr));
5547 host_opt_state = NULL;
5567 if (!find_hosts_by_duid_chaddr(&packet_host,
5585 log_error(
"iterate_over_ia_na: no memory for option_state.");
5598 (
unsigned char *)server_duid.data,
5601 "error saving server identifier.");
5608 (
unsigned char *)client_id->
data,
5612 "error saving client identifier.");
5617 if ((packet->
unicast == ISC_TRUE) && !is_unicast_option_defined()) {
5637 snprintf(status_msg,
sizeof(status_msg),
5638 "%s received unicast.", packet_type);
5651 sizeof(reply_data)-reply_ofs,
5653 required_opts_NAA, NULL);
5657 snprintf(status_msg,
sizeof(status_msg),
"%s received.", packet_type);
5666 sizeof(reply_data)-reply_ofs,
5668 required_opts, NULL);
5676 ia != NULL; ia = ia->
next) {
5678 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5684 iaid =
getULong(cli_enc_opt_data.data);
5702 memset(&iaaddr, 0,
sizeof(iaaddr));
5707 "error evaluating IAADDR.");
5721 cli_enc_opt_state,
MDL)) {
5722 if (packet_host != NULL) {
5728 while (host != NULL) {
5736 "evaluating host address.");
5739 if ((iaaddr.
len >= 16) &&
5740 !memcmp(fixed_addr.data, iaaddr.
data, 16)) {
5754 (
char *)client_id->
data,
5756 MDL) != ISC_R_SUCCESS) {
5757 log_fatal(
"iterate_over_ia_na: no memory for "
5761 existing_ia_na = NULL;
5763 (
unsigned char *)key.data,
5770 struct in6_addr *in6_addr;
5773 in6_addr = &tmp->
addr;
5774 if (memcmp(in6_addr,
5775 iaaddr.
data, 16) == 0) {
5786 if ((host != NULL) || (lease != NULL)) {
5787 ia_na_match(client_id, &iaaddr, lease);
5789 ia_na_nomatch(client_id, &iaaddr,
5790 (u_int32_t *)cli_enc_opt_data.
data,
5791 packet, reply_data, &reply_ofs,
5792 sizeof(reply_data));
5795 if (lease != NULL) {
5808 reply_ret->
len = reply_ofs;
5809 reply_ret->
buffer = NULL;
5814 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5817 if (lease != NULL) {
5820 if (host_opt_state != NULL) {
5823 if (fixed_addr.buffer != NULL) {
5826 if (iaaddr.
buffer != NULL) {
5829 if (cli_enc_opt_state != NULL) {
5832 if (cli_enc_opt_data.buffer != NULL) {
5835 if (opt_state != NULL) {
5855 dhcpv6_decline(
struct data_string *reply,
struct packet *packet) {
5864 if (!valid_client_resp(packet, &client_id, &server_id)) {
5876 iterate_over_ia_na(reply, packet, &client_id, &server_id,
"Decline",
5877 ia_na_match_decline, ia_na_nomatch_decline);
5886 ia_na_match_release(
const struct data_string *client_id,
5890 char tmp_addr[INET6_ADDRSTRLEN];
5892 log_info(
"Client %s releases address %s",
5894 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5895 if (lease != NULL) {
5903 ia_na_nomatch_release(
const struct data_string *client_id,
5905 u_int32_t *ia_na_id,
5906 struct packet *packet,
5911 char tmp_addr[INET6_ADDRSTRLEN];
5915 log_info(
"Client %s releases address %s, which is not leased to it.",
5917 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5922 host_opt_state = NULL;
5924 log_error(
"ia_na_nomatch_release: out of memory "
5925 "allocating option_state.");
5930 "Release for non-leased address.",
5938 if (reply_len < (*reply_ofs + 16)) {
5940 "out of space for reply packet.");
5948 reply_len-(*reply_ofs)-16,
5949 host_opt_state, packet,
5950 required_opts_STATUS_CODE, NULL);
5960 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5962 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5964 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5965 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5970 *reply_ofs += (len + 16);
5977 ia_pd_match_release(
const struct data_string *client_id,
5981 char tmp_addr[INET6_ADDRSTRLEN];
5983 log_info(
"Client %s releases prefix %s/%u",
5985 inet_ntop(AF_INET6, iapref->
data + 9,
5986 tmp_addr,
sizeof(tmp_addr)),
5988 if (prefix != NULL) {
5996 ia_pd_nomatch_release(
const struct data_string *client_id,
5998 u_int32_t *ia_pd_id,
5999 struct packet *packet,
6004 char tmp_addr[INET6_ADDRSTRLEN];
6008 log_info(
"Client %s releases prefix %s/%u, which is not leased to it.",
6010 inet_ntop(AF_INET6, iapref->
data + 9,
6011 tmp_addr,
sizeof(tmp_addr)),
6017 host_opt_state = NULL;
6019 log_error(
"ia_pd_nomatch_release: out of memory "
6020 "allocating option_state.");
6025 "Release for non-leased prefix.",
6033 if (reply_len < (*reply_ofs + 16)) {
6035 "out of space for reply packet.");
6043 reply_len-(*reply_ofs)-16,
6044 host_opt_state, packet,
6045 required_opts_STATUS_CODE, NULL);
6055 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
6057 memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
6059 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
6060 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
6065 *reply_ofs += (len + 16);
6073 struct packet *packet,
6076 const char *packet_type,
6077 void (*ia_pd_match)(),
6078 void (*ia_pd_nomatch)())
6092 char reply_data[65536];
6095 struct ia_xx *existing_ia_pd;
6103 memset(&reply_new, 0,
sizeof(reply_new));
6105 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
6106 cli_enc_opt_state = NULL;
6107 memset(&iaprefix, 0,
sizeof(iaprefix));
6108 host_opt_state = NULL;
6114 reply_len =
sizeof(reply_data) - reply_ret->
len;
6134 if (!find_hosts_by_duid_chaddr(&packet_host,
6145 log_error(
"iterate_over_ia_pd: no memory for option_state.");
6157 ia != NULL; ia = ia->
next) {
6159 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
6165 iaid =
getULong(cli_enc_opt_data.data);
6176 for (; oc != NULL; oc = oc->
next) {
6177 memset(&iaprefix, 0,
sizeof(iaprefix));
6182 "error evaluating IAPREFIX.");
6196 cli_enc_opt_state,
MDL)) {
6197 if (packet_host != NULL) {
6203 while (host != NULL) {
6212 if (memcmp(iaprefix.data + 9,
6217 if ((l != NULL) && (iaprefix.len >= 17))
6228 (
char *)client_id->
data,
6230 MDL) != ISC_R_SUCCESS) {
6231 log_fatal(
"iterate_over_ia_pd: no memory for "
6235 existing_ia_pd = NULL;
6237 (
unsigned char *)key.data,
6248 plen =
getUChar(iaprefix.data + 8);
6250 if ((tmp->
plen == plen) &&
6264 if ((host != NULL) || (prefix != NULL)) {
6265 ia_pd_match(client_id, &iaprefix, prefix);
6267 ia_pd_nomatch(client_id, &iaprefix,
6268 (u_int32_t *)cli_enc_opt_data.
data,
6269 packet, reply_data, &reply_ofs,
6270 reply_len - reply_ofs);
6273 if (prefix != NULL) {
6288 reply_new.len = reply_ret->
len + reply_ofs;
6292 reply_new.data = reply_new.buffer->data;
6293 memcpy(reply_new.buffer->data,
6295 memcpy(reply_new.buffer->data + reply_ret->
len,
6296 reply_data, reply_ofs);
6302 if (prefix != NULL) {
6305 if (host_opt_state != NULL) {
6308 if (iaprefix.buffer != NULL) {
6311 if (cli_enc_opt_state != NULL) {
6314 if (cli_enc_opt_data.buffer != NULL) {
6317 if (opt_state != NULL) {
6327 dhcpv6_release(
struct data_string *reply,
struct packet *packet) {
6336 if (!valid_client_resp(packet, &client_id, &server_id)) {
6343 iterate_over_ia_na(reply, packet, &client_id, &server_id,
"Release",
6344 ia_na_match_release, ia_na_nomatch_release);
6349 iterate_over_ia_pd(reply, packet, &client_id, &server_id,
"Release",
6350 ia_pd_match_release, ia_pd_nomatch_release);
6364 dhcpv6_information_request(
struct data_string *reply,
struct packet *packet) {
6373 if (!valid_client_info_req(packet, &server_id)) {
6380 memset(&client_id, 0,
sizeof(client_id));
6391 lease_to_client(reply, packet, &client_id,
6392 server_id.
data != NULL ? &server_id : NULL);
6397 if (client_id.
data != NULL) {
6415 dhcpv6_relay_forw(
struct data_string *reply_ret,
struct packet *packet) {
6418 struct packet *enc_packet;
6419 unsigned char msg_type;
6423 char link_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6424 char peer_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6427 static char reply_data[65536];
6437 memset(&a_opt, 0,
sizeof(a_opt));
6438 memset(&packet_ero, 0,
sizeof(packet_ero));
6439 memset(&enc_reply, 0,
sizeof(enc_reply));
6440 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6449 link_addr,
sizeof(link_addr));
6451 peer_addr,
sizeof(peer_addr));
6452 log_info(
"Relay-forward from %s with link address=%s and "
6453 "peer address=%s missing Relay Message option.",
6460 log_error(
"dhcpv6_forw_relay: error evaluating "
6461 "relayed message.");
6466 log_error(
"dhcpv6_forw_relay: encapsulated packet too short.");
6476 "no memory for encapsulated packet.");
6482 "no memory for encapsulated packet's options.");
6491 msg_type = enc_opt_data.
data[0];
6507 enc_opt_data.
len - relaylen,
6525 enc_opt_data.
len - msglen,
6537 build_dhcpv6_reply(&enc_reply, enc_packet);
6543 if (enc_reply.data == NULL) {
6565 log_error(
"dhcpv6_relay_forw: no memory for option state.");
6579 log_error(
"dhcpv6_relay_forw: error evaluating "
6584 (
unsigned char *)a_opt.data,
6587 log_error(
"dhcpv6_relay_forw: error saving "
6598 (
unsigned char *)enc_reply.data,
6601 log_error(
"dhcpv6_relay_forw: error saving Relay MSG.");
6617 (packet_ero.len & 1)) {
6618 log_error(
"dhcpv6_relay_forw: error evaluating ERO.");
6623 for (i = 0; i < packet_ero.len; i += 2) {
6640 "evaluating option %u.", req);
6646 (
unsigned char *)a_opt.data,
6650 log_error(
"dhcpv6_relay_forw: error saving "
6659 sizeof(reply_data) - reply_ofs,
6661 required_opts_agent, &packet_ero);
6666 reply_ret->
len = reply_ofs;
6667 reply_ret->
buffer = NULL;
6672 memcpy(reply_ret->
buffer->
data, reply_data, reply_ofs);
6675 if (opt_state != NULL)
6677 if (a_opt.data != NULL) {
6680 if (packet_ero.data != NULL) {
6683 if (enc_reply.data != NULL) {
6686 if (enc_opt_data.
data != NULL) {
6689 if (enc_packet != NULL) {
6697 dhcpv6_discard(
struct packet *packet) {
6701 log_debug(
"Discarding %s from %s; message type not handled by server",
6707 build_dhcpv6_reply(
struct data_string *reply,
struct packet *packet) {
6708 memset(reply, 0,
sizeof(*reply));
6721 dhcpv6_solicit(reply, packet);
6724 dhcpv6_discard(packet);
6728 dhcpv6_request(reply, packet);
6732 dhcpv6_confirm(reply, packet);
6736 dhcpv6_renew(reply, packet);
6740 dhcpv6_rebind(reply, packet);
6743 dhcpv6_discard(packet);
6747 dhcpv6_release(reply, packet);
6751 dhcpv6_decline(reply, packet);
6754 dhcpv6_discard(packet);
6758 dhcpv6_information_request(reply, packet);
6761 dhcpv6_relay_forw(reply, packet);
6764 dhcpv6_discard(packet);
6771 dhcpv6_discard(packet);
6776 log_info(
"Discarding unknown DHCPv6 message type %d "
6783 log_packet_in(
const struct packet *packet) {
6786 char tmp_addr[INET6_ADDRSTRLEN];
6789 memset(&s, 0,
sizeof(s));
6798 "Unknown message type %d from %s port %d",
6807 inet_ntop(AF_INET6, addr,
6808 tmp_addr,
sizeof(tmp_addr)));
6811 inet_ntop(AF_INET6, addr,
6812 tmp_addr,
sizeof(tmp_addr)));
6842 dhcpv6(
struct packet *packet) {
6844 struct sockaddr_in6 to_addr;
6850 log_packet_in(packet);
6855 build_dhcpv6_reply(&reply, packet);
6857 if (reply.
data != NULL) {
6861 memset(&to_addr, 0,
sizeof(to_addr));
6862 to_addr.sin6_family = AF_INET6;
6870 #if defined (REPLY_TO_SOURCE_PORT)
6882 sizeof(to_addr.sin6_addr));
6884 log_info(
"Sending %s to %s port %d",
6887 ntohs(to_addr.sin6_port));
6890 reply.
data, reply.
len, &to_addr);
6891 if (send_ret != reply.
len) {
6892 log_error(
"dhcpv6: send_packet6() sent %d of %d bytes",
6893 send_ret, reply.
len);
6909 host_reference(&hold, *hp,
MDL);
6910 host_dereference(hp,
MDL);
6912 while (seek != NULL) {
6915 else if (fixed_matches_shared(seek, shared))
6921 if ((seek == NULL) && (nofixed != NULL))
6925 host_reference(hp, seek,
MDL);
6928 static isc_boolean_t
6930 struct subnet *subnet;
6932 isc_boolean_t matched;
6938 memset(&addr, 0,
sizeof(addr));
6943 if (addr.len < 16) {
6949 memcpy(fixed.iabuf, addr.data, 16);
6951 matched = ISC_FALSE;
6952 for (subnet = shared->
subnets ; subnet != NULL ;
6971 find_hosts_by_duid_chaddr(
struct host_decl **host,
6973 static int once_htype;
6975 const unsigned char *chaddr;
6981 if (client_id->
len < 4)
6995 if (client_id->
len > 8) {
6996 hlen = client_id->
len - 8;
6997 chaddr = client_id->
data + 8;
7006 hlen = client_id->
len - 4;
7007 chaddr = client_id->
data + 4;
7027 if ((htype & 0xFF00) && !once_htype) {
7029 log_error(
"Attention: At least one client advertises a "
7030 "hardware type of %d, which exceeds the software "
7031 "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
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 *)
struct enumeration_value * values
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)
#define FIND_POND6_PERCENT(count, percent)
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()
isc_uint64_t low_threshold
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_uint64_t num_abandoned
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
struct enumeration prefix_length_modes
#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)