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 struct group *find_group_by_prefix(
struct reply_state *reply);
136 static isc_result_t reply_process_prefix(
struct reply_state *reply,
138 static isc_boolean_t prefix_is_owned(
struct reply_state *reply,
140 static isc_result_t find_client_prefix(
struct reply_state *reply);
141 static isc_result_t reply_process_try_prefix(
struct reply_state *reply,
143 static isc_result_t reply_process_is_prefixed(
struct reply_state *reply,
146 static isc_result_t reply_process_send_prefix(
struct reply_state *reply,
148 static struct iasubopt *prefix_compare(
struct reply_state *reply,
151 static int find_hosts_by_duid_chaddr(
struct host_decl **host,
153 static void schedule_lease_timeout_reply(
struct reply_state *reply);
155 static int eval_prefix_mode(
int thislen,
int preflen,
int prefix_mode);
156 static isc_result_t pick_v6_prefix_helper(
struct reply_state *reply,
163 static isc_boolean_t is_unicast_option_defined(
struct packet *
packet);
164 static isc_result_t shared_network_from_requested_addr (
struct shared_network 167 static isc_result_t get_first_ia_addr_val (
struct packet*
packet,
int addr_type,
176 schedule_lease_timeout_reply(
struct reply_state *reply) {
181 if ((reply == NULL) || (reply->ia == NULL) || (reply->ia->iasubopt == NULL))
185 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
186 tmp = reply->ia->iasubopt[i];
196 duid_time(time_t when) {
233 return (server_duid.data != NULL);
271 isc_result_t ret_val;
284 ret_val = ISC_R_NOTFOUND;
286 memset(&option_duid, 0,
sizeof(option_duid));
290 ret_val = ISC_R_UNEXPECTED;
294 ret_val = ISC_R_SUCCESS;
313 static int server_duid_type =
DUID_LLT;
320 server_duid_type = type;
337 log_error(
"Invalid DUID type %d specified, " 338 "only LL and LLT types supported", server_duid_type);
351 log_error(
"Can not generate DUID from interfaces which do not have hardware addresses, please configure server-duid!");
355 return ISC_R_UNEXPECTED;
361 memset(&generated_duid, 0,
sizeof(generated_duid));
363 time_val = duid_time(time(NULL));
366 generated_duid.len,
MDL)) {
369 generated_duid.data = generated_duid.buffer->data;
371 putUShort(generated_duid.buffer->data + 2,
373 putULong(generated_duid.buffer->data + 4, time_val);
374 memcpy(generated_duid.buffer->data + 8,
376 }
else if (server_duid_type ==
DUID_LL) {
379 generated_duid.len,
MDL)) {
382 generated_duid.data = generated_duid.buffer->data;
384 putUShort(generated_duid.buffer->data + 2,
386 memcpy(generated_duid.buffer->data + 4,
389 log_fatal(
"Unsupported server DUID type %d.", server_duid_type);
395 return ISC_R_SUCCESS;
408 if ((client_id->
data != NULL) || (client_id->
len != 0)) {
414 return ISC_R_NOTFOUND;
420 return ISC_R_FAILURE;
423 return ISC_R_SUCCESS;
434 valid_client_msg(
struct packet *packet,
struct data_string *client_id) {
440 memset(client_id, 0,
sizeof(*client_id));
448 "client identifier missing",
453 log_error(
"Error processing %s from %s; " 454 "unable to evaluate Client Identifier",
464 log_debug(
"Discarding %s from %s; packet sent unicast " 479 "server identifier found " 480 "(CLIENTID %s, SERVERID %s)",
484 client_id->
data, 60),
489 "server identifier found " 493 client_id->
data, 60),
507 if (client_id->
len > 0) {
527 valid_client_resp(
struct packet *packet,
537 memset(client_id, 0,
sizeof(*client_id));
538 memset(server_id, 0,
sizeof(*server_id));
545 "client identifier missing",
550 log_error(
"Error processing %s from %s; " 551 "unable to evaluate Client Identifier",
560 "server identifier missing (CLIENTID %s)",
569 log_error(
"Error processing %s from %s; " 570 "unable to evaluate Server Identifier (CLIENTID %s)",
576 if ((server_duid.len != server_id->
len) ||
577 (memcmp(server_duid.data, server_id->
data, server_duid.len) != 0)) {
579 "not our server identifier " 580 "(CLIENTID %s, SERVERID %s, server DUID %s)",
585 print_hex_3(server_duid.len, server_duid.data, 60));
594 if (server_id->
len > 0) {
597 if (client_id->
len > 0) {
616 valid_client_info_req(
struct packet *packet,
struct data_string *server_id) {
620 char client_id_str[80];
624 memset(server_id, 0,
sizeof(*server_id));
625 memset(&client_id, 0,
sizeof(client_id));
636 snprintf(client_id_str,
sizeof(client_id_str),
" (CLIENTID %s)",
640 client_id_str[0] =
'\0';
647 log_debug(
"Discarding %s from %s; packet sent unicast%s",
656 "IA_NA option present%s",
664 "IA_TA option present%s",
672 "IA_PD option present%s",
683 log_error(
"Error processing %s from %s; " 684 "unable to evaluate Server Identifier%s",
689 if ((server_duid.len != server_id->
len) ||
690 (memcmp(server_duid.data, server_id->
data,
691 server_duid.len) != 0)) {
693 "not our server identifier " 694 "(SERVERID %s, server DUID %s)%s",
698 server_id->
data, 60),
700 server_duid.data, 60),
711 if (server_id->
len > 0) {
722 static const int required_opts[] = {
729 static const int required_opts_solicit[] = {
741 static const int required_opts_agent[] = {
746 static const int required_opts_IA[] = {
751 static const int required_opts_IA_PD[] = {
756 static const int required_opts_STATUS_CODE[] = {
761 static const int unicast_reject_opts[] = {
776 get_encapsulated_IA_state(
struct option_state **enc_opt_state,
778 struct packet *packet,
785 memset(enc_opt_data, 0,
sizeof(*enc_opt_data));
787 NULL, NULL, packet->
options, NULL,
790 "error evaluating raw option.");
793 if (enc_opt_data->
len < offset) {
794 log_error(
"get_encapsulated_IA_state: raw option too small.");
803 *enc_opt_state = NULL;
805 log_error(
"get_encapsulated_IA_state: no memory for options.");
810 enc_opt_data->
data + offset,
811 enc_opt_data->
len - offset,
813 log_error(
"get_encapsulated_IA_state: error parsing options.");
823 set_status_code(u_int16_t status_code,
const char *status_message,
829 memset(&d, 0,
sizeof(d));
830 d.len =
sizeof(status_code) + strlen(status_message);
832 log_fatal(
"set_status_code: no memory for status code.");
834 d.data = d.buffer->data;
836 memcpy(d.buffer->data +
sizeof(status_code),
837 status_message, d.len -
sizeof(status_code));
839 d.buffer, (
unsigned char *)d.data, d.len,
841 log_error(
"set_status_code: error saving status code.");
850 void check_pool6_threshold(
struct reply_state *reply,
854 isc_uint64_t used, count, high_threshold;
855 int poolhigh = 0, poollow = 0;
856 char *shared_name =
"no name";
857 char tmp_addr[INET6_ADDRSTRLEN];
891 log_error(
"Pool threshold reset - shared subnet: %s; " 892 "address: %s; low threshold %llu/%llu.",
894 inet_ntop(AF_INET6, &lease->
addr,
895 tmp_addr,
sizeof(tmp_addr)),
903 NULL, reply->packet->options, reply->opt_state,
904 reply->opt_state, &lease->
scope,
911 if ((poolhigh <= 0) || (poolhigh > 100)) {
918 if (used < high_threshold) {
924 log_error(
"Pool threshold exceeded - shared subnet: %s; " 925 "address: %s; high threshold %d%% %llu/%llu.",
927 inet_ntop(AF_INET6, &lease->
addr, tmp_addr,
sizeof(tmp_addr)),
928 poolhigh, used, count);
933 NULL, reply->packet->options, reply->opt_state,
934 reply->opt_state, &lease->
scope,
945 if (poollow < poolhigh) {
956 start_reply(
struct packet *packet,
963 const unsigned char *server_id_data;
971 log_error(
"start_reply: no memory for option_state.");
1039 if (server_id == NULL) {
1040 server_id_data = server_duid.data;
1041 server_id_len = server_duid.len;
1043 server_id_data = server_id->
data;
1044 server_id_len = server_id->
len;
1047 NULL, (
unsigned char *)server_id_data,
1050 "error saving server identifier.");
1055 if (client_id->
buffer != NULL) {
1058 (
unsigned char *)client_id->
data,
1062 "client identifier.");
1078 NULL, (
unsigned char *)
"", 0,
1081 "error saving RECONF_ACCEPT option.");
1099 try_client_v6_address(
struct iasubopt **addr,
1103 struct in6_addr tmp_addr;
1104 isc_result_t result;
1106 if (requested_addr->
len <
sizeof(tmp_addr)) {
1109 memcpy(&tmp_addr, requested_addr->
data,
sizeof(tmp_addr));
1110 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
1111 return ISC_R_FAILURE;
1119 return ISC_R_ADDRNOTAVAIL;
1123 return ISC_R_ADDRINUSE;
1126 result = iasubopt_allocate(addr,
MDL);
1127 if (result != ISC_R_SUCCESS) {
1130 (*addr)->addr = tmp_addr;
1135 if (result != ISC_R_SUCCESS) {
1164 pick_v6_address(
struct reply_state *reply)
1170 unsigned int attempts;
1171 char tmp_buf[INET6_ADDRSTRLEN];
1172 struct iasubopt **addr = &reply->lease;
1173 isc_uint64_t total = 0;
1174 isc_uint64_t active = 0;
1175 isc_uint64_t abandoned = 0;
1176 int jumbo_range = 0;
1177 char *shared_name = (reply->shared->name ?
1178 reply->shared->name :
"(no name)");
1184 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1188 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1198 log_debug(
"Unable to pick client address: " 1199 "no IPv6 pools on this shared network");
1200 return ISC_R_NORESOURCES;
1214 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1215 isc_result_t result = ISC_R_FAILURE;
1229 &reply->ia->iaid_duid,
1231 if (result == ISC_R_SUCCESS) {
1249 tmp_buf,
sizeof(tmp_buf)));
1250 return (ISC_R_SUCCESS);
1258 }
while (i != start_pool);
1260 if (result == ISC_R_NORESOURCES) {
1272 if (jumbo_range != 0) {
1273 log_debug(
"Unable to pick client address: " 1274 "no addresses available - shared network %s: " 1275 " 2^64-1 < total, %llu active, %llu abandoned",
1276 shared_name, active - abandoned, abandoned);
1278 log_debug(
"Unable to pick client address: " 1279 "no addresses available - shared network %s: " 1280 "%llu total, %llu active, %llu abandoned",
1281 shared_name, total, active - abandoned, abandoned);
1284 return ISC_R_NORESOURCES;
1296 try_client_v6_prefix(
struct iasubopt **pref,
1301 struct in6_addr tmp_pref;
1303 isc_result_t result;
1305 if (requested_pref->
len <
sizeof(tmp_plen) +
sizeof(tmp_pref)) {
1308 tmp_plen = (
int) requested_pref->
data[0];
1309 if ((tmp_plen < 3) || (tmp_plen > 128) ||
1310 ((
int)tmp_plen != pool->
units)) {
1311 return ISC_R_FAILURE;
1313 memcpy(&tmp_pref, requested_pref->
data + 1,
sizeof(tmp_pref));
1314 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
1315 return ISC_R_FAILURE;
1318 memcpy(&ia.iabuf, &tmp_pref, 16);
1320 return ISC_R_FAILURE;
1324 return ISC_R_ADDRNOTAVAIL;
1328 return ISC_R_ADDRINUSE;
1331 result = iasubopt_allocate(pref,
MDL);
1332 if (result != ISC_R_SUCCESS) {
1335 (*pref)->addr = tmp_pref;
1336 (*pref)->plen = tmp_plen;
1340 if (result != ISC_R_SUCCESS) {
1386 pick_v6_prefix(
struct reply_state *reply) {
1390 isc_result_t result;
1396 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1400 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1410 log_debug(
"Unable to pick client prefix: " 1411 "no IPv6 pools on this shared network");
1412 return ISC_R_NORESOURCES;
1415 if (reply->preflen <= 0) {
1418 result = pick_v6_prefix_helper(reply,
PLM_IGNORE);
1424 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1425 if (result != ISC_R_SUCCESS) {
1426 result = pick_v6_prefix_helper(reply,
1433 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1440 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1441 if (result != ISC_R_SUCCESS) {
1442 result = pick_v6_prefix_helper(reply,
1449 result = pick_v6_prefix_helper(reply,
PLM_IGNORE);
1454 if (result == ISC_R_SUCCESS) {
1455 char tmp_buf[INET6_ADDRSTRLEN];
1458 inet_ntop(AF_INET6, &(reply->lease->addr),
1459 tmp_buf,
sizeof(tmp_buf)),
1460 (
unsigned)(reply->lease->plen));
1461 return (ISC_R_SUCCESS);
1468 log_debug(
"Unable to pick client prefix: no prefixes available");
1469 return ISC_R_NORESOURCES;
1496 pick_v6_prefix_helper(
struct reply_state *reply,
int prefix_mode) {
1500 unsigned int attempts;
1501 struct iasubopt **pref = &reply->lease;
1503 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1510 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1512 (eval_prefix_mode(p->
units, reply->preflen,
1513 prefix_mode) == 1) &&
1515 &reply->ia->iaid_duid,
1516 cur_time + 120) == ISC_R_SUCCESS)) {
1517 return (ISC_R_SUCCESS);
1522 return ISC_R_NORESOURCES;
1540 eval_prefix_mode(
int len,
int preflen,
int prefix_mode) {
1542 switch (prefix_mode) {
1544 use_it = (len == preflen);
1548 use_it = (len >= preflen);
1552 use_it = (len <= preflen);
1561 "len %d, preflen %d, mode %s, use_it %d",
1606 struct packet *packet,
1610 static struct reply_state reply;
1615 memset(&packet_oro, 0,
sizeof(packet_oro));
1618 if (shared_network_from_packet6(&reply.shared,
1619 packet) != ISC_R_SUCCESS)
1628 if (!start_reply(packet, client_id, server_id, &reply.opt_state,
1644 log_error(
"lease_to_client: error evaluating ORO.");
1656 seek_shared_host(&reply.host, reply.shared);
1659 if ((reply.host == NULL) &&
1662 seek_shared_host(&reply.host, reply.shared);
1669 if ((reply.host == NULL) &&
1670 find_hosts_by_duid_chaddr(&reply.host, client_id)) {
1672 seek_shared_host(&reply.host, reply.shared);
1679 for (; oc != NULL ; oc = oc->
next) {
1680 isc_result_t status;
1683 reply.client_resources = 0;
1684 reply.resources_included = ISC_FALSE;
1686 status = reply_process_ia_na(&reply, oc);
1692 if ((status != ISC_R_SUCCESS) &&
1693 (status != ISC_R_NORESOURCES))
1697 for (; oc != NULL ; oc = oc->
next) {
1698 isc_result_t status;
1701 reply.client_resources = 0;
1702 reply.resources_included = ISC_FALSE;
1704 status = reply_process_ia_ta(&reply, oc);
1710 if ((status != ISC_R_SUCCESS) &&
1711 (status != ISC_R_NORESOURCES))
1718 for (; oc != NULL ; oc = oc->
next) {
1719 isc_result_t status;
1722 reply.client_resources = 0;
1723 reply.resources_included = ISC_FALSE;
1725 status = reply_process_ia_pd(&reply, oc);
1731 if ((status != ISC_R_SUCCESS) &&
1732 (status != ISC_R_NORESOURCES))
1740 if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
1741 if (reply.packet->dhcpv6_msg_type !=
1751 reply.packet->options,
1757 for (i = reply.packet->class_count; i > 0; i--) {
1760 reply.packet->options,
1763 reply.packet->classes[i - 1]->group,
1764 reply.shared->group, NULL);
1768 if (reply.host != NULL)
1771 reply.packet->options,
1775 reply.shared->group, NULL);
1810 reply.cursor +=
store_options6((
char *)reply.buf.data + reply.cursor,
1811 sizeof(reply.buf) - reply.cursor,
1812 reply.opt_state, reply.packet,
1813 required_opts_solicit,
1817 reply_ret->
len = reply.cursor;
1818 reply_ret->
buffer = NULL;
1822 memcpy(reply_ret->
buffer->
data, reply.buf.data, reply.cursor);
1830 if (reply.shared != NULL)
1831 shared_network_dereference(&reply.shared,
MDL);
1832 if (reply.host != NULL)
1833 host_dereference(&reply.host,
MDL);
1834 if (reply.opt_state != NULL)
1836 if (reply.packet != NULL)
1838 if (reply.client_id.data != NULL)
1840 if (packet_oro.buffer != NULL)
1842 reply.renew = reply.rebind = reply.prefer = reply.valid = 0;
1850 reply_process_ia_na(
struct reply_state *reply,
struct option_cache *ia) {
1851 isc_result_t status = ISC_R_SUCCESS;
1860 memset(&ia_data, 0,
sizeof(ia_data));
1867 if ((reply->cursor +
IA_NA_OFFSET + 4) >
sizeof(reply->buf)) {
1868 log_error(
"reply_process_ia_na: Reply too long for IA.");
1869 return ISC_R_NOSPACE;
1874 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
1876 log_error(
"reply_process_ia_na: error evaluating ia");
1877 status = ISC_R_FAILURE;
1883 reply->renew =
getULong(ia_data.data + 4);
1884 reply->rebind =
getULong(ia_data.data + 8);
1887 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
1888 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
1889 log_error(
"reply_process_ia_na: no memory for ia.");
1890 status = ISC_R_NOMEMORY;
1897 (
unsigned char *)reply->ia->iaid_duid.data,
1898 reply->ia->iaid_duid.len,
MDL);
1905 status = ISC_R_NOMEMORY;
1910 if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
1911 struct iaddr tmp_addr;
1915 reply->host->fixed_addr,
MDL)) {
1916 log_error(
"reply_process_ia_na: unable to evaluate " 1918 status = ISC_R_FAILURE;
1922 if (reply->fixed.len < 16) {
1923 log_error(
"reply_process_ia_na: invalid fixed address.");
1930 memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
1933 tmp_addr,
MDL) == 0)
1936 reply->static_lease = ISC_TRUE;
1938 reply->static_lease = ISC_FALSE;
1946 ia_cursor = reply->cursor;
1953 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
1957 putULong(reply->buf.data + reply->cursor, iaid);
1961 putULong(reply->buf.data + reply->cursor, reply->renew);
1965 putULong(reply->buf.data + reply->cursor, reply->rebind);
1978 reply->valid = reply->prefer = 0xffffffff;
1979 reply->client_valid = reply->client_prefer = 0;
1980 for (; oc != NULL ; oc = oc->
next) {
1981 status = reply_process_addr(reply, oc);
1989 if (status == ISC_R_CANCELED)
1992 if ((status != ISC_R_SUCCESS) &&
1993 (status != ISC_R_ADDRINUSE) &&
1994 (status != ISC_R_ADDRNOTAVAIL))
2004 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
2005 status = find_client_address(reply);
2007 if (status == ISC_R_NORESOURCES) {
2008 switch (reply->packet->dhcpv6_msg_type) {
2031 "memory for option state " 2033 status = ISC_R_NOMEMORY;
2038 "No addresses available " 2039 "for this interface.",
2041 log_error(
"reply_process_ia_na: Unable " 2042 "to set NoAddrsAvail status " 2044 status = ISC_R_FAILURE;
2048 status = ISC_R_SUCCESS;
2068 if (reply->resources_included)
2069 status = ISC_R_SUCCESS;
2076 if (status != ISC_R_SUCCESS)
2080 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2081 sizeof(reply->buf) - reply->cursor,
2082 reply->reply_ia, reply->packet,
2083 required_opts_IA, NULL);
2086 putUShort(reply->buf.data + ia_cursor + 2,
2087 reply->cursor - (ia_cursor + 4));
2100 reply->packet->options,
2106 reply->renew =
getULong(data.data);
2109 if (data.data != NULL)
2112 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
2120 reply->packet->options,
2126 reply->rebind =
getULong(data.data);
2129 if (data.data != NULL)
2132 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
2138 if (status == ISC_R_CANCELED)
2145 if (reply->static_lease) {
2146 char tmp_addr[INET6_ADDRSTRLEN];
2147 log_info(
"%s NA: address %s to client with duid %s iaid = %d " 2150 inet_ntop(AF_INET6, reply->fixed.data, tmp_addr,
2153 reply->client_id.data, 60),
2157 (reply->on_star.on_commit != NULL)) {
2159 reply->packet->options,
2160 reply->opt_state, NULL,
2161 reply->on_star.on_commit, NULL);
2163 (&reply->on_star.on_commit,
MDL);
2171 if (reply->ia->num_iasubopt != 0) {
2174 char tmp_addr[INET6_ADDRSTRLEN];
2176 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2177 tmp = reply->ia->iasubopt[i];
2179 log_info(
"%s NA: address %s to client with duid %s " 2180 "iaid = %d valid for %d seconds",
2182 inet_ntop(AF_INET6, &tmp->
addr,
2183 tmp_addr,
sizeof(tmp_addr)),
2185 reply->client_id.data, 60),
2199 if ((reply->ia->num_iasubopt != 0) &&
2205 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2206 tmp = reply->ia->iasubopt[i];
2208 if (tmp->
ia != NULL)
2220 reply->packet->options,
2229 #if defined (NSUPDATE) 2238 reply->packet->options,
2243 tmp, NULL, reply->opt_state);
2247 check_pool6_threshold(reply, tmp);
2251 if (reply->old_ia != NULL) {
2252 ia_id = &reply->old_ia->iaid_duid;
2254 (
unsigned char *)ia_id->
data,
2261 ia_id = &reply->ia->iaid_duid;
2263 ia_id->
len, reply->ia,
MDL);
2267 schedule_lease_timeout_reply(reply);
2271 if (packet_ia != NULL)
2273 if (reply->reply_ia != NULL)
2275 if (ia_data.data != NULL)
2277 if (
data.data != NULL)
2279 if (reply->ia != NULL)
2281 if (reply->old_ia != NULL)
2283 if (reply->lease != NULL)
2285 if (reply->fixed.data != NULL)
2287 if (reply->subnet != NULL)
2288 subnet_dereference(&reply->subnet,
MDL);
2289 if (reply->on_star.on_expiry != NULL)
2291 (&reply->on_star.on_expiry,
MDL);
2292 if (reply->on_star.on_release != NULL)
2294 (&reply->on_star.on_release,
MDL);
2301 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2311 reply_process_addr(
struct reply_state *reply,
struct option_cache *addr) {
2312 u_int32_t pref_life, valid_life;
2316 struct iaddr tmp_addr;
2319 isc_result_t status = ISC_R_SUCCESS;
2322 memset(&iaaddr, 0,
sizeof(iaaddr));
2330 if ((reply->cursor + 28) >
sizeof(reply->buf)) {
2331 log_error(
"reply_process_addr: Out of room for address.");
2332 return ISC_R_NOSPACE;
2340 log_error(
"reply_process_addr: error evaluating IAADDR.");
2341 status = ISC_R_FAILURE;
2346 pref_life =
getULong(iaaddr.data + 16);
2347 valid_life =
getULong(iaaddr.data + 20);
2349 if ((reply->client_valid == 0) ||
2350 (reply->client_valid > valid_life))
2351 reply->client_valid = valid_life;
2353 if ((reply->client_prefer == 0) ||
2354 (reply->client_prefer > pref_life))
2355 reply->client_prefer = pref_life;
2362 memset(tmp_addr.iabuf, 0, 16);
2363 if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
2369 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2374 for (subnet = reply->shared->subnets ; subnet != NULL ;
2382 if (subnet == NULL) {
2407 log_error(
"reply_process_addr: No memory for " 2408 "option state wipe.");
2409 status = ISC_R_NOMEMORY;
2415 "Address not for use on this " 2416 "link.", reply->reply_ia)) {
2417 log_error(
"reply_process_addr: Failure " 2418 "setting status code.");
2419 status = ISC_R_FAILURE;
2424 status = ISC_R_CANCELED;
2436 if ((reply->packet->dhcpv6_msg_type !=
DHCPV6_RENEW) &&
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;
2445 reply->send_prefer = reply->send_valid = 0;
2450 if (!address_is_owned(reply, &tmp_addr)) {
2461 status = reply_process_try_addr(reply, &tmp_addr);
2468 if ((status != ISC_R_SUCCESS) &&
2469 (status != ISC_R_ADDRINUSE) &&
2470 (status != ISC_R_ADDRNOTAVAIL))
2478 if (reply->lease == NULL) {
2479 if (reply->packet->dhcpv6_msg_type ==
2481 reply->send_prefer = 0;
2482 reply->send_valid = 0;
2499 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
2503 log_error(
"reply_process_addr: No memory for " 2504 "option state wipe.");
2505 status = ISC_R_NOMEMORY;
2511 "Address not bound to this " 2512 "interface.", reply->reply_ia)) {
2513 log_error(
"reply_process_addr: Unable to " 2514 "attach status code.");
2515 status = ISC_R_FAILURE;
2520 status = ISC_R_CANCELED;
2523 log_error(
"It is impossible to lease a client that is " 2524 "not sending a solicit, request, renew, or " 2526 status = ISC_R_FAILURE;
2531 if (reply->static_lease) {
2532 if (reply->host == NULL)
2536 group = reply->subnet->group;
2538 if (reply->lease == NULL)
2541 scope = &reply->lease->scope;
2542 group = reply->lease->ipv6_pool->ipv6_pond->group;
2551 if (reply->client_resources != 0) {
2564 reply->packet->options,
2568 log_error(
"reply_process_addr: unable to " 2569 "evaluate addrs-per-ia value.");
2570 status = ISC_R_FAILURE;
2582 if (reply->client_resources >= limit)
2586 status = reply_process_is_addressed(reply, scope, group);
2587 if (status != ISC_R_SUCCESS)
2591 status = reply_process_send_addr(reply, &tmp_addr);
2594 if (iaaddr.data != NULL)
2596 if (
data.data != NULL)
2598 if (reply->lease != NULL)
2610 static isc_boolean_t
2611 address_is_owned(
struct reply_state *reply,
struct iaddr *addr) {
2618 if (reply->static_lease) {
2619 if (reply->fixed.data == NULL)
2622 if (memcmp(addr->
iabuf, reply->fixed.data, 16) == 0)
2628 if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
2631 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2634 tmp = reply->old_ia->iasubopt[i];
2636 if (memcmp(addr->
iabuf, &tmp->
addr, 16) == 0) {
2661 reply_process_ia_ta(
struct reply_state *reply,
struct option_cache *ia) {
2662 isc_result_t status = ISC_R_SUCCESS;
2669 u_int32_t pref_life, valid_life;
2670 struct iaddr tmp_addr;
2674 memset(&ia_data, 0,
sizeof(ia_data));
2675 memset(&data, 0,
sizeof(data));
2676 memset(&iaaddr, 0,
sizeof(iaaddr));
2679 if ((reply->cursor +
IA_TA_OFFSET + 4) >
sizeof(reply->buf)) {
2680 log_error(
"reply_process_ia_ta: Reply too long for IA.");
2681 return ISC_R_NOSPACE;
2686 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2688 log_error(
"reply_process_ia_ta: error evaluating ia");
2689 status = ISC_R_FAILURE;
2697 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
2698 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
2699 log_error(
"reply_process_ia_ta: no memory for ia.");
2700 status = ISC_R_NOMEMORY;
2707 (
unsigned char *)reply->ia->iaid_duid.data,
2708 reply->ia->iaid_duid.len,
MDL);
2715 status = ISC_R_NOMEMORY;
2722 reply->static_lease = ISC_FALSE;
2730 ia_cursor = reply->cursor;
2737 putUShort(reply->buf.data + reply->cursor, 0x04u);
2741 putULong(reply->buf.data + reply->cursor, iaid);
2748 reply->valid = reply->prefer = 0xffffffff;
2749 reply->client_valid = reply->client_prefer = 0;
2751 for (; oc != NULL; oc = oc->
next) {
2752 memset(&iaaddr, 0,
sizeof(iaaddr));
2755 reply->packet->options, NULL,
2759 "evaluating IAADDR.");
2760 status = ISC_R_FAILURE;
2764 pref_life =
getULong(iaaddr.data + 16);
2765 valid_life =
getULong(iaaddr.data + 20);
2767 if ((reply->client_valid == 0) ||
2768 (reply->client_valid > valid_life))
2769 reply->client_valid = valid_life;
2771 if ((reply->client_prefer == 0) ||
2772 (reply->client_prefer > pref_life))
2773 reply->client_prefer = pref_life;
2776 if (status == ISC_R_CANCELED)
2780 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2781 if (!temporary_is_available(reply, &tmp_addr))
2783 status = reply_process_is_addressed(reply,
2784 &reply->lease->scope,
2785 reply->lease->ipv6_pool->ipv6_pond->group);
2786 if (status != ISC_R_SUCCESS)
2788 status = reply_process_send_addr(reply, &tmp_addr);
2789 if (status != ISC_R_SUCCESS)
2791 if (reply->lease != NULL)
2799 status = ISC_R_NOMEMORY;
2802 status = ISC_R_CANCELED;
2803 reply->client_resources = 0;
2804 reply->resources_included = ISC_FALSE;
2805 if (reply->lease != NULL)
2813 if (reply->client_resources != 0)
2815 status = find_client_temporaries(reply);
2816 if (status == ISC_R_NORESOURCES) {
2817 switch (reply->packet->dhcpv6_msg_type) {
2838 "memory for option state wipe.");
2839 status = ISC_R_NOMEMORY;
2844 "No addresses available " 2845 "for this interface.",
2847 log_error(
"reply_process_ia_ta: Unable " 2848 "to set NoAddrsAvail status code.");
2849 status = ISC_R_FAILURE;
2853 status = ISC_R_SUCCESS;
2862 if (reply->resources_included)
2863 status = ISC_R_SUCCESS;
2868 }
else if (status != ISC_R_SUCCESS)
2872 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2873 sizeof(reply->buf) - reply->cursor,
2874 reply->reply_ia, reply->packet,
2875 required_opts_IA, NULL);
2878 putUShort(reply->buf.data + ia_cursor + 2,
2879 reply->cursor - (ia_cursor + 4));
2885 if (status == ISC_R_CANCELED)
2891 if (reply->ia->num_iasubopt != 0) {
2894 char tmp_addr[INET6_ADDRSTRLEN];
2896 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2897 tmp = reply->ia->iasubopt[i];
2899 log_info(
"%s TA: address %s to client with duid %s " 2900 "iaid = %d valid for %d seconds",
2902 inet_ntop(AF_INET6, &tmp->
addr,
2903 tmp_addr,
sizeof(tmp_addr)),
2905 reply->client_id.data, 60),
2919 if ((reply->ia->num_iasubopt != 0) &&
2925 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2926 tmp = reply->ia->iasubopt[i];
2928 if (tmp->
ia != NULL)
2940 reply->packet->options,
2949 #if defined (NSUPDATE) 2958 reply->packet->options,
2963 tmp, NULL, reply->opt_state);
2967 check_pool6_threshold(reply, tmp);
2971 if (reply->old_ia != NULL) {
2972 ia_id = &reply->old_ia->iaid_duid;
2974 (
unsigned char *)ia_id->
data,
2981 ia_id = &reply->ia->iaid_duid;
2983 ia_id->
len, reply->ia,
MDL);
2987 schedule_lease_timeout_reply(reply);
2991 if (packet_ia != NULL)
2993 if (iaaddr.data != NULL)
2995 if (reply->reply_ia != NULL)
2997 if (ia_data.data != NULL)
2999 if (
data.data != NULL)
3001 if (reply->ia != NULL)
3003 if (reply->old_ia != NULL)
3005 if (reply->lease != NULL)
3013 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
3019 static isc_boolean_t
3020 temporary_is_available(
struct reply_state *reply,
struct iaddr *addr) {
3021 struct in6_addr tmp_addr;
3022 struct subnet *subnet;
3027 memcpy(&tmp_addr, addr->
iabuf,
sizeof(tmp_addr));
3033 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
3039 for (subnet = reply->shared->subnets ; subnet != NULL ;
3053 if (address_is_owned(reply, addr))
3059 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3066 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
3082 if (iasubopt_allocate(&reply->lease,
MDL) != ISC_R_SUCCESS)
3084 reply->lease->addr = tmp_addr;
3085 reply->lease->plen = 0;
3097 find_client_temporaries(
struct reply_state *reply) {
3101 isc_result_t status = ISC_R_NORESOURCES;;
3102 unsigned int attempts;
3103 struct iaddr send_addr;
3109 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3113 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3123 log_debug(
"Unable to get client addresses: " 3124 "no IPv6 pools on this shared network");
3125 return ISC_R_NORESOURCES;
3135 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3142 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3151 &reply->client_id,
cur_time + 120);
3152 if (status != ISC_R_SUCCESS) {
3153 log_debug(
"Unable to get a temporary address.");
3157 status = reply_process_is_addressed(reply,
3158 &reply->lease->scope,
3160 if (status != ISC_R_SUCCESS) {
3164 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3165 status = reply_process_send_addr(reply, &send_addr);
3166 if (status != ISC_R_SUCCESS) {
3178 if (reply->lease != NULL) {
3189 reply_process_try_addr(
struct reply_state *reply,
struct iaddr *addr) {
3190 isc_result_t status = ISC_R_ADDRNOTAVAIL;
3196 if ((reply == NULL) || (reply->shared == NULL) ||
3197 (addr == NULL) || (reply->lease != NULL))
3204 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3208 for (i = 0; ; i++) {
3210 if ((pool == NULL) ||
3220 return (ISC_R_ADDRNOTAVAIL);
3223 memset(&data_addr, 0,
sizeof(data_addr));
3224 data_addr.len = addr->
len;
3225 data_addr.data = addr->
iabuf;
3238 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3245 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
3249 status = try_client_v6_address(&reply->lease, pool,
3251 if (status == ISC_R_SUCCESS)
3255 if (status == ISC_R_SUCCESS)
3270 find_client_address(
struct reply_state *reply) {
3271 struct iaddr send_addr;
3272 isc_result_t status = ISC_R_NORESOURCES;
3273 struct iasubopt *lease, *best_lease = NULL;
3275 struct group *group;
3278 if (reply->static_lease) {
3279 if (reply->host == NULL)
3283 memcpy(send_addr.iabuf, reply->fixed.data, 16);
3286 group = reply->subnet->group;
3290 if (reply->old_ia != NULL) {
3291 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
3295 lease = reply->old_ia->iasubopt[i];
3304 if ((candidate_shared != reply->shared) ||
3314 best_lease = lease_compare(lease, best_lease);
3322 status = pick_v6_address(reply);
3323 }
else if (best_lease != NULL) {
3325 status = ISC_R_SUCCESS;
3329 if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
3331 log_error(
"Best match for DUID %s is an abandoned address," 3332 " This may be a result of multiple clients attempting" 3333 " to use this DUID",
3335 reply->client_id.data, 60));
3340 if (status != ISC_R_SUCCESS)
3343 if (reply->lease == NULL)
3350 scope = &reply->lease->scope;
3351 group = reply->lease->ipv6_pool->ipv6_pond->group;
3354 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3357 status = reply_process_is_addressed(reply, scope, group);
3358 if (status != ISC_R_SUCCESS)
3361 status = reply_process_send_addr(reply, &send_addr);
3370 reply_process_is_addressed(
struct reply_state *reply,
3373 isc_result_t status = ISC_R_SUCCESS;
3381 memset(&data, 0,
sizeof(data));
3390 on_star = &reply->lease->on_star;
3392 on_star = &reply->on_star;
3402 reply->packet->options, tmp_options,
3405 if (tmp_options != NULL) {
3415 reply->packet->options, reply->opt_state,
3419 for (i = reply->packet->class_count; i > 0; i--) {
3421 reply->packet->options,
3422 reply->opt_state, scope,
3423 reply->packet->classes[i - 1]->group,
3432 if (reply->host != NULL)
3434 reply->packet->options,
3435 reply->opt_state, scope,
3436 reply->host->group, group,
3440 if (reply->client_valid == 0)
3443 reply->send_valid = reply->client_valid;
3449 reply->packet->options,
3453 log_error(
"reply_process_is_addressed: unable to " 3454 "evaluate default lease time");
3455 status = ISC_R_FAILURE;
3459 reply->send_valid =
getULong(data.data);
3463 if (reply->client_prefer == 0)
3464 reply->send_prefer = reply->send_valid;
3466 reply->send_prefer = reply->client_prefer;
3468 if (reply->send_prefer >= reply->send_valid)
3469 reply->send_prefer = (reply->send_valid / 2) +
3470 (reply->send_valid / 8);
3476 reply->packet->options,
3480 log_error(
"reply_process_is_addressed: unable to " 3481 "evaluate preferred lease time");
3482 status = ISC_R_FAILURE;
3486 reply->send_prefer =
getULong(data.data);
3491 if (reply->prefer > reply->send_prefer)
3492 reply->prefer = reply->send_prefer;
3494 if (reply->valid > reply->send_valid)
3495 reply->valid = reply->send_valid;
3507 if (reply->host != NULL)
3509 reply->client_id->len);
3513 if (reply->lease != NULL) {
3515 reply->lease->prefer = reply->send_prefer;
3516 reply->lease->valid = reply->send_valid;
3520 reply->lease->soft_lifetime_end_time =
3526 if (status != ISC_R_SUCCESS) {
3527 log_fatal(
"reply_process_is_addressed: Unable to " 3528 "attach lease to new IA: %s",
3529 isc_result_totext(status));
3535 if (reply->lease->ia == NULL) {
3542 reply->packet->options, reply->reply_ia,
3546 for (i = reply->packet->class_count; i > 0; i--) {
3548 reply->packet->options,
3549 reply->reply_ia, scope,
3550 reply->packet->classes[i - 1]->group,
3558 if (reply->host != NULL)
3560 reply->packet->options,
3561 reply->reply_ia, scope,
3562 reply->host->group, group, NULL);
3565 if (data.data != NULL)
3568 if (status == ISC_R_SUCCESS)
3569 reply->client_resources++;
3576 reply_process_send_addr(
struct reply_state *reply,
struct iaddr *addr) {
3577 isc_result_t status = ISC_R_SUCCESS;
3585 log_error(
"reply_process_send_addr: out of memory" 3586 "allocating new IAADDR buffer.");
3587 status = ISC_R_NOMEMORY;
3592 memcpy(
data.buffer->data, addr->
iabuf, 16);
3599 log_error(
"reply_process_send_addr: unable " 3600 "to save IAADDR option");
3601 status = ISC_R_FAILURE;
3605 reply->resources_included = ISC_TRUE;
3608 if (
data.data != NULL)
3622 switch(alpha->
state) {
3624 switch(beta->
state) {
3645 switch (beta->
state) {
3671 switch (beta->
state) {
3693 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
3701 reply_process_ia_pd(
struct reply_state *reply,
struct option_cache *ia) {
3702 isc_result_t status = ISC_R_SUCCESS;
3711 memset(&ia_data, 0,
sizeof(ia_data));
3718 if ((reply->cursor +
IA_PD_OFFSET + 4) >
sizeof(reply->buf)) {
3719 log_error(
"reply_process_ia_pd: Reply too long for IA.");
3720 return ISC_R_NOSPACE;
3725 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
3727 log_error(
"reply_process_ia_pd: error evaluating ia");
3728 status = ISC_R_FAILURE;
3734 reply->renew =
getULong(ia_data.data + 4);
3735 reply->rebind =
getULong(ia_data.data + 8);
3738 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
3739 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
3740 log_error(
"reply_process_ia_pd: no memory for ia.");
3741 status = ISC_R_NOMEMORY;
3748 (
unsigned char *)reply->ia->iaid_duid.data,
3749 reply->ia->iaid_duid.len,
MDL);
3756 status = ISC_R_NOMEMORY;
3761 reply->static_prefixes = 0;
3762 if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
3765 for (fp = reply->host->fixed_prefix; fp != NULL;
3767 reply->static_prefixes += 1;
3777 ia_cursor = reply->cursor;
3784 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
3788 putULong(reply->buf.data + reply->cursor, iaid);
3792 putULong(reply->buf.data + reply->cursor, reply->renew);
3796 putULong(reply->buf.data + reply->cursor, reply->rebind);
3803 reply->valid = reply->prefer = 0xffffffff;
3804 reply->client_valid = reply->client_prefer = 0;
3805 reply->preflen = -1;
3806 for (; oc != NULL ; oc = oc->
next) {
3807 status = reply_process_prefix(reply, oc);
3815 if (status == ISC_R_CANCELED)
3818 if ((status != ISC_R_SUCCESS) &&
3819 (status != ISC_R_ADDRINUSE) &&
3820 (status != ISC_R_ADDRNOTAVAIL))
3830 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
3831 status = find_client_prefix(reply);
3833 if (status == ISC_R_NORESOURCES) {
3834 switch (reply->packet->dhcpv6_msg_type) {
3849 "memory for option state " 3851 status = ISC_R_NOMEMORY;
3856 "No prefixes available " 3857 "for this interface.",
3861 "NoPrefixAvail status " 3863 status = ISC_R_FAILURE;
3867 status = ISC_R_SUCCESS;
3871 if (reply->resources_included)
3872 status = ISC_R_SUCCESS;
3879 if (status != ISC_R_SUCCESS)
3883 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
3884 sizeof(reply->buf) - reply->cursor,
3885 reply->reply_ia, reply->packet,
3886 required_opts_IA_PD, NULL);
3889 putUShort(reply->buf.data + ia_cursor + 2,
3890 reply->cursor - (ia_cursor + 4));
3903 reply->packet->options,
3909 reply->renew =
getULong(data.data);
3912 if (data.data != NULL)
3915 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
3923 reply->packet->options,
3929 reply->rebind =
getULong(data.data);
3932 if (data.data != NULL)
3935 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
3941 if (status == ISC_R_CANCELED)
3948 if (reply->static_prefixes != 0) {
3949 char tmp_addr[INET6_ADDRSTRLEN];
3950 log_info(
"%s PD: address %s/%d to client with duid %s " 3953 inet_ntop(AF_INET6, reply->fixed_pref.lo_addr.iabuf,
3954 tmp_addr,
sizeof(tmp_addr)),
3955 reply->fixed_pref.bits,
3957 reply->client_id.data, 60),
3960 (reply->on_star.on_commit != NULL)) {
3962 reply->packet->options,
3964 NULL, reply->on_star.on_commit,
3967 (&reply->on_star.on_commit,
MDL);
3975 if (reply->ia->num_iasubopt != 0) {
3978 char tmp_addr[INET6_ADDRSTRLEN];
3980 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3981 tmp = reply->ia->iasubopt[i];
3983 log_info(
"%s PD: address %s/%d to client with duid %s" 3984 " iaid = %d valid for %d seconds",
3986 inet_ntop(AF_INET6, &tmp->
addr,
3987 tmp_addr,
sizeof(tmp_addr)),
3990 reply->client_id.data, 60),
4004 (reply->ia->num_iasubopt != 0)) {
4009 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
4010 tmp = reply->ia->iasubopt[i];
4012 if (tmp->
ia != NULL)
4024 reply->packet->options,
4034 check_pool6_threshold(reply, tmp);
4038 if (reply->old_ia != NULL) {
4039 ia_id = &reply->old_ia->iaid_duid;
4041 (
unsigned char *)ia_id->
data,
4048 ia_id = &reply->ia->iaid_duid;
4050 ia_id->
len, reply->ia,
MDL);
4054 schedule_lease_timeout_reply(reply);
4058 if (packet_ia != NULL)
4060 if (reply->reply_ia != NULL)
4062 if (ia_data.data != NULL)
4064 if (
data.data != NULL)
4066 if (reply->ia != NULL)
4068 if (reply->old_ia != NULL)
4070 if (reply->lease != NULL)
4072 if (reply->on_star.on_expiry != NULL)
4074 (&reply->on_star.on_expiry,
MDL);
4075 if (reply->on_star.on_release != NULL)
4077 (&reply->on_star.on_release,
MDL);
4084 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
4106 static struct group *
4107 find_group_by_prefix(
struct reply_state *reply) {
4109 struct group *group = reply->shared->group;
4110 struct subnet *subnet = NULL;
4111 struct iaddr tmp_addr;
4116 reply->fixed_pref.lo_addr,
MDL) != 0) {
4117 group = subnet->
group;
4118 subnet_dereference(&subnet,
MDL);
4125 memset(&fixed_addr, 0,
sizeof(fixed_addr));
4127 if ((reply->host->fixed_addr != NULL) &&
4130 reply->host->fixed_addr,
MDL))) {
4131 if (fixed_addr.len >= 16) {
4133 memcpy(tmp_addr.iabuf, fixed_addr.data, 16);
4135 tmp_addr,
MDL) != 0) {
4136 group = subnet->
group;
4137 subnet_dereference(&subnet,
MDL);
4154 reply_process_prefix(
struct reply_state *reply,
struct option_cache *pref) {
4155 u_int32_t pref_life, valid_life;
4160 isc_result_t status = ISC_R_SUCCESS;
4161 struct group *group;
4164 memset(&iapref, 0,
sizeof(iapref));
4165 memset(&data, 0,
sizeof(data));
4172 if ((reply->cursor + 29) >
sizeof(reply->buf)) {
4173 log_error(
"reply_process_prefix: Out of room for prefix.");
4174 return ISC_R_NOSPACE;
4182 log_error(
"reply_process_prefix: error evaluating IAPREFIX.");
4183 status = ISC_R_FAILURE;
4192 valid_life =
getULong(iapref.data + 4);
4194 if ((reply->client_valid == 0) ||
4195 (reply->client_valid > valid_life))
4196 reply->client_valid = valid_life;
4198 if ((reply->client_prefer == 0) ||
4199 (reply->client_prefer > pref_life))
4200 reply->client_prefer = pref_life;
4206 tmp_pref.lo_addr.len = 16;
4207 memset(tmp_pref.lo_addr.iabuf, 0, 16);
4208 if ((iapref.data[8] == 0) &&
4209 (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
4218 tmp_pref.bits = (
int) iapref.data[8];
4219 if (reply->preflen < 0) {
4221 reply->preflen = tmp_pref.bits;
4223 if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
4227 memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
4230 if (!prefix_is_owned(reply, &tmp_pref)) {
4235 status = reply_process_try_prefix(reply, &tmp_pref);
4238 if ((status != ISC_R_SUCCESS) &&
4239 (status != ISC_R_ADDRINUSE) &&
4240 (status != ISC_R_ADDRNOTAVAIL))
4243 if (reply->lease == NULL) {
4244 if (reply->packet->dhcpv6_msg_type ==
4246 reply->send_prefer = 0;
4247 reply->send_valid = 0;
4266 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
4270 log_error(
"reply_process_prefix: No memory " 4271 "for option state wipe.");
4272 status = ISC_R_NOMEMORY;
4278 "Prefix not bound to this " 4279 "interface.", reply->reply_ia)) {
4280 log_error(
"reply_process_prefix: Unable to " 4281 "attach status code.");
4282 status = ISC_R_FAILURE;
4287 status = ISC_R_CANCELED;
4290 log_error(
"It is impossible to lease a client that is " 4291 "not sending a solicit, request, renew, or " 4293 status = ISC_R_FAILURE;
4298 if (reply->static_prefixes > 0) {
4299 if (reply->host == NULL)
4305 memcpy(&reply->fixed_pref, &tmp_pref,
sizeof(tmp_pref));
4308 group = find_group_by_prefix(reply);
4310 if (reply->lease == NULL)
4313 scope = &reply->lease->scope;
4314 group = reply->lease->ipv6_pool->ipv6_pond->group;
4323 if (reply->client_resources != 0) {
4336 reply->packet->options,
4340 log_error(
"reply_process_prefix: unable to " 4341 "evaluate prefs-per-ia value.");
4342 status = ISC_R_FAILURE;
4354 if (reply->client_resources >= limit)
4358 status = reply_process_is_prefixed(reply, scope, group);
4359 if (status != ISC_R_SUCCESS)
4363 status = reply_process_send_prefix(reply, &tmp_pref);
4366 if (iapref.data != NULL)
4368 if (data.data != NULL)
4370 if (reply->lease != NULL)
4382 static isc_boolean_t
4383 prefix_is_owned(
struct reply_state *reply,
struct iaddrcidrnet *pref) {
4391 if (reply->static_prefixes > 0) {
4392 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4401 if ((reply->old_ia == NULL) ||
4402 (reply->old_ia->num_iasubopt == 0))
4405 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4408 tmp = reply->old_ia->iasubopt[i];
4410 if ((pref->
bits == (
int) tmp->
plen) &&
4436 reply_process_try_prefix(
struct reply_state *reply,
4438 isc_result_t status = ISC_R_ADDRNOTAVAIL;
4444 if ((reply == NULL) || (reply->shared == NULL) ||
4445 (pref == NULL) || (reply->lease != NULL))
4452 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4456 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4466 return (ISC_R_ADDRNOTAVAIL);
4469 memset(&data_pref, 0,
sizeof(data_pref));
4472 log_error(
"reply_process_try_prefix: out of memory.");
4473 return (ISC_R_NOMEMORY);
4475 data_pref.data = data_pref.buffer->data;
4476 data_pref.buffer->data[0] = (u_int8_t) pref->
bits;
4477 memcpy(data_pref.buffer->data + 1, pref->
lo_addr.
iabuf, 16);
4487 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4494 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4499 status = try_client_v6_prefix(&reply->lease, pool,
4503 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4506 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4520 find_client_prefix(
struct reply_state *reply) {
4522 isc_result_t status = ISC_R_NORESOURCES;
4523 struct iasubopt *prefix, *best_prefix = NULL;
4526 struct group *group;
4528 if (reply->static_prefixes > 0) {
4531 if (reply->host == NULL)
4534 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4543 l = reply->host->fixed_prefix;
4545 memcpy(&send_pref, &l->
cidrnet,
sizeof(send_pref));
4550 memcpy(&reply->fixed_pref, &l->
cidrnet,
sizeof(send_pref));
4553 group = find_group_by_prefix(reply);
4558 if (reply->old_ia != NULL) {
4559 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4563 prefix = reply->old_ia->iasubopt[i];
4572 if (((candidate_shared != NULL) &&
4573 (candidate_shared != reply->shared)) ||
4587 best_prefix = prefix_compare(reply, prefix,
4596 status = pick_v6_prefix(reply);
4597 }
else if (best_prefix != NULL) {
4599 status = ISC_R_SUCCESS;
4603 if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
4605 log_error(
"Reclaiming abandoned prefixes is not yet " 4606 "supported. Treating this as an out of space " 4612 if (status != ISC_R_SUCCESS)
4615 if (reply->lease == NULL)
4618 scope = &reply->lease->scope;
4619 group = reply->lease->ipv6_pool->ipv6_pond->group;
4621 send_pref.lo_addr.len = 16;
4622 memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
4623 send_pref.bits = (
int) reply->lease->plen;
4626 status = reply_process_is_prefixed(reply, scope, group);
4627 if (status != ISC_R_SUCCESS)
4630 status = reply_process_send_prefix(reply, &send_pref);
4639 reply_process_is_prefixed(
struct reply_state *reply,
4642 isc_result_t status = ISC_R_SUCCESS;
4646 struct on_star *on_star;
4650 memset(&data, 0,
sizeof(data));
4659 on_star = &reply->lease->on_star;
4661 on_star = &reply->on_star;
4671 reply->packet->options, tmp_options,
4674 if (tmp_options != NULL) {
4684 reply->packet->options, reply->opt_state,
4688 for (i = reply->packet->class_count; i > 0; i--) {
4690 reply->packet->options,
4691 reply->opt_state, scope,
4692 reply->packet->classes[i - 1]->group,
4701 if (reply->host != NULL)
4703 reply->packet->options,
4704 reply->opt_state, scope,
4705 reply->host->group, group,
4709 if (reply->client_valid == 0)
4712 reply->send_valid = reply->client_valid;
4718 reply->packet->options,
4722 log_error(
"reply_process_is_prefixed: unable to " 4723 "evaluate default prefix time");
4724 status = ISC_R_FAILURE;
4728 reply->send_valid =
getULong(data.data);
4732 if (reply->client_prefer == 0)
4733 reply->send_prefer = reply->send_valid;
4735 reply->send_prefer = reply->client_prefer;
4737 if (reply->send_prefer >= reply->send_valid)
4738 reply->send_prefer = (reply->send_valid / 2) +
4739 (reply->send_valid / 8);
4745 reply->packet->options,
4749 log_error(
"reply_process_is_prefixed: unable to " 4750 "evaluate preferred prefix time");
4751 status = ISC_R_FAILURE;
4755 reply->send_prefer =
getULong(data.data);
4760 if (reply->prefer > reply->send_prefer)
4761 reply->prefer = reply->send_prefer;
4763 if (reply->valid > reply->send_valid)
4764 reply->valid = reply->send_valid;
4767 if (reply->lease != NULL) {
4769 reply->lease->prefer = reply->send_prefer;
4770 reply->lease->valid = reply->send_valid;
4774 reply->lease->soft_lifetime_end_time =
4780 if (status != ISC_R_SUCCESS) {
4781 log_fatal(
"reply_process_is_prefixed: Unable to " 4782 "attach prefix to new IA_PD: %s",
4783 isc_result_totext(status));
4789 if (reply->lease->ia == NULL) {
4796 reply->packet->options, reply->reply_ia,
4800 for (i = reply->packet->class_count; i > 0; i--) {
4802 reply->packet->options,
4803 reply->reply_ia, scope,
4804 reply->packet->classes[i - 1]->group,
4812 if (reply->host != NULL)
4814 reply->packet->options,
4815 reply->reply_ia, scope,
4816 reply->host->group, group, NULL);
4819 if (data.data != NULL)
4822 if (status == ISC_R_SUCCESS)
4823 reply->client_resources++;
4830 reply_process_send_prefix(
struct reply_state *reply,
4832 isc_result_t status = ISC_R_SUCCESS;
4840 log_error(
"reply_process_send_prefix: out of memory" 4841 "allocating new IAPREFIX buffer.");
4842 status = ISC_R_NOMEMORY;
4855 log_error(
"reply_process_send_prefix: unable " 4856 "to save IAPREFIX option");
4857 status = ISC_R_FAILURE;
4861 reply->resources_included = ISC_TRUE;
4864 if (
data.data != NULL)
4872 prefix_compare(
struct reply_state *reply,
4879 if (reply->preflen >= 0) {
4880 if ((alpha->
plen == reply->preflen) &&
4881 (beta->
plen != reply->preflen))
4883 if ((beta->
plen == reply->preflen) &&
4884 (alpha->
plen != reply->preflen))
4888 switch(alpha->
state) {
4890 switch(beta->
state) {
4911 switch (beta->
state) {
4937 switch (beta->
state) {
4959 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
4973 dhcpv6_solicit(
struct data_string *reply_ret,
struct packet *packet) {
4981 if (!valid_client_msg(packet, &client_id)) {
4985 lease_to_client(reply_ret, packet, &client_id, NULL);
5002 dhcpv6_request(
struct data_string *reply_ret,
struct packet *packet) {
5011 if (!valid_client_resp(packet, &client_id, &server_id)) {
5017 if (packet->
unicast == ISC_TRUE &&
5018 is_unicast_option_defined(packet) == ISC_FALSE) {
5019 unicast_reject(reply_ret, packet, &client_id, &server_id);
5024 lease_to_client(reply_ret, packet, &client_id, &server_id);
5040 struct packet *packet)
5042 const struct packet *chk_packet;
5043 const struct in6_addr *link_addr, *first_link_addr;
5044 struct iaddr tmp_addr;
5045 struct subnet *subnet;
5046 isc_result_t status;
5048 if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
5055 first_link_addr = NULL;
5057 while (chk_packet != NULL) {
5059 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
5060 !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
5061 first_link_addr = link_addr;
5072 if (first_link_addr != NULL) {
5073 tmp_addr.len =
sizeof(*first_link_addr);
5074 memcpy(tmp_addr.iabuf,
5075 first_link_addr,
sizeof(*first_link_addr));
5078 log_debug(
"No subnet found for link-address %s.",
5080 return ISC_R_NOTFOUND;
5082 status = shared_network_reference(shared,
5084 subnet_dereference(&subnet,
MDL);
5091 status = shared_network_reference(shared,
5095 log_info(
"[L2 Relay] No link address in relay packet " 5096 "assuming L2 relay and using receiving " 5106 log_error(
"No interface and no link address " 5107 "can't determine pool");
5133 dhcpv6_confirm(
struct data_string *reply_ret,
struct packet *packet) {
5135 struct subnet *subnet;
5137 struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
5139 struct iaddr cli_addr;
5141 isc_boolean_t inappropriate, has_addrs;
5142 char reply_data[65536];
5151 memset(&client_id, 0,
sizeof(client_id));
5152 if (!valid_client_msg(packet, &client_id)) {
5161 if ((ia == NULL) && (ta == NULL))
5172 opt_state = cli_enc_opt_state = NULL;
5173 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5174 memset(&iaaddr, 0,
sizeof(iaaddr));
5175 memset(&packet_oro, 0,
sizeof(packet_oro));
5182 if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
5194 has_addrs = inappropriate = ISC_FALSE;
5196 while(!inappropriate) {
5200 if ((pass ==
D6O_IA_NA) && (ia == NULL)) {
5210 !get_encapsulated_IA_state(&cli_enc_opt_state,
5214 !get_encapsulated_IA_state(&cli_enc_opt_state,
5223 for ( ; oc != NULL ; oc = oc->
next) {
5229 "error evaluating IAADDR.");
5235 memcpy(cli_addr.iabuf, iaaddr.data, 16);
5240 has_addrs = ISC_TRUE;
5243 for (subnet = shared->
subnets ; subnet != NULL ;
5258 if (subnet == NULL) {
5259 inappropriate = ISC_TRUE;
5278 if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
5285 if (inappropriate) {
5287 "Some of the addresses are not on link.",
5293 "All addresses still on link.",
5303 sizeof(reply_data)-reply_ofs,
5305 required_opts, &packet_oro);
5310 reply_ret->
len = reply_ofs;
5311 reply_ret->
buffer = NULL;
5316 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5320 if (cli_enc_opt_data.buffer != NULL)
5322 if (iaaddr.buffer != NULL)
5324 if (client_id.
buffer != NULL)
5326 if (packet_oro.buffer != NULL)
5330 if (cli_enc_opt_state != NULL)
5332 if (opt_state != NULL)
5346 dhcpv6_renew(
struct data_string *reply,
struct packet *packet) {
5355 if (!valid_client_resp(packet, &client_id, &server_id)) {
5361 if (packet->
unicast == ISC_TRUE &&
5362 is_unicast_option_defined(packet) == ISC_FALSE) {
5363 unicast_reject(reply, packet, &client_id, &server_id);
5368 lease_to_client(reply, packet, &client_id, &server_id);
5388 dhcpv6_rebind(
struct data_string *reply,
struct packet *packet) {
5393 if (!valid_client_msg(packet, &client_id)) {
5397 lease_to_client(reply, packet, &client_id, NULL);
5405 ia_na_match_decline(
const struct data_string *client_id,
5409 char tmp_addr[INET6_ADDRSTRLEN];
5411 log_error(
"Client %s reports address %s is " 5412 "already in use by another host!",
5414 inet_ntop(AF_INET6, iaaddr->
data,
5415 tmp_addr,
sizeof(tmp_addr)));
5416 if (lease != NULL) {
5424 ia_na_nomatch_decline(
const struct data_string *client_id,
5426 u_int32_t *ia_na_id,
5427 struct packet *packet,
5432 char tmp_addr[INET6_ADDRSTRLEN];
5436 log_info(
"Client %s declines address %s, which is not offered to it.",
5438 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5443 host_opt_state = NULL;
5445 log_error(
"ia_na_nomatch_decline: out of memory " 5446 "allocating option_state.");
5458 if (reply_len < (*reply_ofs + 16)) {
5460 "out of space for reply packet.");
5468 reply_len-(*reply_ofs)-16,
5469 host_opt_state, packet,
5470 required_opts_STATUS_CODE, NULL);
5480 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5482 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5484 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5485 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5490 *reply_ofs += (len + 16);
5498 struct packet *packet,
5501 const char *packet_type,
5502 void (*ia_na_match)(),
5503 void (*ia_na_nomatch)())
5516 char reply_data[65536];
5519 char status_msg[32];
5521 struct ia_xx *existing_ia_na;
5530 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5531 cli_enc_opt_state = NULL;
5532 memset(&iaaddr, 0,
sizeof(iaaddr));
5533 memset(&fixed_addr, 0,
sizeof(fixed_addr));
5534 host_opt_state = NULL;
5554 if (!find_hosts_by_duid_chaddr(&packet_host,
5572 log_error(
"iterate_over_ia_na: no memory for option_state.");
5585 (
unsigned char *)server_duid.data,
5588 "error saving server identifier.");
5595 (
unsigned char *)client_id->
data,
5599 "error saving client identifier.");
5603 snprintf(status_msg,
sizeof(status_msg),
"%s received.", packet_type);
5612 sizeof(reply_data)-reply_ofs,
5614 required_opts, NULL);
5621 ia != NULL; ia = ia->
next) {
5623 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5629 iaid =
getULong(cli_enc_opt_data.data);
5647 memset(&iaaddr, 0,
sizeof(iaaddr));
5652 "error evaluating IAADDR.");
5666 cli_enc_opt_state,
MDL)) {
5667 if (packet_host != NULL) {
5673 while (host != NULL) {
5681 "evaluating host address.");
5684 if ((iaaddr.
len >= 16) &&
5685 !memcmp(fixed_addr.data, iaaddr.
data, 16)) {
5699 (
char *)client_id->
data,
5701 MDL) != ISC_R_SUCCESS) {
5702 log_fatal(
"iterate_over_ia_na: no memory for " 5706 existing_ia_na = NULL;
5708 (
unsigned char *)key.data,
5715 struct in6_addr *in6_addr;
5718 in6_addr = &tmp->
addr;
5719 if (memcmp(in6_addr,
5720 iaaddr.
data, 16) == 0) {
5731 if ((host != NULL) || (lease != NULL)) {
5732 ia_na_match(client_id, &iaaddr, lease);
5734 ia_na_nomatch(client_id, &iaaddr,
5735 (u_int32_t *)cli_enc_opt_data.
data,
5736 packet, reply_data, &reply_ofs,
5737 sizeof(reply_data));
5740 if (lease != NULL) {
5752 reply_ret->
len = reply_ofs;
5753 reply_ret->
buffer = NULL;
5758 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5761 if (lease != NULL) {
5764 if (host_opt_state != NULL) {
5767 if (fixed_addr.buffer != NULL) {
5770 if (iaaddr.
buffer != NULL) {
5773 if (cli_enc_opt_state != NULL) {
5776 if (cli_enc_opt_data.buffer != NULL) {
5779 if (opt_state != NULL) {
5799 dhcpv6_decline(
struct data_string *reply,
struct packet *packet) {
5808 if (!valid_client_resp(packet, &client_id, &server_id)) {
5814 if (packet->
unicast == ISC_TRUE &&
5815 is_unicast_option_defined(packet) == ISC_FALSE) {
5816 unicast_reject(reply, packet, &client_id, &server_id);
5826 iterate_over_ia_na(reply, packet, &client_id, &server_id,
5827 "Decline", ia_na_match_decline,
5828 ia_na_nomatch_decline);
5839 ia_na_match_release(
const struct data_string *client_id,
5843 char tmp_addr[INET6_ADDRSTRLEN];
5845 log_info(
"Client %s releases address %s",
5847 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5848 if (lease != NULL) {
5856 ia_na_nomatch_release(
const struct data_string *client_id,
5858 u_int32_t *ia_na_id,
5859 struct packet *packet,
5864 char tmp_addr[INET6_ADDRSTRLEN];
5868 log_info(
"Client %s releases address %s, which is not leased to it.",
5870 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5875 host_opt_state = NULL;
5877 log_error(
"ia_na_nomatch_release: out of memory " 5878 "allocating option_state.");
5883 "Release for non-leased address.",
5891 if (reply_len < (*reply_ofs + 16)) {
5893 "out of space for reply packet.");
5901 reply_len-(*reply_ofs)-16,
5902 host_opt_state, packet,
5903 required_opts_STATUS_CODE, NULL);
5913 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5915 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5917 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5918 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5923 *reply_ofs += (len + 16);
5930 ia_pd_match_release(
const struct data_string *client_id,
5934 char tmp_addr[INET6_ADDRSTRLEN];
5936 log_info(
"Client %s releases prefix %s/%u",
5938 inet_ntop(AF_INET6, iapref->
data + 9,
5939 tmp_addr,
sizeof(tmp_addr)),
5941 if (prefix != NULL) {
5949 ia_pd_nomatch_release(
const struct data_string *client_id,
5951 u_int32_t *ia_pd_id,
5952 struct packet *packet,
5957 char tmp_addr[INET6_ADDRSTRLEN];
5961 log_info(
"Client %s releases prefix %s/%u, which is not leased to it.",
5963 inet_ntop(AF_INET6, iapref->
data + 9,
5964 tmp_addr,
sizeof(tmp_addr)),
5970 host_opt_state = NULL;
5972 log_error(
"ia_pd_nomatch_release: out of memory " 5973 "allocating option_state.");
5978 "Release for non-leased prefix.",
5986 if (reply_len < (*reply_ofs + 16)) {
5988 "out of space for reply packet.");
5996 reply_len-(*reply_ofs)-16,
5997 host_opt_state, packet,
5998 required_opts_STATUS_CODE, NULL);
6008 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
6010 memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
6012 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
6013 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
6018 *reply_ofs += (len + 16);
6026 struct packet *packet,
6029 const char *packet_type,
6030 void (*ia_pd_match)(),
6031 void (*ia_pd_nomatch)())
6045 char reply_data[65536];
6048 struct ia_xx *existing_ia_pd;
6056 memset(&reply_new, 0,
sizeof(reply_new));
6058 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
6059 cli_enc_opt_state = NULL;
6060 memset(&iaprefix, 0,
sizeof(iaprefix));
6061 host_opt_state = NULL;
6067 reply_len =
sizeof(reply_data) - reply_ret->
len;
6087 if (!find_hosts_by_duid_chaddr(&packet_host,
6098 log_error(
"iterate_over_ia_pd: no memory for option_state.");
6110 ia != NULL; ia = ia->
next) {
6112 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
6118 iaid =
getULong(cli_enc_opt_data.data);
6129 for (; oc != NULL; oc = oc->
next) {
6130 memset(&iaprefix, 0,
sizeof(iaprefix));
6135 "error evaluating IAPREFIX.");
6149 cli_enc_opt_state,
MDL)) {
6150 if (packet_host != NULL) {
6156 while (host != NULL) {
6165 if (memcmp(iaprefix.data + 9,
6170 if ((l != NULL) && (iaprefix.len >= 17))
6181 (
char *)client_id->
data,
6183 MDL) != ISC_R_SUCCESS) {
6184 log_fatal(
"iterate_over_ia_pd: no memory for " 6188 existing_ia_pd = NULL;
6190 (
unsigned char *)key.data,
6201 plen =
getUChar(iaprefix.data + 8);
6203 if ((tmp->
plen == plen) &&
6217 if ((host != NULL) || (prefix != NULL)) {
6218 ia_pd_match(client_id, &iaprefix, prefix);
6220 ia_pd_nomatch(client_id, &iaprefix,
6221 (u_int32_t *)cli_enc_opt_data.
data,
6222 packet, reply_data, &reply_ofs,
6223 reply_len - reply_ofs);
6226 if (prefix != NULL) {
6241 reply_new.len = reply_ret->
len + reply_ofs;
6245 reply_new.data = reply_new.buffer->data;
6246 memcpy(reply_new.buffer->data,
6248 memcpy(reply_new.buffer->data + reply_ret->
len,
6249 reply_data, reply_ofs);
6255 if (prefix != NULL) {
6258 if (host_opt_state != NULL) {
6261 if (iaprefix.buffer != NULL) {
6264 if (cli_enc_opt_state != NULL) {
6267 if (cli_enc_opt_data.buffer != NULL) {
6270 if (opt_state != NULL) {
6280 dhcpv6_release(
struct data_string *reply,
struct packet *packet) {
6289 if (!valid_client_resp(packet, &client_id, &server_id)) {
6295 if (packet->
unicast == ISC_TRUE &&
6296 is_unicast_option_defined(packet) == ISC_FALSE) {
6297 unicast_reject(reply, packet, &client_id, &server_id);
6302 iterate_over_ia_na(reply, packet, &client_id, &server_id,
6303 "Release", ia_na_match_release,
6304 ia_na_nomatch_release);
6309 iterate_over_ia_pd(reply, packet, &client_id, &server_id,
6310 "Release", ia_pd_match_release,
6311 ia_pd_nomatch_release);
6326 dhcpv6_information_request(
struct data_string *reply,
struct packet *packet) {
6335 if (!valid_client_info_req(packet, &server_id)) {
6342 memset(&client_id, 0,
sizeof(client_id));
6353 lease_to_client(reply, packet, &client_id,
6354 server_id.
data != NULL ? &server_id : NULL);
6359 if (client_id.
data != NULL) {
6377 dhcpv6_relay_forw(
struct data_string *reply_ret,
struct packet *packet) {
6380 struct packet *enc_packet;
6381 unsigned char msg_type;
6385 char link_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6386 char peer_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6389 static char reply_data[65536];
6399 memset(&a_opt, 0,
sizeof(a_opt));
6400 memset(&packet_ero, 0,
sizeof(packet_ero));
6401 memset(&enc_reply, 0,
sizeof(enc_reply));
6402 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6411 link_addr,
sizeof(link_addr));
6413 peer_addr,
sizeof(peer_addr));
6414 log_info(
"Relay-forward from %s with link address=%s and " 6415 "peer address=%s missing Relay Message option.",
6422 log_error(
"dhcpv6_forw_relay: error evaluating " 6423 "relayed message.");
6428 log_error(
"dhcpv6_forw_relay: encapsulated packet too short.");
6438 "no memory for encapsulated packet.");
6444 "no memory for encapsulated packet's options.");
6453 msg_type = enc_opt_data.
data[0];
6469 enc_opt_data.
len - relaylen,
6487 enc_opt_data.
len - msglen,
6499 build_dhcpv6_reply(&enc_reply, enc_packet);
6505 if (enc_reply.data == NULL) {
6527 log_error(
"dhcpv6_relay_forw: no memory for option state.");
6541 log_error(
"dhcpv6_relay_forw: error evaluating " 6546 (
unsigned char *)a_opt.data,
6549 log_error(
"dhcpv6_relay_forw: error saving " 6560 (
unsigned char *)enc_reply.data,
6563 log_error(
"dhcpv6_relay_forw: error saving Relay MSG.");
6579 (packet_ero.len & 1)) {
6580 log_error(
"dhcpv6_relay_forw: error evaluating ERO.");
6585 for (i = 0; i < packet_ero.len; i += 2) {
6602 "evaluating option %u.", req);
6608 (
unsigned char *)a_opt.data,
6612 log_error(
"dhcpv6_relay_forw: error saving " 6621 sizeof(reply_data) - reply_ofs,
6623 required_opts_agent, &packet_ero);
6628 reply_ret->
len = reply_ofs;
6629 reply_ret->
buffer = NULL;
6634 memcpy(reply_ret->
buffer->
data, reply_data, reply_ofs);
6637 if (opt_state != NULL)
6639 if (a_opt.data != NULL) {
6642 if (packet_ero.data != NULL) {
6645 if (enc_reply.data != NULL) {
6648 if (enc_opt_data.
data != NULL) {
6651 if (enc_packet != NULL) {
6659 dhcpv6_discard(
struct packet *packet) {
6663 log_debug(
"Discarding %s from %s; message type not handled by server",
6669 build_dhcpv6_reply(
struct data_string *reply,
struct packet *packet) {
6670 memset(reply, 0,
sizeof(*reply));
6683 dhcpv6_solicit(reply, packet);
6686 dhcpv6_discard(packet);
6690 dhcpv6_request(reply, packet);
6694 dhcpv6_confirm(reply, packet);
6698 dhcpv6_renew(reply, packet);
6702 dhcpv6_rebind(reply, packet);
6705 dhcpv6_discard(packet);
6709 dhcpv6_release(reply, packet);
6713 dhcpv6_decline(reply, packet);
6716 dhcpv6_discard(packet);
6720 dhcpv6_information_request(reply, packet);
6723 dhcpv6_relay_forw(reply, packet);
6726 dhcpv6_discard(packet);
6733 dhcpv6_discard(packet);
6738 log_info(
"Discarding unknown DHCPv6 message type %d " 6745 log_packet_in(
const struct packet *packet) {
6748 char tmp_addr[INET6_ADDRSTRLEN];
6751 memset(&s, 0,
sizeof(s));
6760 "Unknown message type %d from %s port %d",
6769 inet_ntop(AF_INET6, addr,
6770 tmp_addr,
sizeof(tmp_addr)));
6773 inet_ntop(AF_INET6, addr,
6774 tmp_addr,
sizeof(tmp_addr)));
6804 dhcpv6(
struct packet *packet) {
6806 struct sockaddr_in6 to_addr;
6812 log_packet_in(packet);
6817 build_dhcpv6_reply(&reply, packet);
6819 if (reply.
data != NULL) {
6823 memset(&to_addr, 0,
sizeof(to_addr));
6824 to_addr.sin6_family = AF_INET6;
6832 #if defined (REPLY_TO_SOURCE_PORT) 6844 sizeof(to_addr.sin6_addr));
6846 log_info(
"Sending %s to %s port %d",
6849 ntohs(to_addr.sin6_port));
6852 reply.
data, reply.
len, &to_addr);
6853 if (send_ret != reply.
len) {
6854 log_error(
"dhcpv6: send_packet6() sent %d of %d bytes",
6855 send_ret, reply.
len);
6871 host_reference(&hold, *hp,
MDL);
6872 host_dereference(hp,
MDL);
6874 while (seek != NULL) {
6877 else if (fixed_matches_shared(seek, shared))
6883 if ((seek == NULL) && (nofixed != NULL))
6887 host_reference(hp, seek,
MDL);
6890 static isc_boolean_t
6892 struct subnet *subnet;
6894 isc_boolean_t matched;
6900 memset(&addr, 0,
sizeof(addr));
6905 if (addr.len < 16) {
6911 memcpy(fixed.iabuf, addr.data, 16);
6913 matched = ISC_FALSE;
6914 for (subnet = shared->
subnets ; subnet != NULL ;
6933 find_hosts_by_duid_chaddr(
struct host_decl **host,
6935 static int once_htype;
6937 const unsigned char *chaddr;
6943 if (client_id->
len < 4)
6957 if (client_id->
len > 8) {
6958 hlen = client_id->
len - 8;
6959 chaddr = client_id->
data + 8;
6968 hlen = client_id->
len - 4;
6969 chaddr = client_id->
data + 4;
6989 if ((htype & 0xFF00) && !once_htype) {
6991 log_error(
"Attention: At least one client advertises a " 6992 "hardware type of %d, which exceeds the software " 6993 "limitation of 255.", htype);
7018 struct packet *packet,
7022 struct reply_state reply;
7023 memset(&reply, 0x0,
sizeof(
struct reply_state));
7026 if (shared_network_from_packet6(&reply.shared, packet)
7028 log_error(
"unicast_reject: could not locate client.");
7036 if (start_reply(packet, client_id, server_id, &reply.opt_state,
7037 &reply.buf.reply)) {
7040 "Unicast not allowed by server.",
7042 log_error(
"unicast_reject: Unable to set status code.");
7052 unicast_reject_opts,
7056 reply_ret->
len = reply.cursor;
7057 reply_ret->
buffer = NULL;
7059 reply.cursor,
MDL)) {
7061 "No memory to store Reply.");
7072 if (reply.shared != NULL)
7073 shared_network_dereference(&reply.shared,
MDL);
7074 if (reply.opt_state != NULL)
7076 if (reply.packet != NULL)
7078 if (reply.client_id.
data != NULL)
7101 is_unicast_option_defined(
struct packet *packet) {
7102 isc_boolean_t is_defined = ISC_FALSE;
7109 "No memory for option state.");
7114 if (((shared_network_from_requested_addr(&shared, packet)
7115 != ISC_R_SUCCESS) &&
7116 (shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS))
7117 || (shared == NULL)) {
7121 "cannot attribute packet to a network.");
7132 is_defined = (oc != NULL ? ISC_TRUE : ISC_FALSE);
7133 log_debug(
"is_unicast_option_defined: option found : %d", is_defined);
7135 if (shared != NULL) {
7136 shared_network_dereference(&shared,
MDL);
7139 if (opt_state != NULL) {
7143 return (is_defined);
7162 shared_network_from_requested_addr (
struct shared_network **shared,
7163 struct packet* packet) {
7165 struct subnet* subnet = NULL;
7166 isc_result_t status = ISC_R_FAILURE;
7171 if ((get_first_ia_addr_val(packet,
D6O_IA_NA, &
iaddr) != ISC_R_SUCCESS)
7175 != ISC_R_SUCCESS)) {
7177 log_debug(
"share_network_from_request_addr: nothing to match");
7178 return (ISC_R_FAILURE);
7182 log_debug(
"shared_network_from_requested_addr:" 7185 status = shared_network_reference(shared,
7187 subnet_dereference(&subnet,
MDL);
7188 log_debug(
"shared_network_from_requested_addr:" 7189 " found shared network %s for address %s.",
7190 ((*shared)->name ? (*shared)->name :
"unnamed"),
7195 return (ISC_R_FAILURE);
7217 get_first_ia_addr_val (
struct packet* packet,
int addr_type,
7223 int addr_opt_offset;
7225 int addr_opt_data_len;
7228 isc_result_t status = ISC_R_FAILURE;
7229 memset(iaddr, 0,
sizeof(
struct iaddr));
7232 switch (addr_type) {
7236 addr_opt_data_len = 24;
7242 addr_opt_data_len = 24;
7248 addr_opt_data_len = 25;
7253 log_error (
"get_first_ia_addr_val: invalid opt type %d",
7255 return (ISC_R_FAILURE);
7260 ia != NULL && oc == NULL; ia = ia->
next) {
7261 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
7263 packet, ia, addr_opt_offset)) {
7265 " couldn't unroll enclosing option");
7266 return (ISC_R_FAILURE);
7282 memset(&iaddr_str, 0,
sizeof(iaddr_str));
7287 "error evaluating IA_XX option.");
7289 if (iaddr_str.len != addr_opt_data_len) {
7290 log_error(
"shared_network_from_requested_addr:" 7291 " invalid length %d, expected %d",
7292 iaddr_str.len, addr_opt_data_len);
7295 memcpy (iaddr->
iabuf,
7296 iaddr_str.data + ip_addr_offset, 16);
7297 status = ISC_R_SUCCESS;
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)