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,
157 duid_time(time_t when) {
194 return (server_duid.data != NULL);
232 isc_result_t ret_val;
245 ret_val = ISC_R_NOTFOUND;
247 memset(&option_duid, 0,
sizeof(option_duid));
251 ret_val = ISC_R_UNEXPECTED;
255 ret_val = ISC_R_SUCCESS;
274 static int server_duid_type =
DUID_LLT;
281 server_duid_type = type;
298 log_error(
"Invalid DUID type %d specified, " 299 "only LL and LLT types supported", server_duid_type);
312 log_error(
"Can not generate DUID from interfaces which do not have hardware addresses, please configure server-duid!");
316 return ISC_R_UNEXPECTED;
322 memset(&generated_duid, 0,
sizeof(generated_duid));
324 time_val = duid_time(time(NULL));
327 generated_duid.len,
MDL)) {
330 generated_duid.data = generated_duid.buffer->data;
332 putUShort(generated_duid.buffer->data + 2,
334 putULong(generated_duid.buffer->data + 4, time_val);
335 memcpy(generated_duid.buffer->data + 8,
337 }
else if (server_duid_type ==
DUID_LL) {
340 generated_duid.len,
MDL)) {
343 generated_duid.data = generated_duid.buffer->data;
345 putUShort(generated_duid.buffer->data + 2,
347 memcpy(generated_duid.buffer->data + 4,
350 log_fatal(
"Unsupported server DUID type %d.", server_duid_type);
356 return ISC_R_SUCCESS;
362 static isc_boolean_t unicast_option_defined;
368 static isc_boolean_t unicast_option_parsed = ISC_FALSE;
375 is_unicast_option_defined(
void) {
382 if (unicast_option_parsed == ISC_FALSE) {
383 unicast_option_parsed = ISC_TRUE;
386 log_fatal(
"No memory for option state.");
393 unicast_option_defined = (oc != NULL);
398 return (unicast_option_defined);
411 if ((client_id->
data != NULL) || (client_id->
len != 0)) {
417 return ISC_R_NOTFOUND;
423 return ISC_R_FAILURE;
426 return ISC_R_SUCCESS;
437 valid_client_msg(
struct packet *packet,
struct data_string *client_id) {
443 memset(client_id, 0,
sizeof(*client_id));
451 "client identifier missing",
456 log_error(
"Error processing %s from %s; " 457 "unable to evaluate Client Identifier",
467 log_debug(
"Discarding %s from %s; packet sent unicast " 482 "server identifier found " 483 "(CLIENTID %s, SERVERID %s)",
487 client_id->
data, 60),
492 "server identifier found " 496 client_id->
data, 60),
510 if (client_id->
len > 0) {
530 valid_client_resp(
struct packet *packet,
540 memset(client_id, 0,
sizeof(*client_id));
541 memset(server_id, 0,
sizeof(*server_id));
548 "client identifier missing",
553 log_error(
"Error processing %s from %s; " 554 "unable to evaluate Client Identifier",
563 "server identifier missing (CLIENTID %s)",
572 log_error(
"Error processing %s from %s; " 573 "unable to evaluate Server Identifier (CLIENTID %s)",
579 if ((server_duid.len != server_id->
len) ||
580 (memcmp(server_duid.data, server_id->
data, server_duid.len) != 0)) {
582 "not our server identifier " 583 "(CLIENTID %s, SERVERID %s, server DUID %s)",
588 print_hex_3(server_duid.len, server_duid.data, 60));
597 if (server_id->
len > 0) {
600 if (client_id->
len > 0) {
619 valid_client_info_req(
struct packet *packet,
struct data_string *server_id) {
623 char client_id_str[80];
627 memset(server_id, 0,
sizeof(*server_id));
628 memset(&client_id, 0,
sizeof(client_id));
639 snprintf(client_id_str,
sizeof(client_id_str),
" (CLIENTID %s)",
643 client_id_str[0] =
'\0';
650 log_debug(
"Discarding %s from %s; packet sent unicast%s",
659 "IA_NA option present%s",
667 "IA_TA option present%s",
675 "IA_PD option present%s",
686 log_error(
"Error processing %s from %s; " 687 "unable to evaluate Server Identifier%s",
692 if ((server_duid.len != server_id->
len) ||
693 (memcmp(server_duid.data, server_id->
data,
694 server_duid.len) != 0)) {
696 "not our server identifier " 697 "(SERVERID %s, server DUID %s)%s",
701 server_id->
data, 60),
703 server_duid.data, 60),
714 if (server_id->
len > 0) {
725 static const int required_opts[] = {
732 static const int required_opts_NAA[] = {
738 static const int required_opts_solicit[] = {
750 static const int required_opts_agent[] = {
755 static const int required_opts_IA[] = {
760 static const int required_opts_IA_PD[] = {
765 static const int required_opts_STATUS_CODE[] = {
777 get_encapsulated_IA_state(
struct option_state **enc_opt_state,
779 struct packet *packet,
786 memset(enc_opt_data, 0,
sizeof(*enc_opt_data));
788 NULL, NULL, packet->
options, NULL,
791 "error evaluating raw option.");
794 if (enc_opt_data->
len < offset) {
795 log_error(
"get_encapsulated_IA_state: raw option too small.");
804 *enc_opt_state = NULL;
806 log_error(
"get_encapsulated_IA_state: no memory for options.");
811 enc_opt_data->
data + offset,
812 enc_opt_data->
len - offset,
814 log_error(
"get_encapsulated_IA_state: error parsing options.");
824 set_status_code(u_int16_t status_code,
const char *status_message,
830 memset(&d, 0,
sizeof(d));
831 d.len =
sizeof(status_code) + strlen(status_message);
833 log_fatal(
"set_status_code: no memory for status code.");
835 d.data = d.buffer->data;
837 memcpy(d.buffer->data +
sizeof(status_code),
838 status_message, d.len -
sizeof(status_code));
840 d.buffer, (
unsigned char *)d.data, d.len,
842 log_error(
"set_status_code: error saving status code.");
856 start_reply(
struct packet *packet,
863 const unsigned char *server_id_data;
871 log_error(
"start_reply: no memory for option_state.");
939 if (server_id == NULL) {
940 server_id_data = server_duid.data;
941 server_id_len = server_duid.len;
943 server_id_data = server_id->
data;
944 server_id_len = server_id->
len;
947 NULL, (
unsigned char *)server_id_data,
950 "error saving server identifier.");
955 if (client_id->
buffer != NULL) {
958 (
unsigned char *)client_id->
data,
962 "client identifier.");
978 NULL, (
unsigned char *)
"", 0,
981 "error saving RECONF_ACCEPT option.");
999 try_client_v6_address(
struct iasubopt **addr,
1003 struct in6_addr tmp_addr;
1004 isc_result_t result;
1006 if (requested_addr->
len <
sizeof(tmp_addr)) {
1009 memcpy(&tmp_addr, requested_addr->
data,
sizeof(tmp_addr));
1010 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
1011 return ISC_R_FAILURE;
1019 return ISC_R_ADDRNOTAVAIL;
1023 return ISC_R_ADDRINUSE;
1026 result = iasubopt_allocate(addr,
MDL);
1027 if (result != ISC_R_SUCCESS) {
1030 (*addr)->addr = tmp_addr;
1035 if (result != ISC_R_SUCCESS) {
1064 pick_v6_address(
struct reply_state *reply)
1070 unsigned int attempts;
1071 char tmp_buf[INET6_ADDRSTRLEN];
1072 struct iasubopt **addr = &reply->lease;
1078 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1082 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1092 log_debug(
"Unable to pick client address: " 1093 "no IPv6 pools on this shared network");
1094 return ISC_R_NORESOURCES;
1108 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1121 &reply->ia->iaid_duid,
1122 cur_time + 120) == ISC_R_SUCCESS)) {
1136 inet_ntop(AF_INET6, &((*addr)->addr),
1137 tmp_buf,
sizeof(tmp_buf)));
1138 return (ISC_R_SUCCESS);
1145 }
while (i != start_pool);
1152 log_debug(
"Unable to pick client address: no addresses available");
1153 return ISC_R_NORESOURCES;
1165 try_client_v6_prefix(
struct iasubopt **pref,
1170 struct in6_addr tmp_pref;
1172 isc_result_t result;
1174 if (requested_pref->
len <
sizeof(tmp_plen) +
sizeof(tmp_pref)) {
1177 tmp_plen = (
int) requested_pref->
data[0];
1178 if ((tmp_plen < 3) || (tmp_plen > 128) ||
1179 ((
int)tmp_plen != pool->
units)) {
1180 return ISC_R_FAILURE;
1182 memcpy(&tmp_pref, requested_pref->
data + 1,
sizeof(tmp_pref));
1183 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
1184 return ISC_R_FAILURE;
1187 memcpy(&ia.iabuf, &tmp_pref, 16);
1189 return ISC_R_FAILURE;
1193 return ISC_R_ADDRNOTAVAIL;
1197 return ISC_R_ADDRINUSE;
1200 result = iasubopt_allocate(pref,
MDL);
1201 if (result != ISC_R_SUCCESS) {
1204 (*pref)->addr = tmp_pref;
1205 (*pref)->plen = tmp_plen;
1209 if (result != ISC_R_SUCCESS) {
1238 pick_v6_prefix(
struct reply_state *reply)
1243 unsigned int attempts;
1244 char tmp_buf[INET6_ADDRSTRLEN];
1245 struct iasubopt **pref = &reply->lease;
1251 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1255 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1265 log_debug(
"Unable to pick client prefix: " 1266 "no IPv6 pools on this shared network");
1267 return ISC_R_NORESOURCES;
1278 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1285 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1293 if ((reply->preflen >= 0) && (p->
units != reply->preflen)) {
1298 cur_time + 120) == ISC_R_SUCCESS) {
1300 inet_ntop(AF_INET6, &((*pref)->addr),
1301 tmp_buf,
sizeof(tmp_buf)),
1302 (
unsigned) (*pref)->plen);
1304 return (ISC_R_SUCCESS);
1313 log_debug(
"Unable to pick client prefix: no prefixes available");
1314 return ISC_R_NORESOURCES;
1354 struct packet *packet,
1358 static struct reply_state reply;
1361 #if defined (RFC3315_PRE_ERRATA_2010_08) 1362 isc_boolean_t no_resources_avail = ISC_FALSE;
1366 memset(&packet_oro, 0,
sizeof(packet_oro));
1369 if (shared_network_from_packet6(&reply.shared,
1370 packet) != ISC_R_SUCCESS)
1379 if (!start_reply(packet, client_id, server_id, &reply.opt_state,
1395 log_error(
"lease_to_client: error evaluating ORO.");
1407 seek_shared_host(&reply.host, reply.shared);
1410 if ((reply.host == NULL) &&
1413 seek_shared_host(&reply.host, reply.shared);
1420 if ((reply.host == NULL) &&
1421 find_hosts_by_duid_chaddr(&reply.host, client_id)) {
1423 seek_shared_host(&reply.host, reply.shared);
1430 for (; oc != NULL ; oc = oc->
next) {
1431 isc_result_t status;
1434 reply.client_resources = 0;
1435 reply.resources_included = ISC_FALSE;
1437 status = reply_process_ia_na(&reply, oc);
1443 if ((status != ISC_R_SUCCESS) &&
1444 (status != ISC_R_NORESOURCES))
1447 #if defined (RFC3315_PRE_ERRATA_2010_08) 1452 if (reply.client_resources == 0)
1453 no_resources_avail = ISC_TRUE;
1457 for (; oc != NULL ; oc = oc->
next) {
1458 isc_result_t status;
1461 reply.client_resources = 0;
1462 reply.resources_included = ISC_FALSE;
1464 status = reply_process_ia_ta(&reply, oc);
1470 if ((status != ISC_R_SUCCESS) &&
1471 (status != ISC_R_NORESOURCES))
1474 #if defined (RFC3315_PRE_ERRATA_2010_08) 1479 if (reply.client_resources == 0)
1480 no_resources_avail = ISC_TRUE;
1487 for (; oc != NULL ; oc = oc->
next) {
1488 isc_result_t status;
1491 reply.client_resources = 0;
1492 reply.resources_included = ISC_FALSE;
1494 status = reply_process_ia_pd(&reply, oc);
1500 if ((status != ISC_R_SUCCESS) &&
1501 (status != ISC_R_NORESOURCES))
1509 if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
1510 if (reply.packet->dhcpv6_msg_type !=
1520 reply.packet->options,
1526 for (i = reply.packet->class_count; i > 0; i--) {
1529 reply.packet->options,
1532 reply.packet->classes[i - 1]->group,
1533 reply.shared->group, NULL);
1537 if (reply.host != NULL)
1540 reply.packet->options,
1544 reply.shared->group, NULL);
1548 if ((packet->
unicast == ISC_TRUE) && !is_unicast_option_defined())
1571 "Unicast not allowed by server.",
1573 log_error(
"lease_to_client: Unable to set " 1574 "UseMulticast status code.");
1592 reply.opt_state, reply.packet,
1621 #if defined (RFC3315_PRE_ERRATA_2010_08) 1622 else if (no_resources_avail && (reply.ia_count != 0) &&
1627 "No addresses available for this " 1628 "interface.", reply.opt_state)) {
1629 log_error(
"lease_to_client: Unable to set " 1630 "NoAddrsAvail status code.");
1649 reply.opt_state, reply.packet,
1661 reply.opt_state, reply.packet,
1662 required_opts_solicit,
1671 reply.cursor +=
store_options6((
char *)reply.buf.data + reply.cursor,
1672 sizeof(reply.buf) - reply.cursor,
1673 reply.opt_state, reply.packet,
1674 required_opts_solicit,
1679 reply_ret->
len = reply.cursor;
1680 reply_ret->
buffer = NULL;
1684 memcpy(reply_ret->
buffer->
data, reply.buf.data, reply.cursor);
1692 if (reply.shared != NULL)
1693 shared_network_dereference(&reply.shared,
MDL);
1694 if (reply.host != NULL)
1695 host_dereference(&reply.host,
MDL);
1696 if (reply.opt_state != NULL)
1698 if (reply.packet != NULL)
1700 if (reply.client_id.data != NULL)
1702 if (packet_oro.buffer != NULL)
1704 reply.renew = reply.rebind = reply.prefer = reply.valid = 0;
1712 reply_process_ia_na(
struct reply_state *reply,
struct option_cache *ia) {
1713 isc_result_t status = ISC_R_SUCCESS;
1722 memset(&ia_data, 0,
sizeof(ia_data));
1729 if ((reply->cursor +
IA_NA_OFFSET + 4) >
sizeof(reply->buf)) {
1730 log_error(
"reply_process_ia_na: Reply too long for IA.");
1731 return ISC_R_NOSPACE;
1736 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
1738 log_error(
"reply_process_ia_na: error evaluating ia");
1739 status = ISC_R_FAILURE;
1745 reply->renew =
getULong(ia_data.data + 4);
1746 reply->rebind =
getULong(ia_data.data + 8);
1749 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
1750 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
1751 log_error(
"reply_process_ia_na: no memory for ia.");
1752 status = ISC_R_NOMEMORY;
1759 (
unsigned char *)reply->ia->iaid_duid.data,
1760 reply->ia->iaid_duid.len,
MDL);
1767 status = ISC_R_NOMEMORY;
1772 if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
1773 struct iaddr tmp_addr;
1777 reply->host->fixed_addr,
MDL)) {
1778 log_error(
"reply_process_ia_na: unable to evaluate " 1780 status = ISC_R_FAILURE;
1784 if (reply->fixed.len < 16) {
1785 log_error(
"reply_process_ia_na: invalid fixed address.");
1792 memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
1795 tmp_addr,
MDL) == 0)
1798 reply->static_lease = ISC_TRUE;
1800 reply->static_lease = ISC_FALSE;
1808 ia_cursor = reply->cursor;
1815 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
1819 putULong(reply->buf.data + reply->cursor, iaid);
1823 putULong(reply->buf.data + reply->cursor, reply->renew);
1827 putULong(reply->buf.data + reply->cursor, reply->rebind);
1840 reply->valid = reply->prefer = 0xffffffff;
1841 reply->client_valid = reply->client_prefer = 0;
1842 for (; oc != NULL ; oc = oc->
next) {
1843 status = reply_process_addr(reply, oc);
1851 if (status == ISC_R_CANCELED)
1854 if ((status != ISC_R_SUCCESS) &&
1855 (status != ISC_R_ADDRINUSE) &&
1856 (status != ISC_R_ADDRNOTAVAIL))
1866 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
1867 status = find_client_address(reply);
1869 if (status == ISC_R_NORESOURCES) {
1870 switch (reply->packet->dhcpv6_msg_type) {
1893 "memory for option state " 1895 status = ISC_R_NOMEMORY;
1900 "No addresses available " 1901 "for this interface.",
1903 log_error(
"reply_process_ia_na: Unable " 1904 "to set NoAddrsAvail status " 1906 status = ISC_R_FAILURE;
1910 status = ISC_R_SUCCESS;
1930 if (reply->resources_included)
1931 status = ISC_R_SUCCESS;
1938 if (status != ISC_R_SUCCESS)
1942 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
1943 sizeof(reply->buf) - reply->cursor,
1944 reply->reply_ia, reply->packet,
1945 required_opts_IA, NULL);
1948 putUShort(reply->buf.data + ia_cursor + 2,
1949 reply->cursor - (ia_cursor + 4));
1962 reply->packet->options,
1968 reply->renew =
getULong(data.data);
1971 if (data.data != NULL)
1974 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
1982 reply->packet->options,
1988 reply->rebind =
getULong(data.data);
1991 if (data.data != NULL)
1994 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
2000 if (status == ISC_R_CANCELED)
2007 if (reply->static_lease) {
2008 char tmp_addr[INET6_ADDRSTRLEN];
2009 log_info(
"%s NA: address %s to client with duid %s iaid = %d " 2012 inet_ntop(AF_INET6, reply->fixed.data, tmp_addr,
2015 reply->client_id.data, 60),
2019 (reply->on_star.on_commit != NULL)) {
2021 reply->packet->options,
2022 reply->opt_state, NULL,
2023 reply->on_star.on_commit, NULL);
2025 (&reply->on_star.on_commit,
MDL);
2033 if (reply->ia->num_iasubopt != 0) {
2036 char tmp_addr[INET6_ADDRSTRLEN];
2038 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2039 tmp = reply->ia->iasubopt[i];
2041 log_info(
"%s NA: address %s to client with duid %s " 2042 "iaid = %d valid for %d seconds",
2044 inet_ntop(AF_INET6, &tmp->
addr,
2045 tmp_addr,
sizeof(tmp_addr)),
2047 reply->client_id.data, 60),
2061 if ((reply->ia->num_iasubopt != 0) &&
2067 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2068 tmp = reply->ia->iasubopt[i];
2070 if (tmp->
ia != NULL)
2082 reply->packet->options,
2091 #if defined (NSUPDATE) 2100 reply->packet->options,
2105 tmp, NULL, reply->opt_state);
2111 if (reply->old_ia != NULL) {
2112 ia_id = &reply->old_ia->iaid_duid;
2114 (
unsigned char *)ia_id->
data,
2121 ia_id = &reply->ia->iaid_duid;
2123 ia_id->
len, reply->ia,
MDL);
2129 if (packet_ia != NULL)
2131 if (reply->reply_ia != NULL)
2133 if (ia_data.data != NULL)
2135 if (
data.data != NULL)
2137 if (reply->ia != NULL)
2139 if (reply->old_ia != NULL)
2141 if (reply->lease != NULL)
2143 if (reply->fixed.data != NULL)
2145 if (reply->subnet != NULL)
2146 subnet_dereference(&reply->subnet,
MDL);
2147 if (reply->on_star.on_expiry != NULL)
2149 (&reply->on_star.on_expiry,
MDL);
2150 if (reply->on_star.on_release != NULL)
2152 (&reply->on_star.on_release,
MDL);
2159 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2169 reply_process_addr(
struct reply_state *reply,
struct option_cache *addr) {
2170 u_int32_t pref_life, valid_life;
2174 struct iaddr tmp_addr;
2177 isc_result_t status = ISC_R_SUCCESS;
2180 memset(&iaaddr, 0,
sizeof(iaaddr));
2188 if ((reply->cursor + 28) >
sizeof(reply->buf)) {
2189 log_error(
"reply_process_addr: Out of room for address.");
2190 return ISC_R_NOSPACE;
2198 log_error(
"reply_process_addr: error evaluating IAADDR.");
2199 status = ISC_R_FAILURE;
2204 pref_life =
getULong(iaaddr.data + 16);
2205 valid_life =
getULong(iaaddr.data + 20);
2207 if ((reply->client_valid == 0) ||
2208 (reply->client_valid > valid_life))
2209 reply->client_valid = valid_life;
2211 if ((reply->client_prefer == 0) ||
2212 (reply->client_prefer > pref_life))
2213 reply->client_prefer = pref_life;
2220 memset(tmp_addr.iabuf, 0, 16);
2221 if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
2227 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2232 for (subnet = reply->shared->subnets ; subnet != NULL ;
2240 if (subnet == NULL) {
2265 log_error(
"reply_process_addr: No memory for " 2266 "option state wipe.");
2267 status = ISC_R_NOMEMORY;
2273 "Address not for use on this " 2274 "link.", reply->reply_ia)) {
2275 log_error(
"reply_process_addr: Failure " 2276 "setting status code.");
2277 status = ISC_R_FAILURE;
2282 status = ISC_R_CANCELED;
2294 if ((reply->packet->dhcpv6_msg_type !=
DHCPV6_RENEW) &&
2296 log_error(
"It is impossible to lease a client that is " 2297 "not sending a solicit, request, renew, or " 2299 status = ISC_R_FAILURE;
2303 reply->send_prefer = reply->send_valid = 0;
2308 if (!address_is_owned(reply, &tmp_addr)) {
2319 status = reply_process_try_addr(reply, &tmp_addr);
2326 if ((status != ISC_R_SUCCESS) &&
2327 (status != ISC_R_ADDRINUSE) &&
2328 (status != ISC_R_ADDRNOTAVAIL))
2336 if (reply->lease == NULL) {
2337 if (reply->packet->dhcpv6_msg_type ==
2339 reply->send_prefer = 0;
2340 reply->send_valid = 0;
2357 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
2361 log_error(
"reply_process_addr: No memory for " 2362 "option state wipe.");
2363 status = ISC_R_NOMEMORY;
2369 "Address not bound to this " 2370 "interface.", reply->reply_ia)) {
2371 log_error(
"reply_process_addr: Unable to " 2372 "attach status code.");
2373 status = ISC_R_FAILURE;
2378 status = ISC_R_CANCELED;
2381 log_error(
"It is impossible to lease a client that is " 2382 "not sending a solicit, request, renew, or " 2384 status = ISC_R_FAILURE;
2389 if (reply->static_lease) {
2390 if (reply->host == NULL)
2394 group = reply->subnet->group;
2396 if (reply->lease == NULL)
2399 scope = &reply->lease->scope;
2400 group = reply->lease->ipv6_pool->ipv6_pond->group;
2409 if (reply->client_resources != 0) {
2422 reply->packet->options,
2426 log_error(
"reply_process_addr: unable to " 2427 "evaluate addrs-per-ia value.");
2428 status = ISC_R_FAILURE;
2440 if (reply->client_resources >= limit)
2444 status = reply_process_is_addressed(reply, scope, group);
2445 if (status != ISC_R_SUCCESS)
2449 status = reply_process_send_addr(reply, &tmp_addr);
2452 if (iaaddr.data != NULL)
2454 if (
data.data != NULL)
2456 if (reply->lease != NULL)
2468 static isc_boolean_t
2469 address_is_owned(
struct reply_state *reply,
struct iaddr *addr) {
2476 if (reply->static_lease) {
2477 if (reply->fixed.data == NULL)
2480 if (memcmp(addr->
iabuf, reply->fixed.data, 16) == 0)
2486 if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
2489 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2492 tmp = reply->old_ia->iasubopt[i];
2494 if (memcmp(addr->
iabuf, &tmp->
addr, 16) == 0) {
2519 reply_process_ia_ta(
struct reply_state *reply,
struct option_cache *ia) {
2520 isc_result_t status = ISC_R_SUCCESS;
2527 u_int32_t pref_life, valid_life;
2528 struct iaddr tmp_addr;
2532 memset(&ia_data, 0,
sizeof(ia_data));
2533 memset(&data, 0,
sizeof(data));
2534 memset(&iaaddr, 0,
sizeof(iaaddr));
2537 if ((reply->cursor +
IA_TA_OFFSET + 4) >
sizeof(reply->buf)) {
2538 log_error(
"reply_process_ia_ta: Reply too long for IA.");
2539 return ISC_R_NOSPACE;
2544 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2546 log_error(
"reply_process_ia_ta: error evaluating ia");
2547 status = ISC_R_FAILURE;
2555 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
2556 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
2557 log_error(
"reply_process_ia_ta: no memory for ia.");
2558 status = ISC_R_NOMEMORY;
2565 (
unsigned char *)reply->ia->iaid_duid.data,
2566 reply->ia->iaid_duid.len,
MDL);
2573 status = ISC_R_NOMEMORY;
2580 reply->static_lease = ISC_FALSE;
2588 ia_cursor = reply->cursor;
2595 putUShort(reply->buf.data + reply->cursor, 0x04u);
2599 putULong(reply->buf.data + reply->cursor, iaid);
2606 reply->valid = reply->prefer = 0xffffffff;
2607 reply->client_valid = reply->client_prefer = 0;
2609 for (; oc != NULL; oc = oc->
next) {
2610 memset(&iaaddr, 0,
sizeof(iaaddr));
2613 reply->packet->options, NULL,
2617 "evaluating IAADDR.");
2618 status = ISC_R_FAILURE;
2622 pref_life =
getULong(iaaddr.data + 16);
2623 valid_life =
getULong(iaaddr.data + 20);
2625 if ((reply->client_valid == 0) ||
2626 (reply->client_valid > valid_life))
2627 reply->client_valid = valid_life;
2629 if ((reply->client_prefer == 0) ||
2630 (reply->client_prefer > pref_life))
2631 reply->client_prefer = pref_life;
2634 if (status == ISC_R_CANCELED)
2638 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2639 if (!temporary_is_available(reply, &tmp_addr))
2641 status = reply_process_is_addressed(reply,
2642 &reply->lease->scope,
2643 reply->lease->ipv6_pool->ipv6_pond->group);
2644 if (status != ISC_R_SUCCESS)
2646 status = reply_process_send_addr(reply, &tmp_addr);
2647 if (status != ISC_R_SUCCESS)
2649 if (reply->lease != NULL)
2657 status = ISC_R_NOMEMORY;
2660 status = ISC_R_CANCELED;
2661 reply->client_resources = 0;
2662 reply->resources_included = ISC_FALSE;
2663 if (reply->lease != NULL)
2671 if (reply->client_resources != 0)
2673 status = find_client_temporaries(reply);
2674 if (status == ISC_R_NORESOURCES) {
2675 switch (reply->packet->dhcpv6_msg_type) {
2696 "memory for option state wipe.");
2697 status = ISC_R_NOMEMORY;
2702 "No addresses available " 2703 "for this interface.",
2705 log_error(
"reply_process_ia_ta: Unable " 2706 "to set NoAddrsAvail status code.");
2707 status = ISC_R_FAILURE;
2711 status = ISC_R_SUCCESS;
2720 if (reply->resources_included)
2721 status = ISC_R_SUCCESS;
2726 }
else if (status != ISC_R_SUCCESS)
2730 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2731 sizeof(reply->buf) - reply->cursor,
2732 reply->reply_ia, reply->packet,
2733 required_opts_IA, NULL);
2736 putUShort(reply->buf.data + ia_cursor + 2,
2737 reply->cursor - (ia_cursor + 4));
2743 if (status == ISC_R_CANCELED)
2749 if (reply->ia->num_iasubopt != 0) {
2752 char tmp_addr[INET6_ADDRSTRLEN];
2754 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2755 tmp = reply->ia->iasubopt[i];
2757 log_info(
"%s TA: address %s to client with duid %s " 2758 "iaid = %d valid for %d seconds",
2760 inet_ntop(AF_INET6, &tmp->
addr,
2761 tmp_addr,
sizeof(tmp_addr)),
2763 reply->client_id.data, 60),
2777 if ((reply->ia->num_iasubopt != 0) &&
2783 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2784 tmp = reply->ia->iasubopt[i];
2786 if (tmp->
ia != NULL)
2798 reply->packet->options,
2807 #if defined (NSUPDATE) 2816 reply->packet->options,
2821 tmp, NULL, reply->opt_state);
2827 if (reply->old_ia != NULL) {
2828 ia_id = &reply->old_ia->iaid_duid;
2830 (
unsigned char *)ia_id->
data,
2837 ia_id = &reply->ia->iaid_duid;
2839 ia_id->
len, reply->ia,
MDL);
2845 if (packet_ia != NULL)
2847 if (iaaddr.data != NULL)
2849 if (reply->reply_ia != NULL)
2851 if (ia_data.data != NULL)
2853 if (
data.data != NULL)
2855 if (reply->ia != NULL)
2857 if (reply->old_ia != NULL)
2859 if (reply->lease != NULL)
2867 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2873 static isc_boolean_t
2874 temporary_is_available(
struct reply_state *reply,
struct iaddr *addr) {
2875 struct in6_addr tmp_addr;
2876 struct subnet *subnet;
2881 memcpy(&tmp_addr, addr->
iabuf,
sizeof(tmp_addr));
2887 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
2893 for (subnet = reply->shared->subnets ; subnet != NULL ;
2907 if (address_is_owned(reply, addr))
2913 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
2920 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
2936 if (iasubopt_allocate(&reply->lease,
MDL) != ISC_R_SUCCESS)
2938 reply->lease->addr = tmp_addr;
2939 reply->lease->plen = 0;
2951 find_client_temporaries(
struct reply_state *reply) {
2955 isc_result_t status = ISC_R_NORESOURCES;;
2956 unsigned int attempts;
2957 struct iaddr send_addr;
2963 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
2967 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
2977 log_debug(
"Unable to get client addresses: " 2978 "no IPv6 pools on this shared network");
2979 return ISC_R_NORESOURCES;
2989 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
2996 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3005 &reply->client_id,
cur_time + 120);
3006 if (status != ISC_R_SUCCESS) {
3007 log_debug(
"Unable to get a temporary address.");
3011 status = reply_process_is_addressed(reply,
3012 &reply->lease->scope,
3014 if (status != ISC_R_SUCCESS) {
3018 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3019 status = reply_process_send_addr(reply, &send_addr);
3020 if (status != ISC_R_SUCCESS) {
3032 if (reply->lease != NULL) {
3043 reply_process_try_addr(
struct reply_state *reply,
struct iaddr *addr) {
3044 isc_result_t status = ISC_R_ADDRNOTAVAIL;
3050 if ((reply == NULL) || (reply->shared == NULL) ||
3051 (addr == NULL) || (reply->lease != NULL))
3058 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3062 for (i = 0; ; i++) {
3064 if ((pool == NULL) ||
3074 return (ISC_R_ADDRNOTAVAIL);
3077 memset(&data_addr, 0,
sizeof(data_addr));
3078 data_addr.len = addr->
len;
3079 data_addr.data = addr->
iabuf;
3092 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3099 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
3103 status = try_client_v6_address(&reply->lease, pool,
3105 if (status == ISC_R_SUCCESS)
3109 if (status == ISC_R_SUCCESS)
3124 find_client_address(
struct reply_state *reply) {
3125 struct iaddr send_addr;
3126 isc_result_t status = ISC_R_NORESOURCES;
3129 struct group *group;
3132 if (reply->static_lease) {
3133 if (reply->host == NULL)
3137 memcpy(send_addr.iabuf, reply->fixed.data, 16);
3140 group = reply->subnet->group;
3144 if (reply->old_ia != NULL) {
3145 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
3149 lease = reply->old_ia->iasubopt[i];
3158 if ((candidate_shared != reply->shared) ||
3168 best_lease = lease_compare(lease, best_lease);
3176 status = pick_v6_address(reply);
3177 }
else if (best_lease != NULL) {
3179 status = ISC_R_SUCCESS;
3183 if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
3185 log_error(
"Reclaiming abandoned addresses is not yet " 3186 "supported. Treating this as an out of space " 3192 if (status != ISC_R_SUCCESS)
3195 if (reply->lease == NULL)
3202 scope = &reply->lease->scope;
3203 group = reply->lease->ipv6_pool->ipv6_pond->group;
3206 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3209 status = reply_process_is_addressed(reply, scope, group);
3210 if (status != ISC_R_SUCCESS)
3213 status = reply_process_send_addr(reply, &send_addr);
3222 reply_process_is_addressed(
struct reply_state *reply,
3225 isc_result_t status = ISC_R_SUCCESS;
3233 memset(&data, 0,
sizeof(data));
3242 on_star = &reply->lease->on_star;
3244 on_star = &reply->on_star;
3254 reply->packet->options, tmp_options,
3257 if (tmp_options != NULL) {
3267 reply->packet->options, reply->opt_state,
3271 for (i = reply->packet->class_count; i > 0; i--) {
3273 reply->packet->options,
3274 reply->opt_state, scope,
3275 reply->packet->classes[i - 1]->group,
3284 if (reply->host != NULL)
3286 reply->packet->options,
3287 reply->opt_state, scope,
3288 reply->host->group, group,
3292 if (reply->client_valid == 0)
3295 reply->send_valid = reply->client_valid;
3301 reply->packet->options,
3305 log_error(
"reply_process_is_addressed: unable to " 3306 "evaluate default lease time");
3307 status = ISC_R_FAILURE;
3311 reply->send_valid =
getULong(data.data);
3315 if (reply->client_prefer == 0)
3316 reply->send_prefer = reply->send_valid;
3318 reply->send_prefer = reply->client_prefer;
3320 if (reply->send_prefer >= reply->send_valid)
3321 reply->send_prefer = (reply->send_valid / 2) +
3322 (reply->send_valid / 8);
3328 reply->packet->options,
3332 log_error(
"reply_process_is_addressed: unable to " 3333 "evaluate preferred lease time");
3334 status = ISC_R_FAILURE;
3338 reply->send_prefer =
getULong(data.data);
3343 if (reply->prefer > reply->send_prefer)
3344 reply->prefer = reply->send_prefer;
3346 if (reply->valid > reply->send_valid)
3347 reply->valid = reply->send_valid;
3359 if (reply->host != NULL)
3361 reply->client_id->len);
3365 if (reply->lease != NULL) {
3367 reply->lease->prefer = reply->send_prefer;
3368 reply->lease->valid = reply->send_valid;
3372 reply->lease->soft_lifetime_end_time =
3378 if (status != ISC_R_SUCCESS) {
3379 log_fatal(
"reply_process_is_addressed: Unable to " 3380 "attach lease to new IA: %s",
3381 isc_result_totext(status));
3387 if (reply->lease->ia == NULL) {
3394 reply->packet->options, reply->reply_ia,
3398 for (i = reply->packet->class_count; i > 0; i--) {
3400 reply->packet->options,
3401 reply->reply_ia, scope,
3402 reply->packet->classes[i - 1]->group,
3410 if (reply->host != NULL)
3412 reply->packet->options,
3413 reply->reply_ia, scope,
3414 reply->host->group, group, NULL);
3417 if (data.data != NULL)
3420 if (status == ISC_R_SUCCESS)
3421 reply->client_resources++;
3428 reply_process_send_addr(
struct reply_state *reply,
struct iaddr *addr) {
3429 isc_result_t status = ISC_R_SUCCESS;
3437 log_error(
"reply_process_send_addr: out of memory" 3438 "allocating new IAADDR buffer.");
3439 status = ISC_R_NOMEMORY;
3444 memcpy(
data.buffer->data, addr->
iabuf, 16);
3451 log_error(
"reply_process_send_addr: unable " 3452 "to save IAADDR option");
3453 status = ISC_R_FAILURE;
3457 reply->resources_included = ISC_TRUE;
3460 if (
data.data != NULL)
3474 switch(alpha->
state) {
3476 switch(beta->
state) {
3497 switch (beta->
state) {
3523 switch (beta->
state) {
3543 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
3551 reply_process_ia_pd(
struct reply_state *reply,
struct option_cache *ia) {
3552 isc_result_t status = ISC_R_SUCCESS;
3561 memset(&ia_data, 0,
sizeof(ia_data));
3568 if ((reply->cursor +
IA_PD_OFFSET + 4) >
sizeof(reply->buf)) {
3569 log_error(
"reply_process_ia_pd: Reply too long for IA.");
3570 return ISC_R_NOSPACE;
3575 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
3577 log_error(
"reply_process_ia_pd: error evaluating ia");
3578 status = ISC_R_FAILURE;
3584 reply->renew =
getULong(ia_data.data + 4);
3585 reply->rebind =
getULong(ia_data.data + 8);
3588 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
3589 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
3590 log_error(
"reply_process_ia_pd: no memory for ia.");
3591 status = ISC_R_NOMEMORY;
3598 (
unsigned char *)reply->ia->iaid_duid.data,
3599 reply->ia->iaid_duid.len,
MDL);
3606 status = ISC_R_NOMEMORY;
3611 reply->static_prefixes = 0;
3612 if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
3615 for (fp = reply->host->fixed_prefix; fp != NULL;
3617 reply->static_prefixes += 1;
3627 ia_cursor = reply->cursor;
3634 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
3638 putULong(reply->buf.data + reply->cursor, iaid);
3642 putULong(reply->buf.data + reply->cursor, reply->renew);
3646 putULong(reply->buf.data + reply->cursor, reply->rebind);
3653 reply->valid = reply->prefer = 0xffffffff;
3654 reply->client_valid = reply->client_prefer = 0;
3655 reply->preflen = -1;
3656 for (; oc != NULL ; oc = oc->
next) {
3657 status = reply_process_prefix(reply, oc);
3665 if (status == ISC_R_CANCELED)
3668 if ((status != ISC_R_SUCCESS) &&
3669 (status != ISC_R_ADDRINUSE) &&
3670 (status != ISC_R_ADDRNOTAVAIL))
3680 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
3681 status = find_client_prefix(reply);
3683 if (status == ISC_R_NORESOURCES) {
3684 switch (reply->packet->dhcpv6_msg_type) {
3699 "memory for option state " 3701 status = ISC_R_NOMEMORY;
3706 "No prefixes available " 3707 "for this interface.",
3711 "NoPrefixAvail status " 3713 status = ISC_R_FAILURE;
3717 status = ISC_R_SUCCESS;
3721 if (reply->resources_included)
3722 status = ISC_R_SUCCESS;
3729 if (status != ISC_R_SUCCESS)
3733 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
3734 sizeof(reply->buf) - reply->cursor,
3735 reply->reply_ia, reply->packet,
3736 required_opts_IA_PD, NULL);
3739 putUShort(reply->buf.data + ia_cursor + 2,
3740 reply->cursor - (ia_cursor + 4));
3753 reply->packet->options,
3759 reply->renew =
getULong(data.data);
3762 if (data.data != NULL)
3765 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
3773 reply->packet->options,
3779 reply->rebind =
getULong(data.data);
3782 if (data.data != NULL)
3785 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
3791 if (status == ISC_R_CANCELED)
3798 if (reply->static_prefixes != 0) {
3799 char tmp_addr[INET6_ADDRSTRLEN];
3800 log_info(
"%s PD: address %s/%d to client with duid %s " 3803 inet_ntop(AF_INET6, reply->fixed_pref.lo_addr.iabuf,
3804 tmp_addr,
sizeof(tmp_addr)),
3805 reply->fixed_pref.bits,
3807 reply->client_id.data, 60),
3810 (reply->on_star.on_commit != NULL)) {
3812 reply->packet->options,
3814 NULL, reply->on_star.on_commit,
3817 (&reply->on_star.on_commit,
MDL);
3825 if (reply->ia->num_iasubopt != 0) {
3828 char tmp_addr[INET6_ADDRSTRLEN];
3830 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3831 tmp = reply->ia->iasubopt[i];
3833 log_info(
"%s PD: address %s/%d to client with duid %s" 3834 " iaid = %d valid for %d seconds",
3836 inet_ntop(AF_INET6, &tmp->
addr,
3837 tmp_addr,
sizeof(tmp_addr)),
3840 reply->client_id.data, 60),
3854 (reply->ia->num_iasubopt != 0)) {
3859 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3860 tmp = reply->ia->iasubopt[i];
3862 if (tmp->
ia != NULL)
3874 reply->packet->options,
3885 if (reply->old_ia != NULL) {
3886 ia_id = &reply->old_ia->iaid_duid;
3888 (
unsigned char *)ia_id->
data,
3895 ia_id = &reply->ia->iaid_duid;
3897 ia_id->
len, reply->ia,
MDL);
3903 if (packet_ia != NULL)
3905 if (reply->reply_ia != NULL)
3907 if (ia_data.data != NULL)
3909 if (
data.data != NULL)
3911 if (reply->ia != NULL)
3913 if (reply->old_ia != NULL)
3915 if (reply->lease != NULL)
3917 if (reply->on_star.on_expiry != NULL)
3919 (&reply->on_star.on_expiry,
MDL);
3920 if (reply->on_star.on_release != NULL)
3922 (&reply->on_star.on_release,
MDL);
3929 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
3939 reply_process_prefix(
struct reply_state *reply,
struct option_cache *pref) {
3940 u_int32_t pref_life, valid_life;
3945 isc_result_t status = ISC_R_SUCCESS;
3946 struct group *group;
3949 memset(&iapref, 0,
sizeof(iapref));
3950 memset(&data, 0,
sizeof(data));
3957 if ((reply->cursor + 29) >
sizeof(reply->buf)) {
3958 log_error(
"reply_process_prefix: Out of room for prefix.");
3959 return ISC_R_NOSPACE;
3967 log_error(
"reply_process_prefix: error evaluating IAPREFIX.");
3968 status = ISC_R_FAILURE;
3977 valid_life =
getULong(iapref.data + 4);
3979 if ((reply->client_valid == 0) ||
3980 (reply->client_valid > valid_life))
3981 reply->client_valid = valid_life;
3983 if ((reply->client_prefer == 0) ||
3984 (reply->client_prefer > pref_life))
3985 reply->client_prefer = pref_life;
3991 tmp_pref.lo_addr.len = 16;
3992 memset(tmp_pref.lo_addr.iabuf, 0, 16);
3993 if ((iapref.data[8] == 0) &&
3994 (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
4003 tmp_pref.bits = (
int) iapref.data[8];
4004 if (reply->preflen < 0) {
4006 reply->preflen = tmp_pref.bits;
4008 if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
4012 memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
4015 if (!prefix_is_owned(reply, &tmp_pref)) {
4020 status = reply_process_try_prefix(reply, &tmp_pref);
4023 if ((status != ISC_R_SUCCESS) &&
4024 (status != ISC_R_ADDRINUSE) &&
4025 (status != ISC_R_ADDRNOTAVAIL))
4028 if (reply->lease == NULL) {
4029 if (reply->packet->dhcpv6_msg_type ==
4031 reply->send_prefer = 0;
4032 reply->send_valid = 0;
4051 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
4055 log_error(
"reply_process_prefix: No memory " 4056 "for option state wipe.");
4057 status = ISC_R_NOMEMORY;
4063 "Prefix not bound to this " 4064 "interface.", reply->reply_ia)) {
4065 log_error(
"reply_process_prefix: Unable to " 4066 "attach status code.");
4067 status = ISC_R_FAILURE;
4072 status = ISC_R_CANCELED;
4075 log_error(
"It is impossible to lease a client that is " 4076 "not sending a solicit, request, renew, or " 4078 status = ISC_R_FAILURE;
4083 if (reply->static_prefixes > 0) {
4084 if (reply->host == NULL)
4091 tmp_pref.lo_addr,
MDL) == 0)
4093 group = reply->subnet->group;
4094 subnet_dereference(&reply->subnet,
MDL);
4097 memcpy(&reply->fixed_pref, &tmp_pref,
sizeof(tmp_pref));
4099 if (reply->lease == NULL)
4102 scope = &reply->lease->scope;
4103 group = reply->lease->ipv6_pool->ipv6_pond->group;
4112 if (reply->client_resources != 0) {
4125 reply->packet->options,
4129 log_error(
"reply_process_prefix: unable to " 4130 "evaluate prefs-per-ia value.");
4131 status = ISC_R_FAILURE;
4143 if (reply->client_resources >= limit)
4147 status = reply_process_is_prefixed(reply, scope, group);
4148 if (status != ISC_R_SUCCESS)
4152 status = reply_process_send_prefix(reply, &tmp_pref);
4155 if (iapref.data != NULL)
4157 if (data.data != NULL)
4159 if (reply->lease != NULL)
4171 static isc_boolean_t
4172 prefix_is_owned(
struct reply_state *reply,
struct iaddrcidrnet *pref) {
4180 if (reply->static_prefixes > 0) {
4181 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4190 if ((reply->old_ia == NULL) ||
4191 (reply->old_ia->num_iasubopt == 0))
4194 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4197 tmp = reply->old_ia->iasubopt[i];
4199 if ((pref->
bits == (
int) tmp->
plen) &&
4225 reply_process_try_prefix(
struct reply_state *reply,
4227 isc_result_t status = ISC_R_ADDRNOTAVAIL;
4233 if ((reply == NULL) || (reply->shared == NULL) ||
4234 (pref == NULL) || (reply->lease != NULL))
4241 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4245 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4255 return (ISC_R_ADDRNOTAVAIL);
4258 memset(&data_pref, 0,
sizeof(data_pref));
4261 log_error(
"reply_process_try_prefix: out of memory.");
4262 return (ISC_R_NOMEMORY);
4264 data_pref.data = data_pref.buffer->data;
4265 data_pref.buffer->data[0] = (u_int8_t) pref->
bits;
4266 memcpy(data_pref.buffer->data + 1, pref->
lo_addr.
iabuf, 16);
4276 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4283 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4288 status = try_client_v6_prefix(&reply->lease, pool,
4292 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4295 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4309 find_client_prefix(
struct reply_state *reply) {
4311 isc_result_t status = ISC_R_NORESOURCES;
4312 struct iasubopt *prefix, *best_prefix = NULL;
4315 struct group *group;
4317 if (reply->static_prefixes > 0) {
4320 if (reply->host == NULL)
4323 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4332 l = reply->host->fixed_prefix;
4334 memcpy(&send_pref, &l->
cidrnet,
sizeof(send_pref));
4340 send_pref.lo_addr,
MDL) == 0)
4342 group = reply->subnet->group;
4343 subnet_dereference(&reply->subnet,
MDL);
4346 memcpy(&reply->fixed_pref, &l->
cidrnet,
sizeof(send_pref));
4351 if (reply->old_ia != NULL) {
4352 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4356 prefix = reply->old_ia->iasubopt[i];
4365 if (((candidate_shared != NULL) &&
4366 (candidate_shared != reply->shared)) ||
4380 best_prefix = prefix_compare(reply, prefix,
4389 status = pick_v6_prefix(reply);
4390 }
else if (best_prefix != NULL) {
4392 status = ISC_R_SUCCESS;
4396 if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
4398 log_error(
"Reclaiming abandoned prefixes is not yet " 4399 "supported. Treating this as an out of space " 4405 if (status != ISC_R_SUCCESS)
4408 if (reply->lease == NULL)
4411 scope = &reply->lease->scope;
4412 group = reply->lease->ipv6_pool->ipv6_pond->group;
4414 send_pref.lo_addr.len = 16;
4415 memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
4416 send_pref.bits = (
int) reply->lease->plen;
4419 status = reply_process_is_prefixed(reply, scope, group);
4420 if (status != ISC_R_SUCCESS)
4423 status = reply_process_send_prefix(reply, &send_pref);
4432 reply_process_is_prefixed(
struct reply_state *reply,
4435 isc_result_t status = ISC_R_SUCCESS;
4439 struct on_star *on_star;
4443 memset(&data, 0,
sizeof(data));
4452 on_star = &reply->lease->on_star;
4454 on_star = &reply->on_star;
4464 reply->packet->options, tmp_options,
4467 if (tmp_options != NULL) {
4477 reply->packet->options, reply->opt_state,
4481 for (i = reply->packet->class_count; i > 0; i--) {
4483 reply->packet->options,
4484 reply->opt_state, scope,
4485 reply->packet->classes[i - 1]->group,
4494 if (reply->host != NULL)
4496 reply->packet->options,
4497 reply->opt_state, scope,
4498 reply->host->group, group,
4502 if (reply->client_valid == 0)
4505 reply->send_valid = reply->client_valid;
4511 reply->packet->options,
4515 log_error(
"reply_process_is_prefixed: unable to " 4516 "evaluate default prefix time");
4517 status = ISC_R_FAILURE;
4521 reply->send_valid =
getULong(data.data);
4525 if (reply->client_prefer == 0)
4526 reply->send_prefer = reply->send_valid;
4528 reply->send_prefer = reply->client_prefer;
4530 if (reply->send_prefer >= reply->send_valid)
4531 reply->send_prefer = (reply->send_valid / 2) +
4532 (reply->send_valid / 8);
4538 reply->packet->options,
4542 log_error(
"reply_process_is_prefixed: unable to " 4543 "evaluate preferred prefix time");
4544 status = ISC_R_FAILURE;
4548 reply->send_prefer =
getULong(data.data);
4553 if (reply->prefer > reply->send_prefer)
4554 reply->prefer = reply->send_prefer;
4556 if (reply->valid > reply->send_valid)
4557 reply->valid = reply->send_valid;
4560 if (reply->lease != NULL) {
4562 reply->lease->prefer = reply->send_prefer;
4563 reply->lease->valid = reply->send_valid;
4567 reply->lease->soft_lifetime_end_time =
4573 if (status != ISC_R_SUCCESS) {
4574 log_fatal(
"reply_process_is_prefixed: Unable to " 4575 "attach prefix to new IA_PD: %s",
4576 isc_result_totext(status));
4582 if (reply->lease->ia == NULL) {
4589 reply->packet->options, reply->reply_ia,
4593 for (i = reply->packet->class_count; i > 0; i--) {
4595 reply->packet->options,
4596 reply->reply_ia, scope,
4597 reply->packet->classes[i - 1]->group,
4605 if (reply->host != NULL)
4607 reply->packet->options,
4608 reply->reply_ia, scope,
4609 reply->host->group, group, NULL);
4612 if (data.data != NULL)
4615 if (status == ISC_R_SUCCESS)
4616 reply->client_resources++;
4623 reply_process_send_prefix(
struct reply_state *reply,
4625 isc_result_t status = ISC_R_SUCCESS;
4633 log_error(
"reply_process_send_prefix: out of memory" 4634 "allocating new IAPREFIX buffer.");
4635 status = ISC_R_NOMEMORY;
4648 log_error(
"reply_process_send_prefix: unable " 4649 "to save IAPREFIX option");
4650 status = ISC_R_FAILURE;
4654 reply->resources_included = ISC_TRUE;
4657 if (
data.data != NULL)
4665 prefix_compare(
struct reply_state *reply,
4672 if (reply->preflen >= 0) {
4673 if ((alpha->
plen == reply->preflen) &&
4674 (beta->
plen != reply->preflen))
4676 if ((beta->
plen == reply->preflen) &&
4677 (alpha->
plen != reply->preflen))
4681 switch(alpha->
state) {
4683 switch(beta->
state) {
4704 switch (beta->
state) {
4730 switch (beta->
state) {
4750 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
4764 dhcpv6_solicit(
struct data_string *reply_ret,
struct packet *packet) {
4772 if (!valid_client_msg(packet, &client_id)) {
4776 lease_to_client(reply_ret, packet, &client_id, NULL);
4793 dhcpv6_request(
struct data_string *reply_ret,
struct packet *packet) {
4802 if (!valid_client_resp(packet, &client_id, &server_id)) {
4809 lease_to_client(reply_ret, packet, &client_id, &server_id);
4824 struct packet *packet)
4826 const struct packet *chk_packet;
4827 const struct in6_addr *link_addr, *first_link_addr;
4828 struct iaddr tmp_addr;
4829 struct subnet *subnet;
4830 isc_result_t status;
4832 if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
4839 first_link_addr = NULL;
4841 while (chk_packet != NULL) {
4843 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
4844 !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
4845 first_link_addr = link_addr;
4856 if (first_link_addr != NULL) {
4857 tmp_addr.len =
sizeof(*first_link_addr);
4858 memcpy(tmp_addr.iabuf,
4859 first_link_addr,
sizeof(*first_link_addr));
4862 log_debug(
"No subnet found for link-address %s.",
4864 return ISC_R_NOTFOUND;
4866 status = shared_network_reference(shared,
4868 subnet_dereference(&subnet,
MDL);
4875 status = shared_network_reference(shared,
4879 log_info(
"[L2 Relay] No link address in relay packet " 4880 "assuming L2 relay and using receiving " 4890 log_error(
"No interface and no link address " 4891 "can't determine pool");
4917 dhcpv6_confirm(
struct data_string *reply_ret,
struct packet *packet) {
4919 struct subnet *subnet;
4921 struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
4923 struct iaddr cli_addr;
4925 isc_boolean_t inappropriate, has_addrs;
4926 char reply_data[65536];
4935 memset(&client_id, 0,
sizeof(client_id));
4936 if (!valid_client_msg(packet, &client_id)) {
4945 if ((ia == NULL) && (ta == NULL))
4956 opt_state = cli_enc_opt_state = NULL;
4957 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
4958 memset(&iaaddr, 0,
sizeof(iaaddr));
4959 memset(&packet_oro, 0,
sizeof(packet_oro));
4966 if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
4978 has_addrs = inappropriate = ISC_FALSE;
4980 while(!inappropriate) {
4984 if ((pass ==
D6O_IA_NA) && (ia == NULL)) {
4994 !get_encapsulated_IA_state(&cli_enc_opt_state,
4998 !get_encapsulated_IA_state(&cli_enc_opt_state,
5007 for ( ; oc != NULL ; oc = oc->
next) {
5013 "error evaluating IAADDR.");
5019 memcpy(cli_addr.iabuf, iaaddr.data, 16);
5024 has_addrs = ISC_TRUE;
5027 for (subnet = shared->
subnets ; subnet != NULL ;
5042 if (subnet == NULL) {
5043 inappropriate = ISC_TRUE;
5062 if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
5069 if (inappropriate) {
5071 "Some of the addresses are not on link.",
5077 "All addresses still on link.",
5087 sizeof(reply_data)-reply_ofs,
5089 required_opts, &packet_oro);
5094 reply_ret->
len = reply_ofs;
5095 reply_ret->
buffer = NULL;
5100 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5104 if (cli_enc_opt_data.buffer != NULL)
5106 if (iaaddr.buffer != NULL)
5108 if (client_id.
buffer != NULL)
5110 if (packet_oro.buffer != NULL)
5114 if (cli_enc_opt_state != NULL)
5116 if (opt_state != NULL)
5130 dhcpv6_renew(
struct data_string *reply,
struct packet *packet) {
5139 if (!valid_client_resp(packet, &client_id, &server_id)) {
5146 lease_to_client(reply, packet, &client_id, &server_id);
5165 dhcpv6_rebind(
struct data_string *reply,
struct packet *packet) {
5170 if (!valid_client_msg(packet, &client_id)) {
5174 lease_to_client(reply, packet, &client_id, NULL);
5182 ia_na_match_decline(
const struct data_string *client_id,
5186 char tmp_addr[INET6_ADDRSTRLEN];
5188 log_error(
"Client %s reports address %s is " 5189 "already in use by another host!",
5191 inet_ntop(AF_INET6, iaaddr->
data,
5192 tmp_addr,
sizeof(tmp_addr)));
5193 if (lease != NULL) {
5201 ia_na_nomatch_decline(
const struct data_string *client_id,
5203 u_int32_t *ia_na_id,
5204 struct packet *packet,
5209 char tmp_addr[INET6_ADDRSTRLEN];
5213 log_info(
"Client %s declines address %s, which is not offered to it.",
5215 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5220 host_opt_state = NULL;
5222 log_error(
"ia_na_nomatch_decline: out of memory " 5223 "allocating option_state.");
5235 if (reply_len < (*reply_ofs + 16)) {
5237 "out of space for reply packet.");
5245 reply_len-(*reply_ofs)-16,
5246 host_opt_state, packet,
5247 required_opts_STATUS_CODE, NULL);
5257 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5259 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5261 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5262 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5267 *reply_ofs += (len + 16);
5275 struct packet *packet,
5278 const char *packet_type,
5279 void (*ia_na_match)(),
5280 void (*ia_na_nomatch)())
5293 char reply_data[65536];
5296 char status_msg[32];
5298 struct ia_xx *existing_ia_na;
5307 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5308 cli_enc_opt_state = NULL;
5309 memset(&iaaddr, 0,
sizeof(iaaddr));
5310 memset(&fixed_addr, 0,
sizeof(fixed_addr));
5311 host_opt_state = NULL;
5331 if (!find_hosts_by_duid_chaddr(&packet_host,
5349 log_error(
"iterate_over_ia_na: no memory for option_state.");
5362 (
unsigned char *)server_duid.data,
5365 "error saving server identifier.");
5372 (
unsigned char *)client_id->
data,
5376 "error saving client identifier.");
5381 if ((packet->
unicast == ISC_TRUE) && !is_unicast_option_defined()) {
5401 snprintf(status_msg,
sizeof(status_msg),
5402 "%s received unicast.", packet_type);
5415 sizeof(reply_data)-reply_ofs,
5417 required_opts_NAA, NULL);
5421 snprintf(status_msg,
sizeof(status_msg),
"%s received.", packet_type);
5430 sizeof(reply_data)-reply_ofs,
5432 required_opts, NULL);
5440 ia != NULL; ia = ia->
next) {
5442 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5448 iaid =
getULong(cli_enc_opt_data.data);
5466 memset(&iaaddr, 0,
sizeof(iaaddr));
5471 "error evaluating IAADDR.");
5485 cli_enc_opt_state,
MDL)) {
5486 if (packet_host != NULL) {
5492 while (host != NULL) {
5500 "evaluating host address.");
5503 if ((iaaddr.
len >= 16) &&
5504 !memcmp(fixed_addr.data, iaaddr.
data, 16)) {
5518 (
char *)client_id->
data,
5520 MDL) != ISC_R_SUCCESS) {
5521 log_fatal(
"iterate_over_ia_na: no memory for " 5525 existing_ia_na = NULL;
5527 (
unsigned char *)key.data,
5534 struct in6_addr *in6_addr;
5537 in6_addr = &tmp->
addr;
5538 if (memcmp(in6_addr,
5539 iaaddr.
data, 16) == 0) {
5550 if ((host != NULL) || (lease != NULL)) {
5551 ia_na_match(client_id, &iaaddr, lease);
5553 ia_na_nomatch(client_id, &iaaddr,
5554 (u_int32_t *)cli_enc_opt_data.
data,
5555 packet, reply_data, &reply_ofs,
5556 sizeof(reply_data));
5559 if (lease != NULL) {
5572 reply_ret->
len = reply_ofs;
5573 reply_ret->
buffer = NULL;
5578 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5581 if (lease != NULL) {
5584 if (host_opt_state != NULL) {
5587 if (fixed_addr.buffer != NULL) {
5590 if (iaaddr.
buffer != NULL) {
5593 if (cli_enc_opt_state != NULL) {
5596 if (cli_enc_opt_data.buffer != NULL) {
5599 if (opt_state != NULL) {
5619 dhcpv6_decline(
struct data_string *reply,
struct packet *packet) {
5628 if (!valid_client_resp(packet, &client_id, &server_id)) {
5640 iterate_over_ia_na(reply, packet, &client_id, &server_id,
"Decline",
5641 ia_na_match_decline, ia_na_nomatch_decline);
5650 ia_na_match_release(
const struct data_string *client_id,
5654 char tmp_addr[INET6_ADDRSTRLEN];
5656 log_info(
"Client %s releases address %s",
5658 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5659 if (lease != NULL) {
5667 ia_na_nomatch_release(
const struct data_string *client_id,
5669 u_int32_t *ia_na_id,
5670 struct packet *packet,
5675 char tmp_addr[INET6_ADDRSTRLEN];
5679 log_info(
"Client %s releases address %s, which is not leased to it.",
5681 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5686 host_opt_state = NULL;
5688 log_error(
"ia_na_nomatch_release: out of memory " 5689 "allocating option_state.");
5694 "Release for non-leased address.",
5702 if (reply_len < (*reply_ofs + 16)) {
5704 "out of space for reply packet.");
5712 reply_len-(*reply_ofs)-16,
5713 host_opt_state, packet,
5714 required_opts_STATUS_CODE, NULL);
5724 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5726 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5728 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5729 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5734 *reply_ofs += (len + 16);
5741 ia_pd_match_release(
const struct data_string *client_id,
5745 char tmp_addr[INET6_ADDRSTRLEN];
5747 log_info(
"Client %s releases prefix %s/%u",
5749 inet_ntop(AF_INET6, iapref->
data + 9,
5750 tmp_addr,
sizeof(tmp_addr)),
5752 if (prefix != NULL) {
5760 ia_pd_nomatch_release(
const struct data_string *client_id,
5762 u_int32_t *ia_pd_id,
5763 struct packet *packet,
5768 char tmp_addr[INET6_ADDRSTRLEN];
5772 log_info(
"Client %s releases prefix %s/%u, which is not leased to it.",
5774 inet_ntop(AF_INET6, iapref->
data + 9,
5775 tmp_addr,
sizeof(tmp_addr)),
5781 host_opt_state = NULL;
5783 log_error(
"ia_pd_nomatch_release: out of memory " 5784 "allocating option_state.");
5789 "Release for non-leased prefix.",
5797 if (reply_len < (*reply_ofs + 16)) {
5799 "out of space for reply packet.");
5807 reply_len-(*reply_ofs)-16,
5808 host_opt_state, packet,
5809 required_opts_STATUS_CODE, NULL);
5819 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5821 memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
5823 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5824 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5829 *reply_ofs += (len + 16);
5837 struct packet *packet,
5840 const char *packet_type,
5841 void (*ia_pd_match)(),
5842 void (*ia_pd_nomatch)())
5856 char reply_data[65536];
5859 struct ia_xx *existing_ia_pd;
5867 memset(&reply_new, 0,
sizeof(reply_new));
5869 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5870 cli_enc_opt_state = NULL;
5871 memset(&iaprefix, 0,
sizeof(iaprefix));
5872 host_opt_state = NULL;
5878 reply_len =
sizeof(reply_data) - reply_ret->
len;
5898 if (!find_hosts_by_duid_chaddr(&packet_host,
5909 log_error(
"iterate_over_ia_pd: no memory for option_state.");
5921 ia != NULL; ia = ia->
next) {
5923 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5929 iaid =
getULong(cli_enc_opt_data.data);
5940 for (; oc != NULL; oc = oc->
next) {
5941 memset(&iaprefix, 0,
sizeof(iaprefix));
5946 "error evaluating IAPREFIX.");
5960 cli_enc_opt_state,
MDL)) {
5961 if (packet_host != NULL) {
5967 while (host != NULL) {
5976 if (memcmp(iaprefix.data + 9,
5981 if ((l != NULL) && (iaprefix.len >= 17))
5992 (
char *)client_id->
data,
5994 MDL) != ISC_R_SUCCESS) {
5995 log_fatal(
"iterate_over_ia_pd: no memory for " 5999 existing_ia_pd = NULL;
6001 (
unsigned char *)key.data,
6012 plen =
getUChar(iaprefix.data + 8);
6014 if ((tmp->
plen == plen) &&
6028 if ((host != NULL) || (prefix != NULL)) {
6029 ia_pd_match(client_id, &iaprefix, prefix);
6031 ia_pd_nomatch(client_id, &iaprefix,
6032 (u_int32_t *)cli_enc_opt_data.
data,
6033 packet, reply_data, &reply_ofs,
6034 reply_len - reply_ofs);
6037 if (prefix != NULL) {
6052 reply_new.len = reply_ret->
len + reply_ofs;
6056 reply_new.data = reply_new.buffer->data;
6057 memcpy(reply_new.buffer->data,
6059 memcpy(reply_new.buffer->data + reply_ret->
len,
6060 reply_data, reply_ofs);
6066 if (prefix != NULL) {
6069 if (host_opt_state != NULL) {
6072 if (iaprefix.buffer != NULL) {
6075 if (cli_enc_opt_state != NULL) {
6078 if (cli_enc_opt_data.buffer != NULL) {
6081 if (opt_state != NULL) {
6091 dhcpv6_release(
struct data_string *reply,
struct packet *packet) {
6100 if (!valid_client_resp(packet, &client_id, &server_id)) {
6107 iterate_over_ia_na(reply, packet, &client_id, &server_id,
"Release",
6108 ia_na_match_release, ia_na_nomatch_release);
6113 iterate_over_ia_pd(reply, packet, &client_id, &server_id,
"Release",
6114 ia_pd_match_release, ia_pd_nomatch_release);
6128 dhcpv6_information_request(
struct data_string *reply,
struct packet *packet) {
6137 if (!valid_client_info_req(packet, &server_id)) {
6144 memset(&client_id, 0,
sizeof(client_id));
6155 lease_to_client(reply, packet, &client_id,
6156 server_id.
data != NULL ? &server_id : NULL);
6161 if (client_id.
data != NULL) {
6179 dhcpv6_relay_forw(
struct data_string *reply_ret,
struct packet *packet) {
6182 struct packet *enc_packet;
6183 unsigned char msg_type;
6187 char link_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6188 char peer_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6191 static char reply_data[65536];
6201 memset(&a_opt, 0,
sizeof(a_opt));
6202 memset(&packet_ero, 0,
sizeof(packet_ero));
6203 memset(&enc_reply, 0,
sizeof(enc_reply));
6204 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6213 link_addr,
sizeof(link_addr));
6215 peer_addr,
sizeof(peer_addr));
6216 log_info(
"Relay-forward from %s with link address=%s and " 6217 "peer address=%s missing Relay Message option.",
6224 log_error(
"dhcpv6_forw_relay: error evaluating " 6225 "relayed message.");
6230 log_error(
"dhcpv6_forw_relay: encapsulated packet too short.");
6240 "no memory for encapsulated packet.");
6246 "no memory for encapsulated packet's options.");
6255 msg_type = enc_opt_data.
data[0];
6271 enc_opt_data.
len - relaylen,
6289 enc_opt_data.
len - msglen,
6301 build_dhcpv6_reply(&enc_reply, enc_packet);
6307 if (enc_reply.data == NULL) {
6329 log_error(
"dhcpv6_relay_forw: no memory for option state.");
6343 log_error(
"dhcpv6_relay_forw: error evaluating " 6348 (
unsigned char *)a_opt.data,
6351 log_error(
"dhcpv6_relay_forw: error saving " 6362 (
unsigned char *)enc_reply.data,
6365 log_error(
"dhcpv6_relay_forw: error saving Relay MSG.");
6381 (packet_ero.len & 1)) {
6382 log_error(
"dhcpv6_relay_forw: error evaluating ERO.");
6387 for (i = 0; i < packet_ero.len; i += 2) {
6404 "evaluating option %u.", req);
6410 (
unsigned char *)a_opt.data,
6414 log_error(
"dhcpv6_relay_forw: error saving " 6423 sizeof(reply_data) - reply_ofs,
6425 required_opts_agent, &packet_ero);
6430 reply_ret->
len = reply_ofs;
6431 reply_ret->
buffer = NULL;
6436 memcpy(reply_ret->
buffer->
data, reply_data, reply_ofs);
6439 if (opt_state != NULL)
6441 if (a_opt.data != NULL) {
6444 if (packet_ero.data != NULL) {
6447 if (enc_reply.data != NULL) {
6450 if (enc_opt_data.
data != NULL) {
6453 if (enc_packet != NULL) {
6461 dhcpv6_discard(
struct packet *packet) {
6465 log_debug(
"Discarding %s from %s; message type not handled by server",
6471 build_dhcpv6_reply(
struct data_string *reply,
struct packet *packet) {
6472 memset(reply, 0,
sizeof(*reply));
6485 dhcpv6_solicit(reply, packet);
6488 dhcpv6_discard(packet);
6492 dhcpv6_request(reply, packet);
6496 dhcpv6_confirm(reply, packet);
6500 dhcpv6_renew(reply, packet);
6504 dhcpv6_rebind(reply, packet);
6507 dhcpv6_discard(packet);
6511 dhcpv6_release(reply, packet);
6515 dhcpv6_decline(reply, packet);
6518 dhcpv6_discard(packet);
6522 dhcpv6_information_request(reply, packet);
6525 dhcpv6_relay_forw(reply, packet);
6528 dhcpv6_discard(packet);
6535 dhcpv6_discard(packet);
6540 log_info(
"Discarding unknown DHCPv6 message type %d " 6547 log_packet_in(
const struct packet *packet) {
6550 char tmp_addr[INET6_ADDRSTRLEN];
6553 memset(&s, 0,
sizeof(s));
6562 "Unknown message type %d from %s port %d",
6571 inet_ntop(AF_INET6, addr,
6572 tmp_addr,
sizeof(tmp_addr)));
6575 inet_ntop(AF_INET6, addr,
6576 tmp_addr,
sizeof(tmp_addr)));
6606 dhcpv6(
struct packet *packet) {
6608 struct sockaddr_in6 to_addr;
6614 log_packet_in(packet);
6619 build_dhcpv6_reply(&reply, packet);
6621 if (reply.
data != NULL) {
6625 memset(&to_addr, 0,
sizeof(to_addr));
6626 to_addr.sin6_family = AF_INET6;
6634 #if defined (REPLY_TO_SOURCE_PORT) 6646 sizeof(to_addr.sin6_addr));
6648 log_info(
"Sending %s to %s port %d",
6651 ntohs(to_addr.sin6_port));
6654 reply.
data, reply.
len, &to_addr);
6655 if (send_ret != reply.
len) {
6656 log_error(
"dhcpv6: send_packet6() sent %d of %d bytes",
6657 send_ret, reply.
len);
6673 host_reference(&hold, *hp,
MDL);
6674 host_dereference(hp,
MDL);
6676 while (seek != NULL) {
6679 else if (fixed_matches_shared(seek, shared))
6685 if ((seek == NULL) && (nofixed != NULL))
6689 host_reference(hp, seek,
MDL);
6692 static isc_boolean_t
6694 struct subnet *subnet;
6696 isc_boolean_t matched;
6702 memset(&addr, 0,
sizeof(addr));
6707 if (addr.len < 16) {
6713 memcpy(fixed.iabuf, addr.data, 16);
6715 matched = ISC_FALSE;
6716 for (subnet = shared->
subnets ; subnet != NULL ;
6735 find_hosts_by_duid_chaddr(
struct host_decl **host,
6737 static int once_htype;
6739 const unsigned char *chaddr;
6745 if (client_id->
len < 4)
6759 if (client_id->
len > 8) {
6760 hlen = client_id->
len - 8;
6761 chaddr = client_id->
data + 8;
6770 hlen = client_id->
len - 4;
6771 chaddr = client_id->
data + 4;
6791 if ((htype & 0xFF00) && !once_htype) {
6793 log_error(
"Attention: At least one client advertises a " 6794 "hardware type of %d, which exceeds the software " 6795 "limitation of 255.", htype);
struct iaddrcidrnet cidrnet
#define DHCPD_SIX_RELAY_FORW_DONE()
isc_result_t renew_lease6(struct ipv6_pool *pool, struct iasubopt *lease)
Renew a lease in the pool.
int find_grouped_subnet(struct subnet **, struct shared_network *, struct iaddr, const char *, int)
unsigned char peer_address[16]
#define DHCPD_SIX_INFORMATION_REQUEST_START()
struct binding_scope * global_scope
isc_result_t add_lease6(struct ipv6_pool *pool, struct iasubopt *lease, time_t valid_lifetime_end_time)
#define DHCPD_SIX_SOLICIT_DONE()
isc_result_t ia_make_key(struct data_string *key, u_int32_t iaid, const char *duid, unsigned int duid_len, const char *file, int line)
int executable_statement_dereference(struct executable_statement **ptr, const char *file, int line)
struct shared_network * shared_network
const char * piaddr(const struct iaddr addr)
unsigned char dhcpv6_transaction_id[3]
isc_boolean_t server_duid_isset(void)
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
void dhcpv6_leasequery(struct data_string *, struct packet *)
isc_result_t ia_dereference(struct ia_xx **ia, const char *file, int line)
#define DHCPD_SIX_RELAY_FORW_START()
int data_string_sprintfa(struct data_string *ds, const char *fmt,...)
struct universe server_universe
int execute_statements(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct executable_statement *statements, struct on_star *on_star)
isc_boolean_t lease6_usable(struct iasubopt *lease)
Check if address is available to a lease.
int find_hosts_by_option(struct host_decl **, struct packet *, struct option_state *, const char *, int)
#define print_hex_1(len, data, limit)
#define DHCP_R_INVALIDARG
#define STATUS_NoAddrsAvail
#define DHCPD_SIX_RELEASE_DONE()
const char * dhcpv6_type_names[]
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
#define DHCPV6_RECONFIGURE
#define SV_PREFER_LIFETIME
struct universe dhcp_universe
void data_string_forget(struct data_string *data, const char *file, int line)
struct option_cache * next
#define 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 DHCPD_SIX_DECLINE_START()
#define DHCPD_SIX_REQUEST_DONE()
isc_result_t decline_lease6(struct ipv6_pool *pool, struct iasubopt *lease)
struct iaddr subnet_number(struct iaddr addr, struct iaddr mask)
int find_subnet(struct subnet **sp, struct iaddr addr, const char *file, int line)
void execute_statements_in_scope(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct group *group, struct group *limiting_group, struct on_star *on_star)
void change_host_uid(struct host_decl *host, const char *data, int len)
isc_result_t release_lease6(struct ipv6_pool *pool, struct iasubopt *lease)
void schedule_lease_timeout(struct ipv6_pool *pool)
int option_state_allocate(struct option_state **ptr, const char *file, int line)
time_t hard_lifetime_end_time
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
#define STATUS_NoPrefixAvail
int packet_reference(struct packet **ptr, struct packet *bp, const char *file, int line)
struct ipv6_pool * ipv6_pool
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
struct interface_info * interface
ssize_t send_packet6(struct interface_info *, const unsigned char *, size_t, struct sockaddr_in6 *)
void putULong(unsigned char *, u_int32_t)
struct iaddrcidrnetlist * next
#define DEFAULT_DEFAULT_LEASE_TIME
#define DHCPV6_RELAY_FORW
int save_option_buffer(struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, unsigned code, int terminatep)
u_int32_t getUShort(const unsigned char *)
void set_server_duid(struct data_string *new_duid)
isc_result_t create_lease6(struct ipv6_pool *pool, struct iasubopt **addr, unsigned int *attempts, const struct data_string *uid, time_t soft_lifetime_end_time)
struct host_decl * n_ipaddr
struct hardware hw_address
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
#define print_hex_3(len, data, limit)
int permitted(struct packet *, struct permit *)
void set_server_duid_type(int type)
int int log_info(const char *,...) __attribute__((__format__(__printf__
struct ipv6_pool ** ipv6_pools
int packet6_len_okay(const char *packet, int len)
struct interface_info * interfaces
u_int32_t getULong(const unsigned char *)
struct shared_network * shared_network
int find_hosts_by_uid(struct host_decl **, const unsigned char *, unsigned, const char *, int)
int addr_eq(struct iaddr addr1, struct iaddr addr2)
isc_boolean_t ipv6_in_pool(const struct in6_addr *addr, const struct ipv6_pool *pool)
#define DHCPV6_LEASEQUERY_REPLY
isc_result_t get_client_id(struct packet *, struct data_string *)
int store_options6(char *buf, int buflen, struct option_state *opt_state, struct packet *packet, const int *required_opts, struct data_string *oro)
int append_option_buffer(struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, unsigned code, int terminatep)
u_int32_t getUChar(const unsigned char *)
struct iaddrcidrnetlist * fixed_prefix
int option_state_dereference(struct option_state **ptr, const char *file, int line)
void dhcpv6(struct packet *)
int commit_leases_timed(void)
const int dhcpv6_type_name_max
isc_boolean_t is_cidr_mask_valid(const struct iaddr *addr, int bits)
#define DHCPD_SIX_CONFIRM_START()
struct interface_info * next
struct universe dhcpv6_universe
isc_boolean_t prefix6_exists(const struct ipv6_pool *pool, const struct in6_addr *pref, u_int8_t plen)
int evaluate_boolean_option_cache(int *ignorep, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
#define print_hex_2(len, data, limit)
int packet_dereference(struct packet **ptr, const char *file, int line)
int ddns_updates(struct packet *, struct lease *, struct lease *, struct iasubopt *, struct iasubopt *, struct option_state *)
int packet_allocate(struct packet **ptr, const char *file, int line)
isc_result_t iasubopt_dereference(struct iasubopt **iasubopt, const char *file, int line)
#define DHCPD_SIX_REQUEST_START()
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
isc_result_t generate_new_server_duid(void)
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
struct permit * permit_list
#define D6O_RECONF_ACCEPT
#define DHCPV6_INFORMATION_REQUEST
struct in6_addr dhcpv6_link_address
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
void classify_client(struct packet *)
#define SV_LIMIT_PREFS_PER_IA
#define STATUS_UseMulticast
struct packet * dhcpv6_container_packet
isc_result_t iasubopt_reference(struct iasubopt **iasubopt, struct iasubopt *src, const char *file, int line)