25 static void send_dhcpv4_response(
struct data_string *raw);
27 static void recv_dhcpv4_query(
struct data_string *raw);
28 static void dhcp4o6_dhcpv4_query(
struct data_string *reply_ret,
65 unsigned client_resources;
66 isc_boolean_t resources_included;
67 isc_boolean_t static_lease;
68 unsigned static_prefixes;
82 u_int32_t renew, rebind, min_prefer, min_valid;
85 u_int32_t client_valid, client_prefer;
88 u_int32_t send_valid, send_prefer;
100 unsigned char data[65536];
108 static int get_encapsulated_IA_state(
struct option_state **enc_opt_state,
114 static isc_result_t shared_network_from_packet6(
struct shared_network **shared,
116 static void seek_shared_host(
struct host_decl **hp,
118 static isc_boolean_t fixed_matches_shared(
struct host_decl *host,
120 static isc_result_t reply_process_ia_na(
struct reply_state *reply,
122 static isc_result_t reply_process_ia_ta(
struct reply_state *reply,
124 static isc_result_t reply_process_addr(
struct reply_state *reply,
126 static isc_boolean_t address_is_owned(
struct reply_state *reply,
128 static isc_boolean_t temporary_is_available(
struct reply_state *reply,
130 static isc_result_t find_client_temporaries(
struct reply_state *reply);
131 static isc_result_t reply_process_try_addr(
struct reply_state *reply,
133 static isc_result_t find_client_address(
struct reply_state *reply);
134 static isc_result_t reply_process_is_addressed(
struct reply_state *reply,
137 static isc_result_t reply_process_send_addr(
struct reply_state *reply,
141 static isc_result_t reply_process_ia_pd(
struct reply_state *reply,
143 static struct group *find_group_by_prefix(
struct reply_state *reply);
144 static isc_result_t reply_process_prefix(
struct reply_state *reply,
146 static isc_boolean_t prefix_is_owned(
struct reply_state *reply,
148 static isc_result_t find_client_prefix(
struct reply_state *reply);
149 static isc_result_t reply_process_try_prefix(
struct reply_state *reply,
151 static isc_result_t reply_process_is_prefixed(
struct reply_state *reply,
154 static isc_result_t reply_process_send_prefix(
struct reply_state *reply,
156 static struct iasubopt *prefix_compare(
struct reply_state *reply,
159 static void schedule_lease_timeout_reply(
struct reply_state *reply);
161 static int eval_prefix_mode(
int thislen,
int preflen,
int prefix_mode);
162 static isc_result_t pick_v6_prefix_helper(
struct reply_state *reply,
169 static isc_boolean_t is_unicast_option_defined(
struct packet *
packet);
170 static isc_result_t shared_network_from_requested_addr (
struct shared_network 173 static isc_result_t get_first_ia_addr_val (
struct packet*
packet,
int addr_type,
177 set_reply_tee_times(
struct reply_state* reply,
unsigned ia_cursor);
196 if (h->type != dhcp4o6_type)
199 cc = recv(dhcp4o6_fd, buf,
sizeof(buf), 0);
202 return ISC_R_UNEXPECTED;
203 memset(&raw, 0,
sizeof(raw));
205 log_error(
"dhcpv4o6_handler: no memory buffer.");
206 return ISC_R_NOMEMORY;
208 raw.data = raw.buffer->data;
210 memcpy(raw.buffer->data, buf, cc);
213 send_dhcpv4_response(&raw);
215 recv_dhcpv4_query(&raw);
220 return ISC_R_SUCCESS;
231 static void send_dhcpv4_response(
struct data_string *raw) {
234 struct sockaddr_in6 to_addr;
235 char pbuf[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
238 memset(name, 0,
sizeof(name));
239 memcpy(name, raw->
data, 16);
241 if (!strcmp(name, ip->
name))
245 log_error(
"send_dhcpv4_response: can't find interface %s.",
250 memset(&to_addr, 0,
sizeof(to_addr));
251 to_addr.sin6_family = AF_INET6;
252 memcpy(&to_addr.sin6_addr, raw->
data + 16, 16);
260 log_info(
"send_dhcpv4_response(): sending %s on %s to %s port %d",
263 inet_ntop(AF_INET6, raw->
data + 16, pbuf,
sizeof(pbuf)),
264 ntohs(to_addr.sin6_port));
268 log_error(
"send_dhcpv4_response: send_packet6(): %m");
269 }
else if (send_ret != raw->
len - 32) {
270 log_error(
"send_dhcpv4_response: send_packet6() " 271 "sent %d of %d bytes",
272 send_ret, raw->
len - 32);
283 schedule_lease_timeout_reply(
struct reply_state *reply) {
288 if ((reply == NULL) || (reply->ia == NULL) || (reply->ia->iasubopt == NULL))
292 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
293 tmp = reply->ia->iasubopt[i];
303 duid_time(time_t when) {
340 return (server_duid.data != NULL);
378 isc_result_t ret_val;
391 ret_val = ISC_R_NOTFOUND;
393 memset(&option_duid, 0,
sizeof(option_duid));
397 ret_val = ISC_R_UNEXPECTED;
401 ret_val = ISC_R_SUCCESS;
420 static int server_duid_type =
DUID_LLT;
427 server_duid_type = type;
444 log_error(
"Invalid DUID type %d specified, " 445 "only LL and LLT types supported", server_duid_type);
458 log_error(
"Can not generate DUID from interfaces which do not have hardware addresses, please configure server-duid!");
462 return ISC_R_UNEXPECTED;
468 memset(&generated_duid, 0,
sizeof(generated_duid));
470 time_val = duid_time(time(NULL));
473 generated_duid.len,
MDL)) {
476 generated_duid.data = generated_duid.buffer->data;
478 putUShort(generated_duid.buffer->data + 2,
480 putULong(generated_duid.buffer->data + 4, time_val);
481 memcpy(generated_duid.buffer->data + 8,
483 }
else if (server_duid_type ==
DUID_LL) {
486 generated_duid.len,
MDL)) {
489 generated_duid.data = generated_duid.buffer->data;
491 putUShort(generated_duid.buffer->data + 2,
493 memcpy(generated_duid.buffer->data + 4,
496 log_fatal(
"Unsupported server DUID type %d.", server_duid_type);
502 return ISC_R_SUCCESS;
515 if ((client_id->
data != NULL) || (client_id->
len != 0)) {
521 return ISC_R_NOTFOUND;
527 return ISC_R_FAILURE;
530 return ISC_R_SUCCESS;
541 valid_client_msg(
struct packet *packet,
struct data_string *client_id) {
547 memset(client_id, 0,
sizeof(*client_id));
555 "client identifier missing",
560 log_error(
"Error processing %s from %s; " 561 "unable to evaluate Client Identifier",
571 log_debug(
"Discarding %s from %s; packet sent unicast " 586 "server identifier found " 587 "(CLIENTID %s, SERVERID %s)",
591 client_id->
data, 60),
596 "server identifier found " 600 client_id->
data, 60),
614 if (client_id->
len > 0) {
634 valid_client_resp(
struct packet *packet,
644 memset(client_id, 0,
sizeof(*client_id));
645 memset(server_id, 0,
sizeof(*server_id));
652 "client identifier missing",
657 log_error(
"Error processing %s from %s; " 658 "unable to evaluate Client Identifier",
667 "server identifier missing (CLIENTID %s)",
676 log_error(
"Error processing %s from %s; " 677 "unable to evaluate Server Identifier (CLIENTID %s)",
683 if ((server_duid.len != server_id->
len) ||
684 (memcmp(server_duid.data, server_id->
data, server_duid.len) != 0)) {
686 "not our server identifier " 687 "(CLIENTID %s, SERVERID %s, server DUID %s)",
692 print_hex_3(server_duid.len, server_duid.data, 60));
701 if (server_id->
len > 0) {
704 if (client_id->
len > 0) {
723 valid_client_info_req(
struct packet *packet,
struct data_string *server_id) {
727 char client_id_str[80];
731 memset(server_id, 0,
sizeof(*server_id));
732 memset(&client_id, 0,
sizeof(client_id));
743 snprintf(client_id_str,
sizeof(client_id_str),
" (CLIENTID %s)",
747 client_id_str[0] =
'\0';
754 log_debug(
"Discarding %s from %s; packet sent unicast%s",
763 "IA_NA option present%s",
771 "IA_TA option present%s",
779 "IA_PD option present%s",
790 log_error(
"Error processing %s from %s; " 791 "unable to evaluate Server Identifier%s",
796 if ((server_duid.len != server_id->
len) ||
797 (memcmp(server_duid.data, server_id->
data,
798 server_duid.len) != 0)) {
800 "not our server identifier " 801 "(SERVERID %s, server DUID %s)%s",
805 server_id->
data, 60),
807 server_duid.data, 60),
818 if (server_id->
len > 0) {
829 static const int required_opts[] = {
836 static const int required_opts_solicit[] = {
848 static const int required_opts_agent[] = {
853 static const int required_opts_IA[] = {
858 static const int required_opts_IA_PD[] = {
863 static const int required_opts_STATUS_CODE[] = {
868 static const int required_opts_4o6[] = {
874 static const int unicast_reject_opts[] = {
889 get_encapsulated_IA_state(
struct option_state **enc_opt_state,
891 struct packet *packet,
898 memset(enc_opt_data, 0,
sizeof(*enc_opt_data));
900 NULL, NULL, packet->
options, NULL,
903 "error evaluating raw option.");
906 if (enc_opt_data->
len < offset) {
907 log_error(
"get_encapsulated_IA_state: raw option too small.");
916 *enc_opt_state = NULL;
918 log_error(
"get_encapsulated_IA_state: no memory for options.");
923 enc_opt_data->
data + offset,
924 enc_opt_data->
len - offset,
926 log_error(
"get_encapsulated_IA_state: error parsing options.");
936 set_status_code(u_int16_t status_code,
const char *status_message,
942 memset(&d, 0,
sizeof(d));
943 d.len =
sizeof(status_code) + strlen(status_message);
945 log_fatal(
"set_status_code: no memory for status code.");
947 d.data = d.buffer->data;
949 memcpy(d.buffer->data +
sizeof(status_code),
950 status_message, d.len -
sizeof(status_code));
952 d.buffer, (
unsigned char *)d.data, d.len,
954 log_error(
"set_status_code: error saving status code.");
963 void check_pool6_threshold(
struct reply_state *reply,
967 isc_uint64_t used, count, high_threshold;
968 int poolhigh = 0, poollow = 0;
969 char *shared_name =
"no name";
970 char tmp_addr[INET6_ADDRSTRLEN];
1004 log_error(
"Pool threshold reset - shared subnet: %s; " 1005 "address: %s; low threshold %llu/%llu.",
1007 inet_ntop(AF_INET6, &lease->
addr,
1008 tmp_addr,
sizeof(tmp_addr)),
1016 NULL, reply->packet->options, reply->opt_state,
1017 reply->opt_state, &lease->
scope,
1024 if ((poolhigh <= 0) || (poolhigh > 100)) {
1031 if (used < high_threshold) {
1037 log_error(
"Pool threshold exceeded - shared subnet: %s; " 1038 "address: %s; high threshold %d%% %llu/%llu.",
1040 inet_ntop(AF_INET6, &lease->
addr, tmp_addr,
sizeof(tmp_addr)),
1041 poolhigh, used, count);
1046 NULL, reply->packet->options, reply->opt_state,
1047 reply->opt_state, &lease->
scope,
1058 if (poollow < poolhigh) {
1069 start_reply(
struct packet *packet,
1076 const unsigned char *server_id_data;
1084 log_error(
"start_reply: no memory for option_state.");
1152 if (server_id == NULL) {
1153 server_id_data = server_duid.data;
1154 server_id_len = server_duid.len;
1156 server_id_data = server_id->
data;
1157 server_id_len = server_id->
len;
1160 NULL, (
unsigned char *)server_id_data,
1163 "error saving server identifier.");
1168 if (client_id->
buffer != NULL) {
1171 (
unsigned char *)client_id->
data,
1175 "client identifier.");
1191 NULL, (
unsigned char *)
"", 0,
1194 "error saving RECONF_ACCEPT option.");
1212 try_client_v6_address(
struct iasubopt **addr,
1216 struct in6_addr tmp_addr;
1217 isc_result_t result;
1219 if (requested_addr->
len <
sizeof(tmp_addr)) {
1222 memcpy(&tmp_addr, requested_addr->
data,
sizeof(tmp_addr));
1223 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
1224 return ISC_R_FAILURE;
1232 return ISC_R_ADDRNOTAVAIL;
1236 return ISC_R_ADDRINUSE;
1239 result = iasubopt_allocate(addr,
MDL);
1240 if (result != ISC_R_SUCCESS) {
1243 (*addr)->addr = tmp_addr;
1248 if (result != ISC_R_SUCCESS) {
1277 pick_v6_address(
struct reply_state *reply)
1283 unsigned int attempts;
1284 char tmp_buf[INET6_ADDRSTRLEN];
1285 struct iasubopt **addr = &reply->lease;
1286 isc_uint64_t total = 0;
1287 isc_uint64_t active = 0;
1288 isc_uint64_t abandoned = 0;
1289 int jumbo_range = 0;
1290 char *shared_name = (reply->shared->name ?
1291 reply->shared->name :
"(no name)");
1297 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1301 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1311 log_debug(
"Unable to pick client address: " 1312 "no IPv6 pools on this shared network");
1313 return ISC_R_NORESOURCES;
1327 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1328 isc_result_t result = ISC_R_FAILURE;
1342 &reply->ia->iaid_duid,
1344 if (result == ISC_R_SUCCESS) {
1362 tmp_buf,
sizeof(tmp_buf)));
1363 return (ISC_R_SUCCESS);
1371 }
while (i != start_pool);
1373 if (result == ISC_R_NORESOURCES) {
1385 if (jumbo_range != 0) {
1386 log_debug(
"Unable to pick client address: " 1387 "no addresses available - shared network %s: " 1388 " 2^64-1 < total, %llu active, %llu abandoned",
1389 shared_name, active - abandoned, abandoned);
1391 log_debug(
"Unable to pick client address: " 1392 "no addresses available - shared network %s: " 1393 "%llu total, %llu active, %llu abandoned",
1394 shared_name, total, active - abandoned, abandoned);
1397 return ISC_R_NORESOURCES;
1409 try_client_v6_prefix(
struct iasubopt **pref,
1414 struct in6_addr tmp_pref;
1416 isc_result_t result;
1418 if (requested_pref->
len <
sizeof(tmp_plen) +
sizeof(tmp_pref)) {
1421 tmp_plen = (
int) requested_pref->
data[0];
1422 if ((tmp_plen < 3) || (tmp_plen > 128) ||
1423 ((
int)tmp_plen != pool->
units)) {
1424 return ISC_R_FAILURE;
1426 memcpy(&tmp_pref, requested_pref->
data + 1,
sizeof(tmp_pref));
1427 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
1428 return ISC_R_FAILURE;
1431 memcpy(&ia.iabuf, &tmp_pref, 16);
1433 return ISC_R_FAILURE;
1437 return ISC_R_ADDRNOTAVAIL;
1441 return ISC_R_ADDRINUSE;
1444 result = iasubopt_allocate(pref,
MDL);
1445 if (result != ISC_R_SUCCESS) {
1448 (*pref)->addr = tmp_pref;
1449 (*pref)->plen = tmp_plen;
1453 if (result != ISC_R_SUCCESS) {
1499 pick_v6_prefix(
struct reply_state *reply) {
1503 isc_result_t result;
1509 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1513 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1523 log_debug(
"Unable to pick client prefix: " 1524 "no IPv6 pools on this shared network");
1525 return ISC_R_NORESOURCES;
1528 if (reply->preflen <= 0) {
1531 result = pick_v6_prefix_helper(reply,
PLM_IGNORE);
1537 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1538 if (result != ISC_R_SUCCESS) {
1539 result = pick_v6_prefix_helper(reply,
1546 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1553 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1554 if (result != ISC_R_SUCCESS) {
1555 result = pick_v6_prefix_helper(reply,
1562 result = pick_v6_prefix_helper(reply,
PLM_IGNORE);
1567 if (result == ISC_R_SUCCESS) {
1568 char tmp_buf[INET6_ADDRSTRLEN];
1571 inet_ntop(AF_INET6, &(reply->lease->addr),
1572 tmp_buf,
sizeof(tmp_buf)),
1573 (
unsigned)(reply->lease->plen));
1574 return (ISC_R_SUCCESS);
1581 log_debug(
"Unable to pick client prefix: no prefixes available");
1582 return ISC_R_NORESOURCES;
1609 pick_v6_prefix_helper(
struct reply_state *reply,
int prefix_mode) {
1613 unsigned int attempts;
1614 struct iasubopt **pref = &reply->lease;
1616 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1623 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1625 (eval_prefix_mode(p->
units, reply->preflen,
1626 prefix_mode) == 1) &&
1628 &reply->ia->iaid_duid,
1629 cur_time + 120) == ISC_R_SUCCESS)) {
1630 return (ISC_R_SUCCESS);
1635 return ISC_R_NORESOURCES;
1653 eval_prefix_mode(
int len,
int preflen,
int prefix_mode) {
1655 switch (prefix_mode) {
1657 use_it = (len == preflen);
1661 use_it = (len >= preflen);
1665 use_it = (len <= preflen);
1674 "len %d, preflen %d, mode %s, use_it %d",
1719 struct packet *packet,
1723 static struct reply_state reply;
1728 memset(&packet_oro, 0,
sizeof(packet_oro));
1731 if (shared_network_from_packet6(&reply.shared,
1732 packet) != ISC_R_SUCCESS)
1741 if (!start_reply(packet, client_id, server_id, &reply.opt_state,
1757 log_error(
"lease_to_client: error evaluating ORO.");
1768 seek_shared_host(&reply.host, reply.shared);
1775 for (; oc != NULL ; oc = oc->
next) {
1776 isc_result_t status;
1779 reply.client_resources = 0;
1780 reply.resources_included = ISC_FALSE;
1782 status = reply_process_ia_na(&reply, oc);
1788 if ((status != ISC_R_SUCCESS) &&
1789 (status != ISC_R_NORESOURCES))
1793 for (; oc != NULL ; oc = oc->
next) {
1794 isc_result_t status;
1797 reply.client_resources = 0;
1798 reply.resources_included = ISC_FALSE;
1800 status = reply_process_ia_ta(&reply, oc);
1806 if ((status != ISC_R_SUCCESS) &&
1807 (status != ISC_R_NORESOURCES))
1814 for (; oc != NULL ; oc = oc->
next) {
1815 isc_result_t status;
1818 reply.client_resources = 0;
1819 reply.resources_included = ISC_FALSE;
1821 status = reply_process_ia_pd(&reply, oc);
1827 if ((status != ISC_R_SUCCESS) &&
1828 (status != ISC_R_NORESOURCES))
1836 if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
1837 if (reply.packet->dhcpv6_msg_type !=
1847 reply.packet->options,
1853 for (i = reply.packet->class_count; i > 0; i--) {
1856 reply.packet->options,
1859 reply.packet->classes[i - 1]->group,
1860 reply.shared->group, NULL);
1864 if (reply.host != NULL)
1867 reply.packet->options,
1871 reply.shared->group, NULL);
1906 reply.cursor +=
store_options6((
char *)reply.buf.data + reply.cursor,
1907 sizeof(reply.buf) - reply.cursor,
1908 reply.opt_state, reply.packet,
1909 required_opts_solicit,
1913 reply_ret->
len = reply.cursor;
1914 reply_ret->
buffer = NULL;
1918 memcpy(reply_ret->
buffer->
data, reply.buf.data, reply.cursor);
1926 if (reply.shared != NULL)
1927 shared_network_dereference(&reply.shared,
MDL);
1928 if (reply.host != NULL)
1929 host_dereference(&reply.host,
MDL);
1930 if (reply.opt_state != NULL)
1932 if (reply.packet != NULL)
1934 if (reply.client_id.data != NULL)
1936 if (packet_oro.buffer != NULL)
1938 reply.renew = reply.rebind = reply.min_prefer = reply.min_valid = 0;
1946 reply_process_ia_na(
struct reply_state *reply,
struct option_cache *ia) {
1947 isc_result_t status = ISC_R_SUCCESS;
1956 memset(&ia_data, 0,
sizeof(ia_data));
1963 if ((reply->cursor +
IA_NA_OFFSET + 4) >
sizeof(reply->buf)) {
1964 log_error(
"reply_process_ia_na: Reply too long for IA.");
1965 return ISC_R_NOSPACE;
1970 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
1972 log_error(
"reply_process_ia_na: error evaluating ia");
1973 status = ISC_R_FAILURE;
1979 reply->renew =
getULong(ia_data.data + 4);
1980 reply->rebind =
getULong(ia_data.data + 8);
1983 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
1984 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
1985 log_error(
"reply_process_ia_na: no memory for ia.");
1986 status = ISC_R_NOMEMORY;
1993 (
unsigned char *)reply->ia->iaid_duid.data,
1994 reply->ia->iaid_duid.len,
MDL);
2001 status = ISC_R_NOMEMORY;
2006 if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
2007 struct iaddr tmp_addr;
2011 reply->host->fixed_addr,
MDL)) {
2012 log_error(
"reply_process_ia_na: unable to evaluate " 2014 status = ISC_R_FAILURE;
2018 if (reply->fixed.len < 16) {
2019 log_error(
"reply_process_ia_na: invalid fixed address.");
2026 memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
2029 tmp_addr,
MDL) == 0)
2032 reply->static_lease = ISC_TRUE;
2034 reply->static_lease = ISC_FALSE;
2042 ia_cursor = reply->cursor;
2049 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
2053 putULong(reply->buf.data + reply->cursor, iaid);
2057 putULong(reply->buf.data + reply->cursor, reply->renew);
2061 putULong(reply->buf.data + reply->cursor, reply->rebind);
2074 reply->min_valid = reply->min_prefer = 0xffffffff;
2075 reply->client_valid = reply->client_prefer = 0;
2076 for (; oc != NULL ; oc = oc->
next) {
2077 status = reply_process_addr(reply, oc);
2085 if (status == ISC_R_CANCELED)
2088 if ((status != ISC_R_SUCCESS) &&
2089 (status != ISC_R_ADDRINUSE) &&
2090 (status != ISC_R_ADDRNOTAVAIL))
2100 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
2101 status = find_client_address(reply);
2103 if (status == ISC_R_NORESOURCES) {
2104 switch (reply->packet->dhcpv6_msg_type) {
2127 "memory for option state " 2129 status = ISC_R_NOMEMORY;
2134 "No addresses available " 2135 "for this interface.",
2137 log_error(
"reply_process_ia_na: Unable " 2138 "to set NoAddrsAvail status " 2140 status = ISC_R_FAILURE;
2144 status = ISC_R_SUCCESS;
2164 if (reply->resources_included)
2165 status = ISC_R_SUCCESS;
2172 if (status != ISC_R_SUCCESS)
2176 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2177 sizeof(reply->buf) - reply->cursor,
2178 reply->reply_ia, reply->packet,
2179 required_opts_IA, NULL);
2182 putUShort(reply->buf.data + ia_cursor + 2,
2183 reply->cursor - (ia_cursor + 4));
2186 set_reply_tee_times(reply, ia_cursor);
2192 if (status == ISC_R_CANCELED)
2199 if (reply->static_lease) {
2200 char tmp_addr[INET6_ADDRSTRLEN];
2201 log_info(
"%s NA: address %s to client with duid %s iaid = %d " 2204 inet_ntop(AF_INET6, reply->fixed.data, tmp_addr,
2207 reply->client_id.data, 60),
2211 (reply->on_star.on_commit != NULL)) {
2213 reply->packet->options,
2214 reply->opt_state, NULL,
2215 reply->on_star.on_commit, NULL);
2217 (&reply->on_star.on_commit,
MDL);
2225 if (reply->ia->num_iasubopt != 0) {
2228 char tmp_addr[INET6_ADDRSTRLEN];
2230 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2231 tmp = reply->ia->iasubopt[i];
2233 log_info(
"%s NA: address %s to client with duid %s " 2234 "iaid = %d valid for %u seconds",
2236 inet_ntop(AF_INET6, &tmp->
addr,
2237 tmp_addr,
sizeof(tmp_addr)),
2239 reply->client_id.data, 60),
2253 if ((reply->ia->num_iasubopt != 0) &&
2259 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2260 tmp = reply->ia->iasubopt[i];
2262 if (tmp->
ia != NULL)
2274 reply->packet->options,
2283 #if defined (NSUPDATE) 2292 reply->packet->options,
2297 tmp, NULL, reply->opt_state);
2301 check_pool6_threshold(reply, tmp);
2305 if (reply->old_ia != NULL) {
2306 ia_id = &reply->old_ia->iaid_duid;
2308 (
unsigned char *)ia_id->
data,
2315 ia_id = &reply->ia->iaid_duid;
2317 ia_id->
len, reply->ia,
MDL);
2321 schedule_lease_timeout_reply(reply);
2325 if (packet_ia != NULL)
2327 if (reply->reply_ia != NULL)
2329 if (ia_data.data != NULL)
2331 if (
data.data != NULL)
2333 if (reply->ia != NULL)
2335 if (reply->old_ia != NULL)
2337 if (reply->lease != NULL)
2339 if (reply->fixed.data != NULL)
2341 if (reply->subnet != NULL)
2342 subnet_dereference(&reply->subnet,
MDL);
2343 if (reply->on_star.on_expiry != NULL)
2345 (&reply->on_star.on_expiry,
MDL);
2346 if (reply->on_star.on_release != NULL)
2348 (&reply->on_star.on_release,
MDL);
2355 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2365 reply_process_addr(
struct reply_state *reply,
struct option_cache *addr) {
2366 u_int32_t pref_life, valid_life;
2370 struct iaddr tmp_addr;
2373 isc_result_t status = ISC_R_SUCCESS;
2376 memset(&iaaddr, 0,
sizeof(iaaddr));
2384 if ((reply->cursor + 28) >
sizeof(reply->buf)) {
2385 log_error(
"reply_process_addr: Out of room for address.");
2386 return ISC_R_NOSPACE;
2394 log_error(
"reply_process_addr: error evaluating IAADDR.");
2395 status = ISC_R_FAILURE;
2400 pref_life =
getULong(iaaddr.data + 16);
2401 valid_life =
getULong(iaaddr.data + 20);
2403 if ((reply->client_valid == 0) ||
2404 (reply->client_valid > valid_life))
2405 reply->client_valid = valid_life;
2407 if ((reply->client_prefer == 0) ||
2408 (reply->client_prefer > pref_life))
2409 reply->client_prefer = pref_life;
2416 memset(tmp_addr.iabuf, 0, 16);
2417 if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
2423 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2428 for (subnet = reply->shared->subnets ; subnet != NULL ;
2436 if (subnet == NULL) {
2461 log_error(
"reply_process_addr: No memory for " 2462 "option state wipe.");
2463 status = ISC_R_NOMEMORY;
2469 "Address not for use on this " 2470 "link.", reply->reply_ia)) {
2471 log_error(
"reply_process_addr: Failure " 2472 "setting status code.");
2473 status = ISC_R_FAILURE;
2478 status = ISC_R_CANCELED;
2490 if ((reply->packet->dhcpv6_msg_type !=
DHCPV6_RENEW) &&
2492 log_error(
"It is impossible to lease a client that is " 2493 "not sending a solicit, request, renew, or " 2495 status = ISC_R_FAILURE;
2499 reply->send_prefer = reply->send_valid = 0;
2504 if (!address_is_owned(reply, &tmp_addr)) {
2515 status = reply_process_try_addr(reply, &tmp_addr);
2522 if ((status != ISC_R_SUCCESS) &&
2523 (status != ISC_R_ADDRINUSE) &&
2524 (status != ISC_R_ADDRNOTAVAIL))
2532 if (reply->lease == NULL) {
2533 if (reply->packet->dhcpv6_msg_type ==
2535 reply->send_prefer = 0;
2536 reply->send_valid = 0;
2553 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
2557 log_error(
"reply_process_addr: No memory for " 2558 "option state wipe.");
2559 status = ISC_R_NOMEMORY;
2565 "Address not bound to this " 2566 "interface.", reply->reply_ia)) {
2567 log_error(
"reply_process_addr: Unable to " 2568 "attach status code.");
2569 status = ISC_R_FAILURE;
2574 status = ISC_R_CANCELED;
2577 log_error(
"It is impossible to lease a client that is " 2578 "not sending a solicit, request, renew, or " 2580 status = ISC_R_FAILURE;
2585 if (reply->static_lease) {
2586 if (reply->host == NULL)
2590 group = reply->subnet->group;
2592 if (reply->lease == NULL)
2595 scope = &reply->lease->scope;
2596 group = reply->lease->ipv6_pool->ipv6_pond->group;
2605 if (reply->client_resources != 0) {
2618 reply->packet->options,
2622 log_error(
"reply_process_addr: unable to " 2623 "evaluate addrs-per-ia value.");
2624 status = ISC_R_FAILURE;
2636 if (reply->client_resources >= limit)
2640 status = reply_process_is_addressed(reply, scope, group);
2641 if (status != ISC_R_SUCCESS)
2645 status = reply_process_send_addr(reply, &tmp_addr);
2648 if (iaaddr.data != NULL)
2650 if (
data.data != NULL)
2652 if (reply->lease != NULL)
2664 static isc_boolean_t
2665 address_is_owned(
struct reply_state *reply,
struct iaddr *addr) {
2672 if (reply->static_lease) {
2673 if (reply->fixed.data == NULL)
2676 if (memcmp(addr->
iabuf, reply->fixed.data, 16) == 0)
2682 if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
2685 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2688 tmp = reply->old_ia->iasubopt[i];
2690 if (memcmp(addr->
iabuf, &tmp->
addr, 16) == 0) {
2715 reply_process_ia_ta(
struct reply_state *reply,
struct option_cache *ia) {
2716 isc_result_t status = ISC_R_SUCCESS;
2723 u_int32_t pref_life, valid_life;
2724 struct iaddr tmp_addr;
2728 memset(&ia_data, 0,
sizeof(ia_data));
2729 memset(&data, 0,
sizeof(data));
2730 memset(&iaaddr, 0,
sizeof(iaaddr));
2733 if ((reply->cursor +
IA_TA_OFFSET + 4) >
sizeof(reply->buf)) {
2734 log_error(
"reply_process_ia_ta: Reply too long for IA.");
2735 return ISC_R_NOSPACE;
2740 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2742 log_error(
"reply_process_ia_ta: error evaluating ia");
2743 status = ISC_R_FAILURE;
2751 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
2752 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
2753 log_error(
"reply_process_ia_ta: no memory for ia.");
2754 status = ISC_R_NOMEMORY;
2761 (
unsigned char *)reply->ia->iaid_duid.data,
2762 reply->ia->iaid_duid.len,
MDL);
2769 status = ISC_R_NOMEMORY;
2776 reply->static_lease = ISC_FALSE;
2784 ia_cursor = reply->cursor;
2791 putUShort(reply->buf.data + reply->cursor, 0x04u);
2795 putULong(reply->buf.data + reply->cursor, iaid);
2802 reply->min_valid = reply->min_prefer = 0xffffffff;
2803 reply->client_valid = reply->client_prefer = 0;
2805 for (; oc != NULL; oc = oc->
next) {
2806 memset(&iaaddr, 0,
sizeof(iaaddr));
2809 reply->packet->options, NULL,
2813 "evaluating IAADDR.");
2814 status = ISC_R_FAILURE;
2818 pref_life =
getULong(iaaddr.data + 16);
2819 valid_life =
getULong(iaaddr.data + 20);
2821 if ((reply->client_valid == 0) ||
2822 (reply->client_valid > valid_life))
2823 reply->client_valid = valid_life;
2825 if ((reply->client_prefer == 0) ||
2826 (reply->client_prefer > pref_life))
2827 reply->client_prefer = pref_life;
2830 if (status == ISC_R_CANCELED)
2834 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2835 if (!temporary_is_available(reply, &tmp_addr))
2837 status = reply_process_is_addressed(reply,
2838 &reply->lease->scope,
2839 reply->lease->ipv6_pool->ipv6_pond->group);
2840 if (status != ISC_R_SUCCESS)
2842 status = reply_process_send_addr(reply, &tmp_addr);
2843 if (status != ISC_R_SUCCESS)
2845 if (reply->lease != NULL)
2853 status = ISC_R_NOMEMORY;
2856 status = ISC_R_CANCELED;
2857 reply->client_resources = 0;
2858 reply->resources_included = ISC_FALSE;
2859 if (reply->lease != NULL)
2867 if (reply->client_resources != 0)
2869 status = find_client_temporaries(reply);
2870 if (status == ISC_R_NORESOURCES) {
2871 switch (reply->packet->dhcpv6_msg_type) {
2892 "memory for option state wipe.");
2893 status = ISC_R_NOMEMORY;
2898 "No addresses available " 2899 "for this interface.",
2901 log_error(
"reply_process_ia_ta: Unable " 2902 "to set NoAddrsAvail status code.");
2903 status = ISC_R_FAILURE;
2907 status = ISC_R_SUCCESS;
2916 if (reply->resources_included)
2917 status = ISC_R_SUCCESS;
2922 }
else if (status != ISC_R_SUCCESS)
2926 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2927 sizeof(reply->buf) - reply->cursor,
2928 reply->reply_ia, reply->packet,
2929 required_opts_IA, NULL);
2932 putUShort(reply->buf.data + ia_cursor + 2,
2933 reply->cursor - (ia_cursor + 4));
2939 if (status == ISC_R_CANCELED)
2945 if (reply->ia->num_iasubopt != 0) {
2948 char tmp_addr[INET6_ADDRSTRLEN];
2950 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2951 tmp = reply->ia->iasubopt[i];
2953 log_info(
"%s TA: address %s to client with duid %s " 2954 "iaid = %d valid for %u seconds",
2956 inet_ntop(AF_INET6, &tmp->
addr,
2957 tmp_addr,
sizeof(tmp_addr)),
2959 reply->client_id.data, 60),
2973 if ((reply->ia->num_iasubopt != 0) &&
2979 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2980 tmp = reply->ia->iasubopt[i];
2982 if (tmp->
ia != NULL)
2994 reply->packet->options,
3003 #if defined (NSUPDATE) 3012 reply->packet->options,
3017 tmp, NULL, reply->opt_state);
3021 check_pool6_threshold(reply, tmp);
3025 if (reply->old_ia != NULL) {
3026 ia_id = &reply->old_ia->iaid_duid;
3028 (
unsigned char *)ia_id->
data,
3035 ia_id = &reply->ia->iaid_duid;
3037 ia_id->
len, reply->ia,
MDL);
3041 schedule_lease_timeout_reply(reply);
3045 if (packet_ia != NULL)
3047 if (iaaddr.data != NULL)
3049 if (reply->reply_ia != NULL)
3051 if (ia_data.data != NULL)
3053 if (
data.data != NULL)
3055 if (reply->ia != NULL)
3057 if (reply->old_ia != NULL)
3059 if (reply->lease != NULL)
3067 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
3073 static isc_boolean_t
3074 temporary_is_available(
struct reply_state *reply,
struct iaddr *addr) {
3075 struct in6_addr tmp_addr;
3076 struct subnet *subnet;
3081 memcpy(&tmp_addr, addr->
iabuf,
sizeof(tmp_addr));
3087 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
3093 for (subnet = reply->shared->subnets ; subnet != NULL ;
3107 if (address_is_owned(reply, addr))
3113 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3120 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
3136 if (iasubopt_allocate(&reply->lease,
MDL) != ISC_R_SUCCESS)
3138 reply->lease->addr = tmp_addr;
3139 reply->lease->plen = 0;
3151 find_client_temporaries(
struct reply_state *reply) {
3155 isc_result_t status = ISC_R_NORESOURCES;;
3156 unsigned int attempts;
3157 struct iaddr send_addr;
3163 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3167 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3177 log_debug(
"Unable to get client addresses: " 3178 "no IPv6 pools on this shared network");
3179 return ISC_R_NORESOURCES;
3189 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3196 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3205 &reply->client_id,
cur_time + 120);
3206 if (status != ISC_R_SUCCESS) {
3207 log_debug(
"Unable to get a temporary address.");
3211 status = reply_process_is_addressed(reply,
3212 &reply->lease->scope,
3214 if (status != ISC_R_SUCCESS) {
3218 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3219 status = reply_process_send_addr(reply, &send_addr);
3220 if (status != ISC_R_SUCCESS) {
3232 if (reply->lease != NULL) {
3243 reply_process_try_addr(
struct reply_state *reply,
struct iaddr *addr) {
3244 isc_result_t status = ISC_R_ADDRNOTAVAIL;
3250 if ((reply == NULL) || (reply->shared == NULL) ||
3251 (addr == NULL) || (reply->lease != NULL))
3258 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3262 for (i = 0; ; i++) {
3264 if ((pool == NULL) ||
3274 return (ISC_R_ADDRNOTAVAIL);
3277 memset(&data_addr, 0,
sizeof(data_addr));
3278 data_addr.len = addr->
len;
3279 data_addr.data = addr->
iabuf;
3292 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3299 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
3303 status = try_client_v6_address(&reply->lease, pool,
3305 if (status == ISC_R_SUCCESS)
3309 if (status == ISC_R_SUCCESS)
3324 find_client_address(
struct reply_state *reply) {
3325 struct iaddr send_addr;
3326 isc_result_t status = ISC_R_NORESOURCES;
3327 struct iasubopt *lease, *best_lease = NULL;
3329 struct group *group;
3332 if (reply->static_lease) {
3333 if (reply->host == NULL)
3337 memcpy(send_addr.iabuf, reply->fixed.data, 16);
3340 group = reply->subnet->group;
3344 if (reply->old_ia != NULL) {
3345 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
3349 lease = reply->old_ia->iasubopt[i];
3358 if ((candidate_shared != reply->shared) ||
3368 best_lease = lease_compare(lease, best_lease);
3376 status = pick_v6_address(reply);
3377 }
else if (best_lease != NULL) {
3379 status = ISC_R_SUCCESS;
3383 if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
3385 log_error(
"Best match for DUID %s is an abandoned address," 3386 " This may be a result of multiple clients attempting" 3387 " to use this DUID",
3389 reply->client_id.data, 60));
3394 if (status != ISC_R_SUCCESS)
3397 if (reply->lease == NULL)
3404 scope = &reply->lease->scope;
3405 group = reply->lease->ipv6_pool->ipv6_pond->group;
3408 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3411 status = reply_process_is_addressed(reply, scope, group);
3412 if (status != ISC_R_SUCCESS)
3415 status = reply_process_send_addr(reply, &send_addr);
3424 reply_process_is_addressed(
struct reply_state *reply,
3427 isc_result_t status = ISC_R_SUCCESS;
3435 memset(&data, 0,
sizeof(data));
3444 on_star = &reply->lease->on_star;
3446 on_star = &reply->on_star;
3456 reply->packet->options, tmp_options,
3459 if (tmp_options != NULL) {
3469 reply->packet->options, reply->opt_state,
3473 for (i = reply->packet->class_count; i > 0; i--) {
3475 reply->packet->options,
3476 reply->opt_state, scope,
3477 reply->packet->classes[i - 1]->group,
3486 if (reply->host != NULL)
3488 reply->packet->options,
3489 reply->opt_state, scope,
3490 reply->host->group, group,
3494 if (reply->client_valid == 0)
3497 reply->send_valid = reply->client_valid;
3503 reply->packet->options,
3507 log_error(
"reply_process_is_addressed: unable to " 3508 "evaluate default lease time");
3509 status = ISC_R_FAILURE;
3513 reply->send_valid =
getULong(data.data);
3522 if (reply->send_valid != 0xFFFFFFFF) {
3523 time_t test_time =
cur_time + reply->send_valid;
3525 reply->send_valid = 0xFFFFFFFF;
3528 if (reply->client_prefer == 0)
3529 reply->send_prefer = reply->send_valid;
3531 reply->send_prefer = reply->client_prefer;
3533 if ((reply->send_prefer >= reply->send_valid) &&
3534 (reply->send_valid != 0xFFFFFFFF))
3535 reply->send_prefer = (reply->send_valid / 2) +
3536 (reply->send_valid / 8);
3542 reply->packet->options,
3546 log_error(
"reply_process_is_addressed: unable to " 3547 "evaluate preferred lease time");
3548 status = ISC_R_FAILURE;
3552 reply->send_prefer =
getULong(data.data);
3557 if (reply->min_prefer > reply->send_prefer)
3558 reply->min_prefer = reply->send_prefer;
3560 if (reply->min_valid > reply->send_valid)
3561 reply->min_valid = reply->send_valid;
3573 if (reply->host != NULL)
3575 reply->client_id->len);
3579 if (reply->lease != NULL) {
3581 reply->lease->prefer = reply->send_prefer;
3582 reply->lease->valid = reply->send_valid;
3589 if (reply->send_valid == 0xFFFFFFFF) {
3590 reply->lease->soft_lifetime_end_time =
MAX_TIME;
3592 reply->lease->soft_lifetime_end_time =
3599 if (status != ISC_R_SUCCESS) {
3600 log_fatal(
"reply_process_is_addressed: Unable to " 3601 "attach lease to new IA: %s",
3602 isc_result_totext(status));
3608 if (reply->lease->ia == NULL) {
3615 reply->packet->options, reply->reply_ia,
3619 for (i = reply->packet->class_count; i > 0; i--) {
3621 reply->packet->options,
3622 reply->reply_ia, scope,
3623 reply->packet->classes[i - 1]->group,
3631 if (reply->host != NULL)
3633 reply->packet->options,
3634 reply->reply_ia, scope,
3635 reply->host->group, group, NULL);
3638 if (data.data != NULL)
3641 if (status == ISC_R_SUCCESS)
3642 reply->client_resources++;
3649 reply_process_send_addr(
struct reply_state *reply,
struct iaddr *addr) {
3650 isc_result_t status = ISC_R_SUCCESS;
3658 log_error(
"reply_process_send_addr: out of memory" 3659 "allocating new IAADDR buffer.");
3660 status = ISC_R_NOMEMORY;
3665 memcpy(
data.buffer->data, addr->
iabuf, 16);
3672 log_error(
"reply_process_send_addr: unable " 3673 "to save IAADDR option");
3674 status = ISC_R_FAILURE;
3678 reply->resources_included = ISC_TRUE;
3681 if (
data.data != NULL)
3695 switch(alpha->
state) {
3697 switch(beta->
state) {
3718 switch (beta->
state) {
3744 switch (beta->
state) {
3766 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
3774 reply_process_ia_pd(
struct reply_state *reply,
struct option_cache *ia) {
3775 isc_result_t status = ISC_R_SUCCESS;
3784 memset(&ia_data, 0,
sizeof(ia_data));
3791 if ((reply->cursor +
IA_PD_OFFSET + 4) >
sizeof(reply->buf)) {
3792 log_error(
"reply_process_ia_pd: Reply too long for IA.");
3793 return ISC_R_NOSPACE;
3798 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
3800 log_error(
"reply_process_ia_pd: error evaluating ia");
3801 status = ISC_R_FAILURE;
3807 reply->renew =
getULong(ia_data.data + 4);
3808 reply->rebind =
getULong(ia_data.data + 8);
3811 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
3812 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
3813 log_error(
"reply_process_ia_pd: no memory for ia.");
3814 status = ISC_R_NOMEMORY;
3821 (
unsigned char *)reply->ia->iaid_duid.data,
3822 reply->ia->iaid_duid.len,
MDL);
3829 status = ISC_R_NOMEMORY;
3834 reply->static_prefixes = 0;
3835 if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
3838 for (fp = reply->host->fixed_prefix; fp != NULL;
3840 reply->static_prefixes += 1;
3850 ia_cursor = reply->cursor;
3857 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
3861 putULong(reply->buf.data + reply->cursor, iaid);
3865 putULong(reply->buf.data + reply->cursor, reply->renew);
3869 putULong(reply->buf.data + reply->cursor, reply->rebind);
3876 reply->min_valid = reply->min_prefer = 0xffffffff;
3877 reply->client_valid = reply->client_prefer = 0;
3878 reply->preflen = -1;
3879 for (; oc != NULL ; oc = oc->
next) {
3880 status = reply_process_prefix(reply, oc);
3888 if (status == ISC_R_CANCELED)
3891 if ((status != ISC_R_SUCCESS) &&
3892 (status != ISC_R_ADDRINUSE) &&
3893 (status != ISC_R_ADDRNOTAVAIL))
3903 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
3904 status = find_client_prefix(reply);
3906 if (status == ISC_R_NORESOURCES) {
3907 switch (reply->packet->dhcpv6_msg_type) {
3922 "memory for option state " 3924 status = ISC_R_NOMEMORY;
3929 "No prefixes available " 3930 "for this interface.",
3934 "NoPrefixAvail status " 3936 status = ISC_R_FAILURE;
3940 status = ISC_R_SUCCESS;
3944 if (reply->resources_included)
3945 status = ISC_R_SUCCESS;
3952 if (status != ISC_R_SUCCESS)
3956 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
3957 sizeof(reply->buf) - reply->cursor,
3958 reply->reply_ia, reply->packet,
3959 required_opts_IA_PD, NULL);
3962 putUShort(reply->buf.data + ia_cursor + 2,
3963 reply->cursor - (ia_cursor + 4));
3966 set_reply_tee_times(reply, ia_cursor);
3972 if (status == ISC_R_CANCELED)
3979 if (reply->static_prefixes != 0) {
3980 char tmp_addr[INET6_ADDRSTRLEN];
3981 log_info(
"%s PD: address %s/%d to client with duid %s " 3984 inet_ntop(AF_INET6, reply->fixed_pref.lo_addr.iabuf,
3985 tmp_addr,
sizeof(tmp_addr)),
3986 reply->fixed_pref.bits,
3988 reply->client_id.data, 60),
3991 (reply->on_star.on_commit != NULL)) {
3993 reply->packet->options,
3995 NULL, reply->on_star.on_commit,
3998 (&reply->on_star.on_commit,
MDL);
4006 if (reply->ia->num_iasubopt != 0) {
4009 char tmp_addr[INET6_ADDRSTRLEN];
4011 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
4012 tmp = reply->ia->iasubopt[i];
4014 log_info(
"%s PD: address %s/%d to client with duid %s" 4015 " iaid = %d valid for %u seconds",
4017 inet_ntop(AF_INET6, &tmp->
addr,
4018 tmp_addr,
sizeof(tmp_addr)),
4021 reply->client_id.data, 60),
4035 (reply->ia->num_iasubopt != 0)) {
4040 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
4041 tmp = reply->ia->iasubopt[i];
4043 if (tmp->
ia != NULL)
4055 reply->packet->options,
4065 check_pool6_threshold(reply, tmp);
4069 if (reply->old_ia != NULL) {
4070 ia_id = &reply->old_ia->iaid_duid;
4072 (
unsigned char *)ia_id->
data,
4079 ia_id = &reply->ia->iaid_duid;
4081 ia_id->
len, reply->ia,
MDL);
4085 schedule_lease_timeout_reply(reply);
4089 if (packet_ia != NULL)
4091 if (reply->reply_ia != NULL)
4093 if (ia_data.data != NULL)
4095 if (
data.data != NULL)
4097 if (reply->ia != NULL)
4099 if (reply->old_ia != NULL)
4101 if (reply->lease != NULL)
4103 if (reply->on_star.on_expiry != NULL)
4105 (&reply->on_star.on_expiry,
MDL);
4106 if (reply->on_star.on_release != NULL)
4108 (&reply->on_star.on_release,
MDL);
4115 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
4137 static struct group *
4138 find_group_by_prefix(
struct reply_state *reply) {
4140 struct group *group = reply->shared->group;
4141 struct subnet *subnet = NULL;
4142 struct iaddr tmp_addr;
4147 reply->fixed_pref.lo_addr,
MDL) != 0) {
4148 group = subnet->
group;
4149 subnet_dereference(&subnet,
MDL);
4156 memset(&fixed_addr, 0,
sizeof(fixed_addr));
4158 if ((reply->host->fixed_addr != NULL) &&
4161 reply->host->fixed_addr,
MDL))) {
4162 if (fixed_addr.len >= 16) {
4164 memcpy(tmp_addr.iabuf, fixed_addr.data, 16);
4166 tmp_addr,
MDL) != 0) {
4167 group = subnet->
group;
4168 subnet_dereference(&subnet,
MDL);
4185 reply_process_prefix(
struct reply_state *reply,
struct option_cache *pref) {
4186 u_int32_t pref_life, valid_life;
4191 isc_result_t status = ISC_R_SUCCESS;
4192 struct group *group;
4195 memset(&iapref, 0,
sizeof(iapref));
4196 memset(&data, 0,
sizeof(data));
4203 if ((reply->cursor + 29) >
sizeof(reply->buf)) {
4204 log_error(
"reply_process_prefix: Out of room for prefix.");
4205 return ISC_R_NOSPACE;
4213 log_error(
"reply_process_prefix: error evaluating IAPREFIX.");
4214 status = ISC_R_FAILURE;
4223 valid_life =
getULong(iapref.data + 4);
4225 if ((reply->client_valid == 0) ||
4226 (reply->client_valid > valid_life))
4227 reply->client_valid = valid_life;
4229 if ((reply->client_prefer == 0) ||
4230 (reply->client_prefer > pref_life))
4231 reply->client_prefer = pref_life;
4237 tmp_pref.lo_addr.len = 16;
4238 memset(tmp_pref.lo_addr.iabuf, 0, 16);
4239 if ((iapref.data[8] == 0) &&
4240 (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
4249 tmp_pref.bits = (
int) iapref.data[8];
4250 if (reply->preflen < 0) {
4252 reply->preflen = tmp_pref.bits;
4254 if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
4258 memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
4261 if (!prefix_is_owned(reply, &tmp_pref)) {
4266 status = reply_process_try_prefix(reply, &tmp_pref);
4269 if ((status != ISC_R_SUCCESS) &&
4270 (status != ISC_R_ADDRINUSE) &&
4271 (status != ISC_R_ADDRNOTAVAIL))
4274 if (reply->lease == NULL) {
4275 if (reply->packet->dhcpv6_msg_type ==
4277 reply->send_prefer = 0;
4278 reply->send_valid = 0;
4297 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
4301 log_error(
"reply_process_prefix: No memory " 4302 "for option state wipe.");
4303 status = ISC_R_NOMEMORY;
4309 "Prefix not bound to this " 4310 "interface.", reply->reply_ia)) {
4311 log_error(
"reply_process_prefix: Unable to " 4312 "attach status code.");
4313 status = ISC_R_FAILURE;
4318 status = ISC_R_CANCELED;
4321 log_error(
"It is impossible to lease a client that is " 4322 "not sending a solicit, request, renew, or " 4324 status = ISC_R_FAILURE;
4329 if (reply->static_prefixes > 0) {
4330 if (reply->host == NULL)
4336 memcpy(&reply->fixed_pref, &tmp_pref,
sizeof(tmp_pref));
4339 group = find_group_by_prefix(reply);
4341 if (reply->lease == NULL)
4344 scope = &reply->lease->scope;
4345 group = reply->lease->ipv6_pool->ipv6_pond->group;
4354 if (reply->client_resources != 0) {
4367 reply->packet->options,
4371 log_error(
"reply_process_prefix: unable to " 4372 "evaluate prefs-per-ia value.");
4373 status = ISC_R_FAILURE;
4385 if (reply->client_resources >= limit)
4389 status = reply_process_is_prefixed(reply, scope, group);
4390 if (status != ISC_R_SUCCESS)
4394 status = reply_process_send_prefix(reply, &tmp_pref);
4397 if (iapref.data != NULL)
4399 if (data.data != NULL)
4401 if (reply->lease != NULL)
4413 static isc_boolean_t
4414 prefix_is_owned(
struct reply_state *reply,
struct iaddrcidrnet *pref) {
4422 if (reply->static_prefixes > 0) {
4423 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4432 if ((reply->old_ia == NULL) ||
4433 (reply->old_ia->num_iasubopt == 0))
4436 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4439 tmp = reply->old_ia->iasubopt[i];
4441 if ((pref->
bits == (
int) tmp->
plen) &&
4467 reply_process_try_prefix(
struct reply_state *reply,
4469 isc_result_t status = ISC_R_ADDRNOTAVAIL;
4475 if ((reply == NULL) || (reply->shared == NULL) ||
4476 (pref == NULL) || (reply->lease != NULL))
4483 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4487 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4497 return (ISC_R_ADDRNOTAVAIL);
4500 memset(&data_pref, 0,
sizeof(data_pref));
4503 log_error(
"reply_process_try_prefix: out of memory.");
4504 return (ISC_R_NOMEMORY);
4506 data_pref.data = data_pref.buffer->data;
4507 data_pref.buffer->data[0] = (u_int8_t) pref->
bits;
4508 memcpy(data_pref.buffer->data + 1, pref->
lo_addr.
iabuf, 16);
4518 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4525 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4530 status = try_client_v6_prefix(&reply->lease, pool,
4534 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4537 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4551 find_client_prefix(
struct reply_state *reply) {
4553 isc_result_t status = ISC_R_NORESOURCES;
4554 struct iasubopt *prefix, *best_prefix = NULL;
4557 struct group *group;
4559 if (reply->static_prefixes > 0) {
4562 if (reply->host == NULL)
4565 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4574 l = reply->host->fixed_prefix;
4576 memcpy(&send_pref, &l->
cidrnet,
sizeof(send_pref));
4581 memcpy(&reply->fixed_pref, &l->
cidrnet,
sizeof(send_pref));
4584 group = find_group_by_prefix(reply);
4589 if (reply->old_ia != NULL) {
4590 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4594 prefix = reply->old_ia->iasubopt[i];
4603 if (((candidate_shared != NULL) &&
4604 (candidate_shared != reply->shared)) ||
4618 best_prefix = prefix_compare(reply, prefix,
4627 status = pick_v6_prefix(reply);
4628 }
else if (best_prefix != NULL) {
4630 status = ISC_R_SUCCESS;
4634 if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
4636 log_error(
"Reclaiming abandoned prefixes is not yet " 4637 "supported. Treating this as an out of space " 4643 if (status != ISC_R_SUCCESS)
4646 if (reply->lease == NULL)
4649 scope = &reply->lease->scope;
4650 group = reply->lease->ipv6_pool->ipv6_pond->group;
4652 send_pref.lo_addr.len = 16;
4653 memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
4654 send_pref.bits = (
int) reply->lease->plen;
4657 status = reply_process_is_prefixed(reply, scope, group);
4658 if (status != ISC_R_SUCCESS)
4661 status = reply_process_send_prefix(reply, &send_pref);
4670 reply_process_is_prefixed(
struct reply_state *reply,
4673 isc_result_t status = ISC_R_SUCCESS;
4677 struct on_star *on_star;
4681 memset(&data, 0,
sizeof(data));
4690 on_star = &reply->lease->on_star;
4692 on_star = &reply->on_star;
4702 reply->packet->options, tmp_options,
4705 if (tmp_options != NULL) {
4715 reply->packet->options, reply->opt_state,
4719 for (i = reply->packet->class_count; i > 0; i--) {
4721 reply->packet->options,
4722 reply->opt_state, scope,
4723 reply->packet->classes[i - 1]->group,
4732 if (reply->host != NULL)
4734 reply->packet->options,
4735 reply->opt_state, scope,
4736 reply->host->group, group,
4740 if (reply->client_valid == 0)
4743 reply->send_valid = reply->client_valid;
4749 reply->packet->options,
4753 log_error(
"reply_process_is_prefixed: unable to " 4754 "evaluate default prefix time");
4755 status = ISC_R_FAILURE;
4759 reply->send_valid =
getULong(data.data);
4768 if (reply->send_valid != 0xFFFFFFFF) {
4769 time_t test_time =
cur_time + reply->send_valid;
4771 reply->send_valid = 0xFFFFFFFF;
4774 if (reply->client_prefer == 0)
4775 reply->send_prefer = reply->send_valid;
4777 reply->send_prefer = reply->client_prefer;
4779 if ((reply->send_prefer >= reply->send_valid) &&
4780 (reply->send_valid != 0xFFFFFFFF))
4781 reply->send_prefer = (reply->send_valid / 2) +
4782 (reply->send_valid / 8);
4788 reply->packet->options,
4792 log_error(
"reply_process_is_prefixed: unable to " 4793 "evaluate preferred prefix time");
4794 status = ISC_R_FAILURE;
4798 reply->send_prefer =
getULong(data.data);
4803 if (reply->min_prefer > reply->send_prefer)
4804 reply->min_prefer = reply->send_prefer;
4806 if (reply->min_valid > reply->send_valid)
4807 reply->min_valid = reply->send_valid;
4810 if (reply->lease != NULL) {
4812 reply->lease->prefer = reply->send_prefer;
4813 reply->lease->valid = reply->send_valid;
4820 if (reply->send_valid == 0xFFFFFFFF) {
4821 reply->lease->soft_lifetime_end_time =
MAX_TIME;
4823 reply->lease->soft_lifetime_end_time =
4830 if (status != ISC_R_SUCCESS) {
4831 log_fatal(
"reply_process_is_prefixed: Unable to " 4832 "attach prefix to new IA_PD: %s",
4833 isc_result_totext(status));
4839 if (reply->lease->ia == NULL) {
4846 reply->packet->options, reply->reply_ia,
4850 for (i = reply->packet->class_count; i > 0; i--) {
4852 reply->packet->options,
4853 reply->reply_ia, scope,
4854 reply->packet->classes[i - 1]->group,
4862 if (reply->host != NULL)
4864 reply->packet->options,
4865 reply->reply_ia, scope,
4866 reply->host->group, group, NULL);
4869 if (data.data != NULL)
4872 if (status == ISC_R_SUCCESS)
4873 reply->client_resources++;
4880 reply_process_send_prefix(
struct reply_state *reply,
4882 isc_result_t status = ISC_R_SUCCESS;
4890 log_error(
"reply_process_send_prefix: out of memory" 4891 "allocating new IAPREFIX buffer.");
4892 status = ISC_R_NOMEMORY;
4905 log_error(
"reply_process_send_prefix: unable " 4906 "to save IAPREFIX option");
4907 status = ISC_R_FAILURE;
4911 reply->resources_included = ISC_TRUE;
4914 if (
data.data != NULL)
4922 prefix_compare(
struct reply_state *reply,
4929 if (reply->preflen >= 0) {
4930 if ((alpha->
plen == reply->preflen) &&
4931 (beta->
plen != reply->preflen))
4933 if ((beta->
plen == reply->preflen) &&
4934 (alpha->
plen != reply->preflen))
4938 switch(alpha->
state) {
4940 switch(beta->
state) {
4961 switch (beta->
state) {
4987 switch (beta->
state) {
5009 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
5023 dhcpv6_solicit(
struct data_string *reply_ret,
struct packet *packet) {
5029 if (!valid_client_msg(packet, &client_id)) {
5033 lease_to_client(reply_ret, packet, &client_id, NULL);
5048 dhcpv6_request(
struct data_string *reply_ret,
struct packet *packet) {
5055 if (!valid_client_resp(packet, &client_id, &server_id)) {
5061 if (packet->
unicast == ISC_TRUE &&
5062 is_unicast_option_defined(packet) == ISC_FALSE) {
5063 unicast_reject(reply_ret, packet, &client_id, &server_id);
5068 lease_to_client(reply_ret, packet, &client_id, &server_id);
5082 struct packet *packet)
5084 const struct packet *chk_packet;
5085 const struct in6_addr *link_addr, *first_link_addr;
5086 struct iaddr tmp_addr;
5087 struct subnet *subnet;
5088 isc_result_t status;
5090 if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
5097 first_link_addr = NULL;
5099 while (chk_packet != NULL) {
5101 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
5102 !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
5103 first_link_addr = link_addr;
5114 if (first_link_addr != NULL) {
5115 tmp_addr.len =
sizeof(*first_link_addr);
5116 memcpy(tmp_addr.iabuf,
5117 first_link_addr,
sizeof(*first_link_addr));
5120 log_debug(
"No subnet found for link-address %s.",
5122 return ISC_R_NOTFOUND;
5124 status = shared_network_reference(shared,
5126 subnet_dereference(&subnet,
MDL);
5133 status = shared_network_reference(shared,
5137 log_info(
"[L2 Relay] No link address in relay packet " 5138 "assuming L2 relay and using receiving " 5148 log_error(
"No interface and no link address " 5149 "can't determine pool");
5175 dhcpv6_confirm(
struct data_string *reply_ret,
struct packet *packet) {
5177 struct subnet *subnet;
5179 struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
5181 struct iaddr cli_addr;
5183 isc_boolean_t inappropriate, has_addrs;
5184 char reply_data[65536];
5191 memset(&client_id, 0,
sizeof(client_id));
5192 if (!valid_client_msg(packet, &client_id)) {
5201 if ((ia == NULL) && (ta == NULL))
5212 opt_state = cli_enc_opt_state = NULL;
5213 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5214 memset(&iaaddr, 0,
sizeof(iaaddr));
5215 memset(&packet_oro, 0,
sizeof(packet_oro));
5222 if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
5234 has_addrs = inappropriate = ISC_FALSE;
5236 while(!inappropriate) {
5240 if ((pass ==
D6O_IA_NA) && (ia == NULL)) {
5250 !get_encapsulated_IA_state(&cli_enc_opt_state,
5254 !get_encapsulated_IA_state(&cli_enc_opt_state,
5263 for ( ; oc != NULL ; oc = oc->
next) {
5269 "error evaluating IAADDR.");
5275 memcpy(cli_addr.iabuf, iaaddr.data, 16);
5280 has_addrs = ISC_TRUE;
5283 for (subnet = shared->
subnets ; subnet != NULL ;
5298 if (subnet == NULL) {
5299 inappropriate = ISC_TRUE;
5318 if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
5325 if (inappropriate) {
5327 "Some of the addresses are not on link.",
5333 "All addresses still on link.",
5343 sizeof(reply_data)-reply_ofs,
5345 required_opts, &packet_oro);
5350 reply_ret->
len = reply_ofs;
5351 reply_ret->
buffer = NULL;
5356 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5360 if (cli_enc_opt_data.buffer != NULL)
5362 if (iaaddr.buffer != NULL)
5364 if (client_id.
buffer != NULL)
5366 if (packet_oro.buffer != NULL)
5370 if (cli_enc_opt_state != NULL)
5372 if (opt_state != NULL)
5384 dhcpv6_renew(
struct data_string *reply,
struct packet *packet) {
5391 if (!valid_client_resp(packet, &client_id, &server_id)) {
5397 if (packet->
unicast == ISC_TRUE &&
5398 is_unicast_option_defined(packet) == ISC_FALSE) {
5399 unicast_reject(reply, packet, &client_id, &server_id);
5404 lease_to_client(reply, packet, &client_id, &server_id);
5422 dhcpv6_rebind(
struct data_string *reply,
struct packet *packet) {
5425 if (!valid_client_msg(packet, &client_id)) {
5429 lease_to_client(reply, packet, &client_id, NULL);
5435 ia_na_match_decline(
const struct data_string *client_id,
5439 char tmp_addr[INET6_ADDRSTRLEN];
5441 log_error(
"Client %s reports address %s is " 5442 "already in use by another host!",
5444 inet_ntop(AF_INET6, iaaddr->
data,
5445 tmp_addr,
sizeof(tmp_addr)));
5446 if (lease != NULL) {
5454 ia_na_nomatch_decline(
const struct data_string *client_id,
5456 u_int32_t *ia_na_id,
5457 struct packet *packet,
5462 char tmp_addr[INET6_ADDRSTRLEN];
5466 log_info(
"Client %s declines address %s, which is not offered to it.",
5468 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5473 host_opt_state = NULL;
5475 log_error(
"ia_na_nomatch_decline: out of memory " 5476 "allocating option_state.");
5488 if (reply_len < (*reply_ofs + 16)) {
5490 "out of space for reply packet.");
5498 reply_len-(*reply_ofs)-16,
5499 host_opt_state, packet,
5500 required_opts_STATUS_CODE, NULL);
5510 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5512 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5514 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5515 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5520 *reply_ofs += (len + 16);
5528 struct packet *packet,
5531 const char *packet_type,
5532 void (*ia_na_match)(),
5533 void (*ia_na_nomatch)())
5545 char reply_data[65536];
5548 char status_msg[32];
5550 struct ia_xx *existing_ia_na;
5559 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5560 cli_enc_opt_state = NULL;
5561 memset(&iaaddr, 0,
sizeof(iaaddr));
5562 memset(&fixed_addr, 0,
sizeof(fixed_addr));
5583 log_error(
"iterate_over_ia_na: no memory for option_state.");
5596 (
unsigned char *)server_duid.data,
5599 "error saving server identifier.");
5606 (
unsigned char *)client_id->
data,
5610 "error saving client identifier.");
5614 snprintf(status_msg,
sizeof(status_msg),
"%s received.", packet_type);
5623 sizeof(reply_data)-reply_ofs,
5625 required_opts, NULL);
5632 ia != NULL; ia = ia->
next) {
5634 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5640 iaid =
getULong(cli_enc_opt_data.data);
5658 memset(&iaaddr, 0,
sizeof(iaaddr));
5663 "error evaluating IAADDR.");
5677 cli_enc_opt_state,
MDL)) {
5678 if (packet_host != NULL) {
5684 while (host != NULL) {
5692 "evaluating host address.");
5695 if ((iaaddr.
len >= 16) &&
5696 !memcmp(fixed_addr.data, iaaddr.
data, 16)) {
5710 (
char *)client_id->
data,
5712 MDL) != ISC_R_SUCCESS) {
5713 log_fatal(
"iterate_over_ia_na: no memory for " 5717 existing_ia_na = NULL;
5719 (
unsigned char *)key.data,
5726 struct in6_addr *in6_addr;
5729 in6_addr = &tmp->
addr;
5730 if (memcmp(in6_addr,
5731 iaaddr.
data, 16) == 0) {
5742 if ((host != NULL) || (lease != NULL)) {
5743 ia_na_match(client_id, &iaaddr, lease);
5745 ia_na_nomatch(client_id, &iaaddr,
5746 (u_int32_t *)cli_enc_opt_data.
data,
5747 packet, reply_data, &reply_ofs,
5748 sizeof(reply_data));
5751 if (lease != NULL) {
5763 reply_ret->
len = reply_ofs;
5764 reply_ret->
buffer = NULL;
5769 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5772 if (lease != NULL) {
5775 if (fixed_addr.buffer != NULL) {
5778 if (iaaddr.
buffer != NULL) {
5781 if (cli_enc_opt_state != NULL) {
5784 if (cli_enc_opt_data.buffer != NULL) {
5787 if (opt_state != NULL) {
5807 dhcpv6_decline(
struct data_string *reply,
struct packet *packet) {
5814 if (!valid_client_resp(packet, &client_id, &server_id)) {
5820 if (packet->
unicast == ISC_TRUE &&
5821 is_unicast_option_defined(packet) == ISC_FALSE) {
5822 unicast_reject(reply, packet, &client_id, &server_id);
5832 iterate_over_ia_na(reply, packet, &client_id, &server_id,
5833 "Decline", ia_na_match_decline,
5834 ia_na_nomatch_decline);
5843 ia_na_match_release(
const struct data_string *client_id,
5847 char tmp_addr[INET6_ADDRSTRLEN];
5849 log_info(
"Client %s releases address %s",
5851 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5852 if (lease != NULL) {
5860 ia_na_nomatch_release(
const struct data_string *client_id,
5862 u_int32_t *ia_na_id,
5863 struct packet *packet,
5868 char tmp_addr[INET6_ADDRSTRLEN];
5872 log_info(
"Client %s releases address %s, which is not leased to it.",
5874 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5879 host_opt_state = NULL;
5881 log_error(
"ia_na_nomatch_release: out of memory " 5882 "allocating option_state.");
5887 "Release for non-leased address.",
5895 if (reply_len < (*reply_ofs + 16)) {
5897 "out of space for reply packet.");
5905 reply_len-(*reply_ofs)-16,
5906 host_opt_state, packet,
5907 required_opts_STATUS_CODE, NULL);
5917 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5919 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5921 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5922 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5927 *reply_ofs += (len + 16);
5934 ia_pd_match_release(
const struct data_string *client_id,
5938 char tmp_addr[INET6_ADDRSTRLEN];
5940 log_info(
"Client %s releases prefix %s/%u",
5942 inet_ntop(AF_INET6, iapref->
data + 9,
5943 tmp_addr,
sizeof(tmp_addr)),
5945 if (prefix != NULL) {
5953 ia_pd_nomatch_release(
const struct data_string *client_id,
5955 u_int32_t *ia_pd_id,
5956 struct packet *packet,
5961 char tmp_addr[INET6_ADDRSTRLEN];
5965 log_info(
"Client %s releases prefix %s/%u, which is not leased to it.",
5967 inet_ntop(AF_INET6, iapref->
data + 9,
5968 tmp_addr,
sizeof(tmp_addr)),
5974 host_opt_state = NULL;
5976 log_error(
"ia_pd_nomatch_release: out of memory " 5977 "allocating option_state.");
5982 "Release for non-leased prefix.",
5990 if (reply_len < (*reply_ofs + 16)) {
5992 "out of space for reply packet.");
6000 reply_len-(*reply_ofs)-16,
6001 host_opt_state, packet,
6002 required_opts_STATUS_CODE, NULL);
6012 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
6014 memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
6016 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
6017 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
6022 *reply_ofs += (len + 16);
6030 struct packet *packet,
6033 const char *packet_type,
6034 void (*ia_pd_match)(),
6035 void (*ia_pd_nomatch)())
6048 char reply_data[65536];
6051 struct ia_xx *existing_ia_pd;
6059 memset(&reply_new, 0,
sizeof(reply_new));
6061 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
6062 cli_enc_opt_state = NULL;
6063 memset(&iaprefix, 0,
sizeof(iaprefix));
6069 reply_len =
sizeof(reply_data) - reply_ret->
len;
6083 log_error(
"iterate_over_ia_pd: no memory for option_state.");
6095 ia != NULL; ia = ia->
next) {
6097 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
6103 iaid =
getULong(cli_enc_opt_data.data);
6114 for (; oc != NULL; oc = oc->
next) {
6115 memset(&iaprefix, 0,
sizeof(iaprefix));
6120 "error evaluating IAPREFIX.");
6134 cli_enc_opt_state,
MDL)) {
6135 if (packet_host != NULL) {
6141 while (host != NULL) {
6150 if (memcmp(iaprefix.data + 9,
6155 if ((l != NULL) && (iaprefix.len >= 17))
6166 (
char *)client_id->
data,
6168 MDL) != ISC_R_SUCCESS) {
6169 log_fatal(
"iterate_over_ia_pd: no memory for " 6173 existing_ia_pd = NULL;
6175 (
unsigned char *)key.data,
6186 plen =
getUChar(iaprefix.data + 8);
6188 if ((tmp->
plen == plen) &&
6202 if ((host != NULL) || (prefix != NULL)) {
6203 ia_pd_match(client_id, &iaprefix, prefix);
6205 ia_pd_nomatch(client_id, &iaprefix,
6206 (u_int32_t *)cli_enc_opt_data.
data,
6207 packet, reply_data, &reply_ofs,
6208 reply_len - reply_ofs);
6211 if (prefix != NULL) {
6226 reply_new.len = reply_ret->
len + reply_ofs;
6230 reply_new.data = reply_new.buffer->data;
6231 memcpy(reply_new.buffer->data,
6233 memcpy(reply_new.buffer->data + reply_ret->
len,
6234 reply_data, reply_ofs);
6240 if (prefix != NULL) {
6243 if (iaprefix.buffer != NULL) {
6246 if (cli_enc_opt_state != NULL) {
6249 if (cli_enc_opt_data.buffer != NULL) {
6252 if (opt_state != NULL) {
6262 dhcpv6_release(
struct data_string *reply,
struct packet *packet) {
6269 if (!valid_client_resp(packet, &client_id, &server_id)) {
6275 if (packet->
unicast == ISC_TRUE &&
6276 is_unicast_option_defined(packet) == ISC_FALSE) {
6277 unicast_reject(reply, packet, &client_id, &server_id);
6282 iterate_over_ia_na(reply, packet, &client_id, &server_id,
6283 "Release", ia_na_match_release,
6284 ia_na_nomatch_release);
6289 iterate_over_ia_pd(reply, packet, &client_id, &server_id,
6290 "Release", ia_pd_match_release,
6291 ia_pd_nomatch_release);
6304 dhcpv6_information_request(
struct data_string *reply,
struct packet *packet) {
6311 if (!valid_client_info_req(packet, &server_id)) {
6318 memset(&client_id, 0,
sizeof(client_id));
6329 lease_to_client(reply, packet, &client_id,
6330 server_id.
data != NULL ? &server_id : NULL);
6335 if (client_id.
data != NULL) {
6352 dhcpv6_relay_forw(
struct data_string *reply_ret,
struct packet *packet) {
6355 struct packet *enc_packet;
6356 unsigned char msg_type;
6360 char link_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6361 char peer_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6364 static char reply_data[65536];
6372 memset(&a_opt, 0,
sizeof(a_opt));
6373 memset(&packet_ero, 0,
sizeof(packet_ero));
6374 memset(&enc_reply, 0,
sizeof(enc_reply));
6375 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6384 link_addr,
sizeof(link_addr));
6386 peer_addr,
sizeof(peer_addr));
6387 log_info(
"Relay-forward from %s with link address=%s and " 6388 "peer address=%s missing Relay Message option.",
6396 log_error(
"dhcpv6_forw_relay: error evaluating " 6397 "relayed message.");
6403 log_error(
"dhcpv6_forw_relay: encapsulated packet too short.");
6414 "no memory for encapsulated packet.");
6421 "no memory for encapsulated packet's options.");
6430 msg_type = enc_opt_data.
data[0];
6446 enc_opt_data.
len - relaylen,
6458 "unsupported %s message type.",
6462 forw_dhcpv4_query(packet);
6465 log_error(
"dhcpv6_relay_forw: unsupported %s message type.",
6481 enc_opt_data.
len - msglen,
6493 build_dhcpv6_reply(&enc_reply, enc_packet);
6499 if (enc_reply.data == NULL) {
6521 log_error(
"dhcpv6_relay_forw: no memory for option state.");
6535 log_error(
"dhcpv6_relay_forw: error evaluating " 6540 (
unsigned char *)a_opt.data,
6543 log_error(
"dhcpv6_relay_forw: error saving " 6554 (
unsigned char *)enc_reply.data,
6557 log_error(
"dhcpv6_relay_forw: error saving Relay MSG.");
6573 (packet_ero.len & 1)) {
6574 log_error(
"dhcpv6_relay_forw: error evaluating ERO.");
6579 for (i = 0; i < packet_ero.len; i += 2) {
6596 "evaluating option %u.", req);
6602 (
unsigned char *)a_opt.data,
6606 log_error(
"dhcpv6_relay_forw: error saving " 6615 sizeof(reply_data) - reply_ofs,
6617 required_opts_agent, &packet_ero);
6622 reply_ret->
len = reply_ofs;
6623 reply_ret->
buffer = NULL;
6628 memcpy(reply_ret->
buffer->
data, reply_data, reply_ofs);
6631 if (opt_state != NULL)
6633 if (a_opt.data != NULL) {
6636 if (packet_ero.data != NULL) {
6639 if (enc_reply.data != NULL) {
6642 if (enc_opt_data.
data != NULL) {
6645 if (enc_packet != NULL) {
6661 dhcp4o6_relay_forw(
struct data_string *reply_ret,
struct packet *packet) {
6664 struct packet *enc_packet;
6665 unsigned char msg_type;
6669 char link_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6670 char peer_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6673 static char reply_data[65536];
6681 memset(&a_opt, 0,
sizeof(a_opt));
6682 memset(&packet_ero, 0,
sizeof(packet_ero));
6683 memset(&enc_reply, 0,
sizeof(enc_reply));
6684 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6693 link_addr,
sizeof(link_addr));
6695 peer_addr,
sizeof(peer_addr));
6696 log_info(
"Relay-forward from %s with link address=%s and " 6697 "peer address=%s missing Relay Message option.",
6704 log_error(
"dhcp4o6_relay_forw: error evaluating " 6705 "relayed message.");
6711 "encapsulated packet too short.");
6720 "no memory for encapsulated packet.");
6726 "no memory for encapsulated packet's options.");
6735 msg_type = enc_opt_data.
data[0];
6751 enc_opt_data.
len - relaylen,
6771 enc_opt_data.
len - msglen,
6778 log_error(
"dhcp4o6_relay_forw: unexpected message of type %d.",
6787 build_dhcpv6_reply(&enc_reply, enc_packet);
6793 if (enc_reply.data == NULL) {
6814 log_error(
"dhcp4o6_relay_forw: no memory for option state.");
6828 log_error(
"dhcp4o6_relay_forw: error evaluating " 6833 (
unsigned char *)a_opt.data,
6836 log_error(
"dhcp4o6_relay_forw: error saving " 6847 (
unsigned char *)enc_reply.data,
6850 log_error(
"dhcp4o6_relay_forw: error saving Relay MSG.");
6866 (packet_ero.len & 1)) {
6867 log_error(
"dhcp4o6_relay_forw: error evaluating ERO.");
6872 for (i = 0; i < packet_ero.len; i += 2) {
6889 "evaluating option %u.", req);
6895 (
unsigned char *)a_opt.data,
6899 log_error(
"dhcp4o6_relay_forw: error saving " 6908 sizeof(reply_data) - reply_ofs,
6910 required_opts_agent, &packet_ero);
6915 reply_ret->
len = reply_ofs;
6916 reply_ret->
buffer = NULL;
6921 memcpy(reply_ret->
buffer->
data, reply_data, reply_ofs);
6924 if (opt_state != NULL)
6926 if (a_opt.data != NULL) {
6929 if (packet_ero.data != NULL) {
6932 if (enc_reply.data != NULL) {
6935 if (enc_opt_data.
data != NULL) {
6938 if (enc_packet != NULL) {
6953 dhcp4o6_dhcpv4_query(
struct data_string *reply_ret,
struct packet *packet) {
6956 struct packet *enc_packet;
6959 static char response_data[65536];
6967 memset(&enc_response, 0,
sizeof(enc_response));
6968 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6976 log_info(
"DHCPv4-query from %s missing DHCPv4 Message option.",
6983 log_error(
"dhcp4o6_dhcpv4_query: error evaluating " 6989 log_error(
"dhcp4o6_dhcpv4_query: DHCPv4 packet too short.");
6998 "no memory for encapsulated packet.");
7014 "discarding packet with bogus hlen.");
7020 log_error(
"dhcp4o6_dhcpv4_query: no memory for options.");
7040 memset(&dp, 0,
sizeof dp);
7066 if (enc_response.data == NULL) {
7083 log_error(
"dhcp4o6_dhcpv4_query: no memory for option state.");
7091 (
unsigned char *)enc_response.data,
7094 log_error(
"dhcp4o6_dhcpv4_query: error saving DHCPv4 MSG.");
7099 sizeof(response_data) - response_ofs,
7101 required_opts_4o6, NULL);
7106 reply_ret->
len = response_ofs;
7107 reply_ret->
buffer = NULL;
7109 log_fatal(
"dhcp4o6_dhcpv4_query: no memory to store reply.");
7112 memcpy(reply_ret->
buffer->
data, response_data, response_ofs);
7115 if (opt_state != NULL)
7117 if (enc_response.data != NULL) {
7120 if (enc_opt_data.
data != NULL) {
7123 if (enc_packet != NULL) {
7136 static void forw_dhcpv4_query(
struct packet *packet) {
7146 if ((packet->
raw == NULL) ||
7149 log_error(
"forw_dhcpv4_query: can't find initial message.");
7155 memset(&ds, 0,
sizeof(ds));
7158 "no memory for encapsulating packet.");
7161 ds.data = ds.buffer->data;
7165 strncpy((
char *)ds.buffer->data, packet->
interface->
name, 16);
7166 memcpy(ds.buffer->data + 16,
7168 memcpy(ds.buffer->data + 32,
7169 (
unsigned char *)packet->
raw,
7173 cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
7175 log_error(
"forw_dhcpv4_query: send(): %m");
7181 dhcpv6_discard(
struct packet *packet) {
7185 log_debug(
"Discarding %s from %s; message type not handled by server",
7191 build_dhcpv6_reply(
struct data_string *reply,
struct packet *packet) {
7192 memset(reply, 0,
sizeof(*reply));
7205 dhcpv6_solicit(reply, packet);
7208 dhcpv6_discard(packet);
7212 dhcpv6_request(reply, packet);
7216 dhcpv6_confirm(reply, packet);
7220 dhcpv6_renew(reply, packet);
7224 dhcpv6_rebind(reply, packet);
7227 dhcpv6_discard(packet);
7231 dhcpv6_release(reply, packet);
7235 dhcpv6_decline(reply, packet);
7238 dhcpv6_discard(packet);
7242 dhcpv6_information_request(reply, packet);
7247 dhcp4o6_relay_forw(reply, packet);
7250 dhcpv6_relay_forw(reply, packet);
7253 dhcpv6_discard(packet);
7260 dhcpv6_discard(packet);
7266 forw_dhcpv4_query(packet);
7268 dhcp4o6_dhcpv4_query(reply, packet);
7272 dhcpv6_discard(packet);
7275 dhcpv6_discard(packet);
7280 log_info(
"Discarding unknown DHCPv6 message type %d " 7287 log_packet_in(
const struct packet *packet) {
7290 char tmp_addr[INET6_ADDRSTRLEN];
7293 memset(&s, 0,
sizeof(s));
7302 "Unknown message type %d from %s port %d",
7311 inet_ntop(AF_INET6, addr,
7312 tmp_addr,
sizeof(tmp_addr)));
7315 inet_ntop(AF_INET6, addr,
7316 tmp_addr,
sizeof(tmp_addr)));
7347 dhcpv6(
struct packet *packet) {
7349 struct sockaddr_in6 to_addr;
7355 log_packet_in(packet);
7360 build_dhcpv6_reply(&reply, packet);
7362 if (reply.
data != NULL) {
7366 memset(&to_addr, 0,
sizeof(to_addr));
7367 to_addr.sin6_family = AF_INET6;
7375 #if defined (REPLY_TO_SOURCE_PORT) 7387 sizeof(to_addr.sin6_addr));
7389 log_info(
"Sending %s to %s port %d",
7392 ntohs(to_addr.sin6_port));
7395 reply.
data, reply.
len, &to_addr);
7396 if (send_ret != reply.
len) {
7397 log_error(
"dhcpv6: send_packet6() sent %d of %d bytes",
7398 send_ret, reply.
len);
7416 static void recv_dhcpv4_query(
struct data_string *raw) {
7420 struct packet *packet;
7421 unsigned char msg_type;
7429 memset(name, 0,
sizeof(name));
7430 memcpy(name, raw->
data, 16);
7432 if (!strcmp(name, ip->
name))
7436 log_error(
"recv_dhcpv4_query: can't find interface %s.",
7450 "short packet from %s, len %d, dropped",
7460 log_error(
"recv_dhcpv4_query: no memory for packet.");
7465 log_error(
"recv_dhcpv4_query: no memory for options.");
7476 msg_type = raw->
data[32];
7493 raw->
len - 32 - relaylen,
7513 raw->
len - 32 - msglen,
7521 log_error(
"recv_dhcpv4_query: unexpected message of type %d.",
7535 memset(&ds, 0,
sizeof(ds));
7542 "Unknown message type %d from %s",
7548 char tmp_addr[INET6_ADDRSTRLEN];
7553 inet_ntop(AF_INET6, addr,
7554 tmp_addr,
sizeof(tmp_addr)));
7557 inet_ntop(AF_INET6, addr,
7558 tmp_addr,
sizeof(tmp_addr)));
7572 build_dhcpv6_reply(&reply, packet);
7576 if (reply.
data == NULL)
7582 len = reply.
len + 32;
7583 memset(&ds, 0,
sizeof(ds));
7585 log_error(
"recv_dhcpv4_query: no memory.");
7588 ds.data = ds.buffer->data;
7591 memcpy(ds.buffer->data, name, 16);
7592 memcpy(ds.buffer->data + 16,
iaddr.
iabuf, 16);
7593 memcpy(ds.buffer->data + 32, reply.
data, reply.
len);
7594 cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
7596 log_error(
"recv_dhcpv4_query: send(): %m");
7611 host_reference(&hold, *hp,
MDL);
7612 host_dereference(hp,
MDL);
7614 while (seek != NULL) {
7617 else if (fixed_matches_shared(seek, shared))
7623 if ((seek == NULL) && (nofixed != NULL))
7627 host_reference(hp, seek,
MDL);
7630 static isc_boolean_t
7632 struct subnet *subnet;
7634 isc_boolean_t matched;
7640 memset(&addr, 0,
sizeof(addr));
7645 if (addr.len < 16) {
7651 memcpy(fixed.iabuf, addr.data, 16);
7653 matched = ISC_FALSE;
7654 for (subnet = shared->
subnets ; subnet != NULL ;
7685 struct packet *packet,
7689 struct reply_state reply;
7690 memset(&reply, 0x0,
sizeof(
struct reply_state));
7693 if (shared_network_from_packet6(&reply.shared, packet)
7695 log_error(
"unicast_reject: could not locate client.");
7703 if (start_reply(packet, client_id, server_id, &reply.opt_state,
7704 &reply.buf.reply)) {
7707 "Unicast not allowed by server.",
7709 log_error(
"unicast_reject: Unable to set status code.");
7719 unicast_reject_opts,
7723 reply_ret->
len = reply.cursor;
7724 reply_ret->
buffer = NULL;
7726 reply.cursor,
MDL)) {
7728 "No memory to store Reply.");
7739 if (reply.shared != NULL)
7740 shared_network_dereference(&reply.shared,
MDL);
7741 if (reply.opt_state != NULL)
7743 if (reply.packet != NULL)
7745 if (reply.client_id.
data != NULL)
7768 is_unicast_option_defined(
struct packet *packet) {
7769 isc_boolean_t is_defined = ISC_FALSE;
7776 "No memory for option state.");
7781 if (((shared_network_from_requested_addr(&shared, packet)
7782 != ISC_R_SUCCESS) &&
7783 (shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS))
7784 || (shared == NULL)) {
7788 "cannot attribute packet to a network.");
7799 is_defined = (oc != NULL ? ISC_TRUE : ISC_FALSE);
7800 log_debug(
"is_unicast_option_defined: option found : %d", is_defined);
7802 if (shared != NULL) {
7803 shared_network_dereference(&shared,
MDL);
7806 if (opt_state != NULL) {
7810 return (is_defined);
7829 shared_network_from_requested_addr (
struct shared_network **shared,
7830 struct packet* packet) {
7832 struct subnet* subnet = NULL;
7833 isc_result_t status = ISC_R_FAILURE;
7838 if ((get_first_ia_addr_val(packet,
D6O_IA_NA, &
iaddr) != ISC_R_SUCCESS)
7842 != ISC_R_SUCCESS)) {
7844 log_debug(
"share_network_from_request_addr: nothing to match");
7845 return (ISC_R_FAILURE);
7849 log_debug(
"shared_network_from_requested_addr:" 7852 status = shared_network_reference(shared,
7854 subnet_dereference(&subnet,
MDL);
7855 log_debug(
"shared_network_from_requested_addr:" 7856 " found shared network %s for address %s.",
7857 ((*shared)->name ? (*shared)->name :
"unnamed"),
7862 return (ISC_R_FAILURE);
7884 get_first_ia_addr_val (
struct packet* packet,
int addr_type,
7890 int addr_opt_offset;
7892 int addr_opt_data_len;
7895 isc_result_t status = ISC_R_FAILURE;
7896 memset(iaddr, 0,
sizeof(
struct iaddr));
7899 switch (addr_type) {
7903 addr_opt_data_len = 24;
7909 addr_opt_data_len = 24;
7915 addr_opt_data_len = 25;
7920 log_error (
"get_first_ia_addr_val: invalid opt type %d",
7922 return (ISC_R_FAILURE);
7927 ia != NULL && oc == NULL; ia = ia->
next) {
7928 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
7930 packet, ia, addr_opt_offset)) {
7932 " couldn't unroll enclosing option");
7933 return (ISC_R_FAILURE);
7949 memset(&iaddr_str, 0,
sizeof(iaddr_str));
7954 "error evaluating IA_XX option.");
7956 if (iaddr_str.len != addr_opt_data_len) {
7957 log_error(
"shared_network_from_requested_addr:" 7958 " invalid length %d, expected %d",
7959 iaddr_str.len, addr_opt_data_len);
7962 memcpy (iaddr->
iabuf,
7963 iaddr_str.data + ip_addr_offset, 16);
7964 status = ISC_R_SUCCESS;
8006 set_reply_tee_times(
struct reply_state* reply,
unsigned ia_cursor)
8014 set_tee_times = (oc &&
8017 reply->packet->options,
8029 reply->packet->options,
8039 if (
data.data != NULL)
8041 }
else if (set_tee_times) {
8044 reply->renew = (reply->min_prefer == 0xFFFFFFFF ? 0xFFFFFFFF
8045 : reply->min_prefer / 2);
8051 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
8062 reply->packet->options,
8072 if (
data.data != NULL)
8074 }
else if (set_tee_times) {
8077 reply->rebind = (reply->min_prefer == 0xFFFFFFFF ? 0xFFFFFFFF
8078 : (reply->min_prefer / 5) * 4);
8084 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
struct iaddrcidrnet cidrnet
#define DHCP_FIXED_NON_UDP
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]
struct binding_scope * global_scope
isc_result_t add_lease6(struct ipv6_pool *pool, struct iasubopt *lease, time_t valid_lifetime_end_time)
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)
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
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
void bootp(struct packet *packet)
struct shared_network * shared_network
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
#define DHCPV6_DHCPV4_QUERY
struct permit * prohibit_list
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
isc_result_t decline_lease6(struct ipv6_pool *pool, struct iasubopt *lease)
int find_hosts6(struct host_decl **host, struct packet *packet, const struct data_string *client_id, char *file, int line)
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
#define DHCPV6_DHCPV4_RESPONSE
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
#define SV_DHCPV6_SET_TEE_TIMES
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)
int parse_options(struct packet *packet)
struct interface_info * interfaces
unsigned char dhcp4o6_flags[3]
u_int32_t getULong(const unsigned char *)
struct shared_network * shared_network
int validate_packet(struct packet *packet)
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 *)
#define DHCP4O6_QUERY_UNICAST
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 data_string * dhcp4o6_response
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)
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 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 SV_DEFAULT_LEASE_TIME
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
#define REPLY_OPTIONS_INDEX
void dhcp(struct packet *packet)
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)
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
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
const unsigned char * data
#define DHO_DHCP_MESSAGE_TYPE
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
unsigned char options[DHCP_MAX_OPTION_LEN]
#define STATUS_UseMulticast
struct packet * dhcpv6_container_packet
isc_result_t iasubopt_reference(struct iasubopt **iasubopt, struct iasubopt *src, const char *file, int line)