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)) {
1422 tmp_plen = (
int) requested_pref->
data[0];
1423 if ((tmp_plen < 3) || (tmp_plen > 128)) {
1424 return ISC_R_FAILURE;
1427 memcpy(&tmp_pref, requested_pref->
data + 1,
sizeof(tmp_pref));
1428 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
1429 return ISC_R_FAILURE;
1433 memcpy(&ia.iabuf, &tmp_pref, 16);
1435 return ISC_R_FAILURE;
1439 ((
int)tmp_plen != pool->
units)) {
1440 return ISC_R_ADDRNOTAVAIL;
1444 return ISC_R_ADDRINUSE;
1447 result = iasubopt_allocate(pref,
MDL);
1448 if (result != ISC_R_SUCCESS) {
1452 (*pref)->addr = tmp_pref;
1453 (*pref)->plen = tmp_plen;
1457 if (result != ISC_R_SUCCESS) {
1504 pick_v6_prefix(
struct reply_state *reply) {
1508 isc_result_t result;
1514 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1518 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1528 log_debug(
"Unable to pick client prefix: " 1529 "no IPv6 pools on this shared network");
1530 return ISC_R_NORESOURCES;
1533 if (reply->preflen <= 0) {
1536 result = pick_v6_prefix_helper(reply,
PLM_IGNORE);
1542 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1543 if (result != ISC_R_SUCCESS) {
1544 result = pick_v6_prefix_helper(reply,
1551 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1558 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1559 if (result != ISC_R_SUCCESS) {
1560 result = pick_v6_prefix_helper(reply,
1567 result = pick_v6_prefix_helper(reply,
PLM_IGNORE);
1572 if (result == ISC_R_SUCCESS) {
1573 char tmp_buf[INET6_ADDRSTRLEN];
1576 inet_ntop(AF_INET6, &(reply->lease->addr),
1577 tmp_buf,
sizeof(tmp_buf)),
1578 (
unsigned)(reply->lease->plen));
1579 return (ISC_R_SUCCESS);
1586 log_debug(
"Unable to pick client prefix: no prefixes available");
1587 return ISC_R_NORESOURCES;
1614 pick_v6_prefix_helper(
struct reply_state *reply,
int prefix_mode) {
1618 unsigned int attempts;
1619 struct iasubopt **pref = &reply->lease;
1621 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1628 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1630 (eval_prefix_mode(p->
units, reply->preflen,
1631 prefix_mode) == 1) &&
1633 &reply->ia->iaid_duid,
1634 cur_time + 120) == ISC_R_SUCCESS)) {
1635 return (ISC_R_SUCCESS);
1640 return ISC_R_NORESOURCES;
1658 eval_prefix_mode(
int len,
int preflen,
int prefix_mode) {
1660 switch (prefix_mode) {
1662 use_it = (len == preflen);
1666 use_it = (len >= preflen);
1670 use_it = (len <= preflen);
1717 struct packet *packet,
1721 static struct reply_state reply;
1726 memset(&packet_oro, 0,
sizeof(packet_oro));
1729 if (shared_network_from_packet6(&reply.shared,
1730 packet) != ISC_R_SUCCESS)
1739 if (!start_reply(packet, client_id, server_id, &reply.opt_state,
1755 log_error(
"lease_to_client: error evaluating ORO.");
1766 seek_shared_host(&reply.host, reply.shared);
1773 for (; oc != NULL ; oc = oc->
next) {
1774 isc_result_t status;
1777 reply.client_resources = 0;
1778 reply.resources_included = ISC_FALSE;
1780 status = reply_process_ia_na(&reply, oc);
1786 if ((status != ISC_R_SUCCESS) &&
1787 (status != ISC_R_NORESOURCES))
1791 for (; oc != NULL ; oc = oc->
next) {
1792 isc_result_t status;
1795 reply.client_resources = 0;
1796 reply.resources_included = ISC_FALSE;
1798 status = reply_process_ia_ta(&reply, oc);
1804 if ((status != ISC_R_SUCCESS) &&
1805 (status != ISC_R_NORESOURCES))
1812 for (; oc != NULL ; oc = oc->
next) {
1813 isc_result_t status;
1816 reply.client_resources = 0;
1817 reply.resources_included = ISC_FALSE;
1819 status = reply_process_ia_pd(&reply, oc);
1825 if ((status != ISC_R_SUCCESS) &&
1826 (status != ISC_R_NORESOURCES))
1834 if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
1835 if (reply.packet->dhcpv6_msg_type !=
1845 reply.packet->options,
1851 for (i = reply.packet->class_count; i > 0; i--) {
1854 reply.packet->options,
1857 reply.packet->classes[i - 1]->group,
1858 reply.shared->group, NULL);
1862 if (reply.host != NULL)
1865 reply.packet->options,
1869 reply.shared->group, NULL);
1904 reply.cursor +=
store_options6((
char *)reply.buf.data + reply.cursor,
1905 sizeof(reply.buf) - reply.cursor,
1906 reply.opt_state, reply.packet,
1907 required_opts_solicit,
1911 reply_ret->
len = reply.cursor;
1912 reply_ret->
buffer = NULL;
1916 memcpy(reply_ret->
buffer->
data, reply.buf.data, reply.cursor);
1924 if (reply.shared != NULL)
1925 shared_network_dereference(&reply.shared,
MDL);
1926 if (reply.host != NULL)
1927 host_dereference(&reply.host,
MDL);
1928 if (reply.opt_state != NULL)
1930 if (reply.packet != NULL)
1932 if (reply.client_id.data != NULL)
1934 if (packet_oro.buffer != NULL)
1936 reply.renew = reply.rebind = reply.min_prefer = reply.min_valid = 0;
1944 reply_process_ia_na(
struct reply_state *reply,
struct option_cache *ia) {
1945 isc_result_t status = ISC_R_SUCCESS;
1954 memset(&ia_data, 0,
sizeof(ia_data));
1961 if ((reply->cursor +
IA_NA_OFFSET + 4) >
sizeof(reply->buf)) {
1962 log_error(
"reply_process_ia_na: Reply too long for IA.");
1963 return ISC_R_NOSPACE;
1968 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
1970 log_error(
"reply_process_ia_na: error evaluating ia");
1971 status = ISC_R_FAILURE;
1977 reply->renew =
getULong(ia_data.data + 4);
1978 reply->rebind =
getULong(ia_data.data + 8);
1981 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
1982 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
1983 log_error(
"reply_process_ia_na: no memory for ia.");
1984 status = ISC_R_NOMEMORY;
1991 (
unsigned char *)reply->ia->iaid_duid.data,
1992 reply->ia->iaid_duid.len,
MDL);
1999 status = ISC_R_NOMEMORY;
2004 if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
2005 struct iaddr tmp_addr;
2009 reply->host->fixed_addr,
MDL)) {
2010 log_error(
"reply_process_ia_na: unable to evaluate " 2012 status = ISC_R_FAILURE;
2016 if (reply->fixed.len < 16) {
2017 log_error(
"reply_process_ia_na: invalid fixed address.");
2024 memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
2027 tmp_addr,
MDL) == 0)
2030 reply->static_lease = ISC_TRUE;
2032 reply->static_lease = ISC_FALSE;
2040 ia_cursor = reply->cursor;
2047 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
2051 putULong(reply->buf.data + reply->cursor, iaid);
2055 putULong(reply->buf.data + reply->cursor, reply->renew);
2059 putULong(reply->buf.data + reply->cursor, reply->rebind);
2073 reply->client_valid = reply->client_prefer = 0;
2074 for (; oc != NULL ; oc = oc->
next) {
2075 status = reply_process_addr(reply, oc);
2083 if (status == ISC_R_CANCELED)
2086 if ((status != ISC_R_SUCCESS) &&
2087 (status != ISC_R_ADDRINUSE) &&
2088 (status != ISC_R_ADDRNOTAVAIL))
2098 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
2099 status = find_client_address(reply);
2101 if (status == ISC_R_NORESOURCES) {
2102 switch (reply->packet->dhcpv6_msg_type) {
2125 "memory for option state " 2127 status = ISC_R_NOMEMORY;
2132 "No addresses available " 2133 "for this interface.",
2135 log_error(
"reply_process_ia_na: Unable " 2136 "to set NoAddrsAvail status " 2138 status = ISC_R_FAILURE;
2142 status = ISC_R_SUCCESS;
2162 if (reply->resources_included)
2163 status = ISC_R_SUCCESS;
2170 if (status != ISC_R_SUCCESS)
2174 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2175 sizeof(reply->buf) - reply->cursor,
2176 reply->reply_ia, reply->packet,
2177 required_opts_IA, NULL);
2180 putUShort(reply->buf.data + ia_cursor + 2,
2181 reply->cursor - (ia_cursor + 4));
2184 set_reply_tee_times(reply, ia_cursor);
2190 if (status == ISC_R_CANCELED)
2197 if (reply->static_lease) {
2198 char tmp_addr[INET6_ADDRSTRLEN];
2199 log_info(
"%s NA: address %s to client with duid %s iaid = %d " 2202 inet_ntop(AF_INET6, reply->fixed.data, tmp_addr,
2205 reply->client_id.data, 60),
2209 (reply->on_star.on_commit != NULL)) {
2211 reply->packet->options,
2212 reply->opt_state, NULL,
2213 reply->on_star.on_commit, NULL);
2215 (&reply->on_star.on_commit,
MDL);
2223 if (reply->ia->num_iasubopt != 0) {
2226 char tmp_addr[INET6_ADDRSTRLEN];
2228 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2229 tmp = reply->ia->iasubopt[i];
2231 log_info(
"%s NA: address %s to client with duid %s " 2232 "iaid = %d valid for %u seconds",
2234 inet_ntop(AF_INET6, &tmp->
addr,
2235 tmp_addr,
sizeof(tmp_addr)),
2237 reply->client_id.data, 60),
2251 if ((reply->ia->num_iasubopt != 0) &&
2257 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2258 tmp = reply->ia->iasubopt[i];
2260 if (tmp->
ia != NULL)
2272 reply->packet->options,
2281 #if defined (NSUPDATE) 2290 reply->packet->options,
2295 tmp, NULL, reply->opt_state);
2299 check_pool6_threshold(reply, tmp);
2303 if (reply->old_ia != NULL) {
2304 ia_id = &reply->old_ia->iaid_duid;
2306 (
unsigned char *)ia_id->
data,
2313 ia_id = &reply->ia->iaid_duid;
2315 ia_id->
len, reply->ia,
MDL);
2319 schedule_lease_timeout_reply(reply);
2323 if (packet_ia != NULL)
2325 if (reply->reply_ia != NULL)
2327 if (ia_data.data != NULL)
2329 if (
data.data != NULL)
2331 if (reply->ia != NULL)
2333 if (reply->old_ia != NULL)
2335 if (reply->lease != NULL)
2337 if (reply->fixed.data != NULL)
2339 if (reply->subnet != NULL)
2340 subnet_dereference(&reply->subnet,
MDL);
2341 if (reply->on_star.on_expiry != NULL)
2343 (&reply->on_star.on_expiry,
MDL);
2344 if (reply->on_star.on_release != NULL)
2346 (&reply->on_star.on_release,
MDL);
2353 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2363 reply_process_addr(
struct reply_state *reply,
struct option_cache *addr) {
2364 u_int32_t pref_life, valid_life;
2368 struct iaddr tmp_addr;
2371 isc_result_t status = ISC_R_SUCCESS;
2374 memset(&iaaddr, 0,
sizeof(iaaddr));
2382 if ((reply->cursor + 28) >
sizeof(reply->buf)) {
2383 log_error(
"reply_process_addr: Out of room for address.");
2384 return ISC_R_NOSPACE;
2392 log_error(
"reply_process_addr: error evaluating IAADDR.");
2393 status = ISC_R_FAILURE;
2398 pref_life =
getULong(iaaddr.data + 16);
2399 valid_life =
getULong(iaaddr.data + 20);
2401 if ((reply->client_valid == 0) ||
2402 (reply->client_valid > valid_life))
2403 reply->client_valid = valid_life;
2405 if ((reply->client_prefer == 0) ||
2406 (reply->client_prefer > pref_life))
2407 reply->client_prefer = pref_life;
2414 memset(tmp_addr.iabuf, 0, 16);
2415 if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
2421 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2426 for (subnet = reply->shared->subnets ; subnet != NULL ;
2434 if (subnet == NULL) {
2459 log_error(
"reply_process_addr: No memory for " 2460 "option state wipe.");
2461 status = ISC_R_NOMEMORY;
2467 "Address not for use on this " 2468 "link.", reply->reply_ia)) {
2469 log_error(
"reply_process_addr: Failure " 2470 "setting status code.");
2471 status = ISC_R_FAILURE;
2476 status = ISC_R_CANCELED;
2488 if ((reply->packet->dhcpv6_msg_type !=
DHCPV6_RENEW) &&
2490 log_error(
"It is impossible to lease a client that is " 2491 "not sending a solicit, request, renew, or " 2493 status = ISC_R_FAILURE;
2497 reply->send_prefer = reply->send_valid = 0;
2502 if (!address_is_owned(reply, &tmp_addr)) {
2513 status = reply_process_try_addr(reply, &tmp_addr);
2520 if ((status != ISC_R_SUCCESS) &&
2521 (status != ISC_R_ADDRINUSE) &&
2522 (status != ISC_R_ADDRNOTAVAIL))
2530 if (reply->lease == NULL) {
2531 if (reply->packet->dhcpv6_msg_type ==
2533 reply->send_prefer = 0;
2534 reply->send_valid = 0;
2551 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
2555 log_error(
"reply_process_addr: No memory for " 2556 "option state wipe.");
2557 status = ISC_R_NOMEMORY;
2563 "Address not bound to this " 2564 "interface.", reply->reply_ia)) {
2565 log_error(
"reply_process_addr: Unable to " 2566 "attach status code.");
2567 status = ISC_R_FAILURE;
2572 status = ISC_R_CANCELED;
2575 log_error(
"It is impossible to lease a client that is " 2576 "not sending a solicit, request, renew, or " 2578 status = ISC_R_FAILURE;
2583 if (reply->static_lease) {
2584 if (reply->host == NULL)
2588 group = reply->subnet->group;
2590 if (reply->lease == NULL)
2593 scope = &reply->lease->scope;
2594 group = reply->lease->ipv6_pool->ipv6_pond->group;
2603 if (reply->client_resources != 0) {
2616 reply->packet->options,
2620 log_error(
"reply_process_addr: unable to " 2621 "evaluate addrs-per-ia value.");
2622 status = ISC_R_FAILURE;
2634 if (reply->client_resources >= limit)
2638 status = reply_process_is_addressed(reply, scope, group);
2639 if (status != ISC_R_SUCCESS)
2643 status = reply_process_send_addr(reply, &tmp_addr);
2646 if (iaaddr.data != NULL)
2648 if (
data.data != NULL)
2650 if (reply->lease != NULL)
2662 static isc_boolean_t
2663 address_is_owned(
struct reply_state *reply,
struct iaddr *addr) {
2670 if (reply->static_lease) {
2671 if (reply->fixed.data == NULL)
2674 if (memcmp(addr->
iabuf, reply->fixed.data, 16) == 0)
2680 if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
2683 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2686 tmp = reply->old_ia->iasubopt[i];
2688 if (memcmp(addr->
iabuf, &tmp->
addr, 16) == 0) {
2713 reply_process_ia_ta(
struct reply_state *reply,
struct option_cache *ia) {
2714 isc_result_t status = ISC_R_SUCCESS;
2721 u_int32_t pref_life, valid_life;
2722 struct iaddr tmp_addr;
2726 memset(&ia_data, 0,
sizeof(ia_data));
2727 memset(&data, 0,
sizeof(data));
2728 memset(&iaaddr, 0,
sizeof(iaaddr));
2731 if ((reply->cursor +
IA_TA_OFFSET + 4) >
sizeof(reply->buf)) {
2732 log_error(
"reply_process_ia_ta: Reply too long for IA.");
2733 return ISC_R_NOSPACE;
2738 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2740 log_error(
"reply_process_ia_ta: error evaluating ia");
2741 status = ISC_R_FAILURE;
2749 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
2750 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
2751 log_error(
"reply_process_ia_ta: no memory for ia.");
2752 status = ISC_R_NOMEMORY;
2759 (
unsigned char *)reply->ia->iaid_duid.data,
2760 reply->ia->iaid_duid.len,
MDL);
2767 status = ISC_R_NOMEMORY;
2774 reply->static_lease = ISC_FALSE;
2782 ia_cursor = reply->cursor;
2789 putUShort(reply->buf.data + reply->cursor, 0x04u);
2793 putULong(reply->buf.data + reply->cursor, iaid);
2801 reply->client_valid = reply->client_prefer = 0;
2803 for (; oc != NULL; oc = oc->
next) {
2804 memset(&iaaddr, 0,
sizeof(iaaddr));
2807 reply->packet->options, NULL,
2811 "evaluating IAADDR.");
2812 status = ISC_R_FAILURE;
2816 pref_life =
getULong(iaaddr.data + 16);
2817 valid_life =
getULong(iaaddr.data + 20);
2819 if ((reply->client_valid == 0) ||
2820 (reply->client_valid > valid_life))
2821 reply->client_valid = valid_life;
2823 if ((reply->client_prefer == 0) ||
2824 (reply->client_prefer > pref_life))
2825 reply->client_prefer = pref_life;
2828 if (status == ISC_R_CANCELED)
2832 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2833 if (!temporary_is_available(reply, &tmp_addr))
2835 status = reply_process_is_addressed(reply,
2836 &reply->lease->scope,
2837 reply->lease->ipv6_pool->ipv6_pond->group);
2838 if (status != ISC_R_SUCCESS)
2840 status = reply_process_send_addr(reply, &tmp_addr);
2841 if (status != ISC_R_SUCCESS)
2843 if (reply->lease != NULL)
2851 status = ISC_R_NOMEMORY;
2854 status = ISC_R_CANCELED;
2855 reply->client_resources = 0;
2856 reply->resources_included = ISC_FALSE;
2857 if (reply->lease != NULL)
2865 if (reply->client_resources != 0)
2867 status = find_client_temporaries(reply);
2868 if (status == ISC_R_NORESOURCES) {
2869 switch (reply->packet->dhcpv6_msg_type) {
2890 "memory for option state wipe.");
2891 status = ISC_R_NOMEMORY;
2896 "No addresses available " 2897 "for this interface.",
2899 log_error(
"reply_process_ia_ta: Unable " 2900 "to set NoAddrsAvail status code.");
2901 status = ISC_R_FAILURE;
2905 status = ISC_R_SUCCESS;
2914 if (reply->resources_included)
2915 status = ISC_R_SUCCESS;
2920 }
else if (status != ISC_R_SUCCESS)
2924 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2925 sizeof(reply->buf) - reply->cursor,
2926 reply->reply_ia, reply->packet,
2927 required_opts_IA, NULL);
2930 putUShort(reply->buf.data + ia_cursor + 2,
2931 reply->cursor - (ia_cursor + 4));
2937 if (status == ISC_R_CANCELED)
2943 if (reply->ia->num_iasubopt != 0) {
2946 char tmp_addr[INET6_ADDRSTRLEN];
2948 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2949 tmp = reply->ia->iasubopt[i];
2951 log_info(
"%s TA: address %s to client with duid %s " 2952 "iaid = %d valid for %u seconds",
2954 inet_ntop(AF_INET6, &tmp->
addr,
2955 tmp_addr,
sizeof(tmp_addr)),
2957 reply->client_id.data, 60),
2971 if ((reply->ia->num_iasubopt != 0) &&
2977 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2978 tmp = reply->ia->iasubopt[i];
2980 if (tmp->
ia != NULL)
2992 reply->packet->options,
3001 #if defined (NSUPDATE) 3010 reply->packet->options,
3015 tmp, NULL, reply->opt_state);
3019 check_pool6_threshold(reply, tmp);
3023 if (reply->old_ia != NULL) {
3024 ia_id = &reply->old_ia->iaid_duid;
3026 (
unsigned char *)ia_id->
data,
3033 ia_id = &reply->ia->iaid_duid;
3035 ia_id->
len, reply->ia,
MDL);
3039 schedule_lease_timeout_reply(reply);
3043 if (packet_ia != NULL)
3045 if (iaaddr.data != NULL)
3047 if (reply->reply_ia != NULL)
3049 if (ia_data.data != NULL)
3051 if (
data.data != NULL)
3053 if (reply->ia != NULL)
3055 if (reply->old_ia != NULL)
3057 if (reply->lease != NULL)
3065 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
3071 static isc_boolean_t
3072 temporary_is_available(
struct reply_state *reply,
struct iaddr *addr) {
3073 struct in6_addr tmp_addr;
3074 struct subnet *subnet;
3079 memcpy(&tmp_addr, addr->
iabuf,
sizeof(tmp_addr));
3085 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
3091 for (subnet = reply->shared->subnets ; subnet != NULL ;
3105 if (address_is_owned(reply, addr))
3111 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3118 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
3134 if (iasubopt_allocate(&reply->lease,
MDL) != ISC_R_SUCCESS)
3136 reply->lease->addr = tmp_addr;
3137 reply->lease->plen = 0;
3149 find_client_temporaries(
struct reply_state *reply) {
3153 isc_result_t status = ISC_R_NORESOURCES;;
3154 unsigned int attempts;
3155 struct iaddr send_addr;
3161 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3165 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3175 log_debug(
"Unable to get client addresses: " 3176 "no IPv6 pools on this shared network");
3177 return ISC_R_NORESOURCES;
3187 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3194 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3203 &reply->client_id,
cur_time + 120);
3204 if (status != ISC_R_SUCCESS) {
3205 log_debug(
"Unable to get a temporary address.");
3209 status = reply_process_is_addressed(reply,
3210 &reply->lease->scope,
3212 if (status != ISC_R_SUCCESS) {
3216 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3217 status = reply_process_send_addr(reply, &send_addr);
3218 if (status != ISC_R_SUCCESS) {
3230 if (reply->lease != NULL) {
3241 reply_process_try_addr(
struct reply_state *reply,
struct iaddr *addr) {
3242 isc_result_t status = ISC_R_ADDRNOTAVAIL;
3248 if ((reply == NULL) || (reply->shared == NULL) ||
3249 (addr == NULL) || (reply->lease != NULL))
3256 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3260 for (i = 0; ; i++) {
3262 if ((pool == NULL) ||
3272 return (ISC_R_ADDRNOTAVAIL);
3275 memset(&data_addr, 0,
sizeof(data_addr));
3276 data_addr.len = addr->
len;
3277 data_addr.data = addr->
iabuf;
3290 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3297 for (i = 0 ; (pool = pond->
ipv6_pools[i]) != NULL ; i++) {
3301 status = try_client_v6_address(&reply->lease, pool,
3303 if (status == ISC_R_SUCCESS)
3307 if (status == ISC_R_SUCCESS)
3322 find_client_address(
struct reply_state *reply) {
3323 struct iaddr send_addr;
3324 isc_result_t status = ISC_R_NORESOURCES;
3325 struct iasubopt *lease, *best_lease = NULL;
3327 struct group *group;
3330 if (reply->static_lease) {
3331 if (reply->host == NULL)
3335 memcpy(send_addr.iabuf, reply->fixed.data, 16);
3338 group = reply->subnet->group;
3342 if (reply->old_ia != NULL) {
3343 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
3347 lease = reply->old_ia->iasubopt[i];
3356 if ((candidate_shared != reply->shared) ||
3366 best_lease = lease_compare(lease, best_lease);
3374 status = pick_v6_address(reply);
3375 }
else if (best_lease != NULL) {
3377 status = ISC_R_SUCCESS;
3381 if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
3383 log_error(
"Best match for DUID %s is an abandoned address," 3384 " This may be a result of multiple clients attempting" 3385 " to use this DUID",
3387 reply->client_id.data, 60));
3392 if (status != ISC_R_SUCCESS)
3395 if (reply->lease == NULL)
3402 scope = &reply->lease->scope;
3403 group = reply->lease->ipv6_pool->ipv6_pond->group;
3406 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3409 status = reply_process_is_addressed(reply, scope, group);
3410 if (status != ISC_R_SUCCESS)
3413 status = reply_process_send_addr(reply, &send_addr);
3422 reply_process_is_addressed(
struct reply_state *reply,
3425 isc_result_t status = ISC_R_SUCCESS;
3433 memset(&data, 0,
sizeof(data));
3442 on_star = &reply->lease->on_star;
3444 on_star = &reply->on_star;
3454 reply->packet->options, tmp_options,
3457 if (tmp_options != NULL) {
3467 reply->packet->options, reply->opt_state,
3471 for (i = reply->packet->class_count; i > 0; i--) {
3473 reply->packet->options,
3474 reply->opt_state, scope,
3475 reply->packet->classes[i - 1]->group,
3484 if (reply->host != NULL)
3486 reply->packet->options,
3487 reply->opt_state, scope,
3488 reply->host->group, group,
3492 if (reply->client_valid == 0)
3495 reply->send_valid = reply->client_valid;
3501 reply->packet->options,
3505 log_error(
"reply_process_is_addressed: unable to " 3506 "evaluate default lease time");
3507 status = ISC_R_FAILURE;
3511 reply->send_valid =
getULong(data.data);
3521 time_t test_time =
cur_time + reply->send_valid;
3526 if (reply->client_prefer == 0)
3527 reply->send_prefer = reply->send_valid;
3529 reply->send_prefer = reply->client_prefer;
3531 if ((reply->send_prefer >= reply->send_valid) &&
3533 reply->send_prefer = (reply->send_valid / 2) +
3534 (reply->send_valid / 8);
3540 reply->packet->options,
3544 log_error(
"reply_process_is_addressed: unable to " 3545 "evaluate preferred lease time");
3546 status = ISC_R_FAILURE;
3550 reply->send_prefer =
getULong(data.data);
3555 if (reply->min_prefer > reply->send_prefer)
3556 reply->min_prefer = reply->send_prefer;
3558 if (reply->min_valid > reply->send_valid)
3559 reply->min_valid = reply->send_valid;
3571 if (reply->host != NULL)
3573 reply->client_id->len);
3577 if (reply->lease != NULL) {
3579 reply->lease->prefer = reply->send_prefer;
3580 reply->lease->valid = reply->send_valid;
3588 reply->lease->soft_lifetime_end_time =
MAX_TIME;
3590 reply->lease->soft_lifetime_end_time =
3597 if (status != ISC_R_SUCCESS) {
3598 log_fatal(
"reply_process_is_addressed: Unable to " 3599 "attach lease to new IA: %s",
3600 isc_result_totext(status));
3606 if (reply->lease->ia == NULL) {
3613 reply->packet->options, reply->reply_ia,
3617 for (i = reply->packet->class_count; i > 0; i--) {
3619 reply->packet->options,
3620 reply->reply_ia, scope,
3621 reply->packet->classes[i - 1]->group,
3629 if (reply->host != NULL)
3631 reply->packet->options,
3632 reply->reply_ia, scope,
3633 reply->host->group, group, NULL);
3636 if (data.data != NULL)
3639 if (status == ISC_R_SUCCESS)
3640 reply->client_resources++;
3647 reply_process_send_addr(
struct reply_state *reply,
struct iaddr *addr) {
3648 isc_result_t status = ISC_R_SUCCESS;
3656 log_error(
"reply_process_send_addr: out of memory" 3657 "allocating new IAADDR buffer.");
3658 status = ISC_R_NOMEMORY;
3663 memcpy(
data.buffer->data, addr->
iabuf, 16);
3670 log_error(
"reply_process_send_addr: unable " 3671 "to save IAADDR option");
3672 status = ISC_R_FAILURE;
3676 reply->resources_included = ISC_TRUE;
3679 if (
data.data != NULL)
3693 switch(alpha->
state) {
3695 switch(beta->
state) {
3716 switch (beta->
state) {
3742 switch (beta->
state) {
3764 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
3772 reply_process_ia_pd(
struct reply_state *reply,
struct option_cache *ia) {
3773 isc_result_t status = ISC_R_SUCCESS;
3782 memset(&ia_data, 0,
sizeof(ia_data));
3789 if ((reply->cursor +
IA_PD_OFFSET + 4) >
sizeof(reply->buf)) {
3790 log_error(
"reply_process_ia_pd: Reply too long for IA.");
3791 return ISC_R_NOSPACE;
3796 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
3798 log_error(
"reply_process_ia_pd: error evaluating ia");
3799 status = ISC_R_FAILURE;
3805 reply->renew =
getULong(ia_data.data + 4);
3806 reply->rebind =
getULong(ia_data.data + 8);
3809 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
3810 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
3811 log_error(
"reply_process_ia_pd: no memory for ia.");
3812 status = ISC_R_NOMEMORY;
3819 (
unsigned char *)reply->ia->iaid_duid.data,
3820 reply->ia->iaid_duid.len,
MDL);
3827 status = ISC_R_NOMEMORY;
3832 reply->static_prefixes = 0;
3833 if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
3836 for (fp = reply->host->fixed_prefix; fp != NULL;
3838 reply->static_prefixes += 1;
3848 ia_cursor = reply->cursor;
3855 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
3859 putULong(reply->buf.data + reply->cursor, iaid);
3863 putULong(reply->buf.data + reply->cursor, reply->renew);
3867 putULong(reply->buf.data + reply->cursor, reply->rebind);
3875 reply->client_valid = reply->client_prefer = 0;
3876 reply->preflen = -1;
3877 for (; oc != NULL ; oc = oc->
next) {
3878 status = reply_process_prefix(reply, oc);
3886 if (status == ISC_R_CANCELED)
3889 if ((status != ISC_R_SUCCESS) &&
3890 (status != ISC_R_ADDRINUSE) &&
3891 (status != ISC_R_ADDRNOTAVAIL))
3901 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
3902 status = find_client_prefix(reply);
3904 if (status == ISC_R_NORESOURCES) {
3905 switch (reply->packet->dhcpv6_msg_type) {
3920 "memory for option state " 3922 status = ISC_R_NOMEMORY;
3927 "No prefixes available " 3928 "for this interface.",
3932 "NoPrefixAvail status " 3934 status = ISC_R_FAILURE;
3938 status = ISC_R_SUCCESS;
3942 if (reply->resources_included)
3943 status = ISC_R_SUCCESS;
3950 if (status != ISC_R_SUCCESS)
3954 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
3955 sizeof(reply->buf) - reply->cursor,
3956 reply->reply_ia, reply->packet,
3957 required_opts_IA_PD, NULL);
3960 putUShort(reply->buf.data + ia_cursor + 2,
3961 reply->cursor - (ia_cursor + 4));
3964 set_reply_tee_times(reply, ia_cursor);
3970 if (status == ISC_R_CANCELED)
3977 if (reply->static_prefixes != 0) {
3978 char tmp_addr[INET6_ADDRSTRLEN];
3979 log_info(
"%s PD: address %s/%d to client with duid %s " 3982 inet_ntop(AF_INET6, reply->fixed_pref.lo_addr.iabuf,
3983 tmp_addr,
sizeof(tmp_addr)),
3984 reply->fixed_pref.bits,
3986 reply->client_id.data, 60),
3989 (reply->on_star.on_commit != NULL)) {
3991 reply->packet->options,
3993 NULL, reply->on_star.on_commit,
3996 (&reply->on_star.on_commit,
MDL);
4004 if (reply->ia->num_iasubopt != 0) {
4007 char tmp_addr[INET6_ADDRSTRLEN];
4009 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
4010 tmp = reply->ia->iasubopt[i];
4012 log_info(
"%s PD: address %s/%d to client with duid %s" 4013 " iaid = %d valid for %u seconds",
4015 inet_ntop(AF_INET6, &tmp->
addr,
4016 tmp_addr,
sizeof(tmp_addr)),
4019 reply->client_id.data, 60),
4033 (reply->ia->num_iasubopt != 0)) {
4038 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
4039 tmp = reply->ia->iasubopt[i];
4041 if (tmp->
ia != NULL)
4053 reply->packet->options,
4063 check_pool6_threshold(reply, tmp);
4067 if (reply->old_ia != NULL) {
4068 ia_id = &reply->old_ia->iaid_duid;
4070 (
unsigned char *)ia_id->
data,
4077 ia_id = &reply->ia->iaid_duid;
4079 ia_id->
len, reply->ia,
MDL);
4083 schedule_lease_timeout_reply(reply);
4087 if (packet_ia != NULL)
4089 if (reply->reply_ia != NULL)
4091 if (ia_data.data != NULL)
4093 if (
data.data != NULL)
4095 if (reply->ia != NULL)
4097 if (reply->old_ia != NULL)
4099 if (reply->lease != NULL)
4101 if (reply->on_star.on_expiry != NULL)
4103 (&reply->on_star.on_expiry,
MDL);
4104 if (reply->on_star.on_release != NULL)
4106 (&reply->on_star.on_release,
MDL);
4113 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
4135 static struct group *
4136 find_group_by_prefix(
struct reply_state *reply) {
4138 struct group *group = reply->shared->group;
4139 struct subnet *subnet = NULL;
4140 struct iaddr tmp_addr;
4145 reply->fixed_pref.lo_addr,
MDL) != 0) {
4146 group = subnet->
group;
4147 subnet_dereference(&subnet,
MDL);
4154 memset(&fixed_addr, 0,
sizeof(fixed_addr));
4156 if ((reply->host->fixed_addr != NULL) &&
4159 reply->host->fixed_addr,
MDL))) {
4160 if (fixed_addr.len >= 16) {
4162 memcpy(tmp_addr.iabuf, fixed_addr.data, 16);
4164 tmp_addr,
MDL) != 0) {
4165 group = subnet->
group;
4166 subnet_dereference(&subnet,
MDL);
4183 reply_process_prefix(
struct reply_state *reply,
struct option_cache *pref) {
4184 u_int32_t pref_life, valid_life;
4189 isc_result_t status = ISC_R_SUCCESS;
4190 struct group *group;
4193 memset(&iapref, 0,
sizeof(iapref));
4194 memset(&data, 0,
sizeof(data));
4201 if ((reply->cursor + 29) >
sizeof(reply->buf)) {
4202 log_error(
"reply_process_prefix: Out of room for prefix.");
4203 return ISC_R_NOSPACE;
4211 log_error(
"reply_process_prefix: error evaluating IAPREFIX.");
4212 status = ISC_R_FAILURE;
4221 valid_life =
getULong(iapref.data + 4);
4223 if ((reply->client_valid == 0) ||
4224 (reply->client_valid > valid_life))
4225 reply->client_valid = valid_life;
4227 if ((reply->client_prefer == 0) ||
4228 (reply->client_prefer > pref_life))
4229 reply->client_prefer = pref_life;
4235 tmp_pref.lo_addr.len = 16;
4236 memset(tmp_pref.lo_addr.iabuf, 0, 16);
4237 if ((iapref.data[8] == 0) &&
4238 (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
4247 tmp_pref.bits = (
int) iapref.data[8];
4248 if (reply->preflen < 0) {
4250 reply->preflen = tmp_pref.bits;
4252 if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
4256 memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
4259 if (!prefix_is_owned(reply, &tmp_pref)) {
4264 status = reply_process_try_prefix(reply, &tmp_pref);
4267 if ((status != ISC_R_SUCCESS) &&
4268 (status != ISC_R_ADDRINUSE) &&
4269 (status != ISC_R_ADDRNOTAVAIL))
4272 if (reply->lease == NULL) {
4273 if (reply->packet->dhcpv6_msg_type ==
4275 reply->send_prefer = 0;
4276 reply->send_valid = 0;
4295 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
4299 log_error(
"reply_process_prefix: No memory " 4300 "for option state wipe.");
4301 status = ISC_R_NOMEMORY;
4307 "Prefix not bound to this " 4308 "interface.", reply->reply_ia)) {
4309 log_error(
"reply_process_prefix: Unable to " 4310 "attach status code.");
4311 status = ISC_R_FAILURE;
4316 status = ISC_R_CANCELED;
4319 log_error(
"It is impossible to lease a client that is " 4320 "not sending a solicit, request, renew, or " 4322 status = ISC_R_FAILURE;
4327 if (reply->static_prefixes > 0) {
4328 if (reply->host == NULL)
4334 memcpy(&reply->fixed_pref, &tmp_pref,
sizeof(tmp_pref));
4337 group = find_group_by_prefix(reply);
4339 if (reply->lease == NULL)
4342 scope = &reply->lease->scope;
4343 group = reply->lease->ipv6_pool->ipv6_pond->group;
4352 if (reply->client_resources != 0) {
4365 reply->packet->options,
4369 log_error(
"reply_process_prefix: unable to " 4370 "evaluate prefs-per-ia value.");
4371 status = ISC_R_FAILURE;
4383 if (reply->client_resources >= limit)
4387 status = reply_process_is_prefixed(reply, scope, group);
4388 if (status != ISC_R_SUCCESS)
4392 status = reply_process_send_prefix(reply, &tmp_pref);
4395 if (iapref.data != NULL)
4397 if (data.data != NULL)
4399 if (reply->lease != NULL)
4411 static isc_boolean_t
4412 prefix_is_owned(
struct reply_state *reply,
struct iaddrcidrnet *pref) {
4420 if (reply->static_prefixes > 0) {
4421 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4430 if ((reply->old_ia == NULL) ||
4431 (reply->old_ia->num_iasubopt == 0))
4434 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4437 tmp = reply->old_ia->iasubopt[i];
4439 if ((pref->
bits == (
int) tmp->
plen) &&
4465 reply_process_try_prefix(
struct reply_state *reply,
4467 isc_result_t status = ISC_R_ADDRNOTAVAIL;
4473 if ((reply == NULL) || (reply->shared == NULL) ||
4474 (pref == NULL) || (reply->lease != NULL))
4481 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4485 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4495 return (ISC_R_ADDRNOTAVAIL);
4498 memset(&data_pref, 0,
sizeof(data_pref));
4501 log_error(
"reply_process_try_prefix: out of memory.");
4502 return (ISC_R_NOMEMORY);
4504 data_pref.data = data_pref.buffer->data;
4505 data_pref.buffer->data[0] = (u_int8_t) pref->
bits;
4506 memcpy(data_pref.buffer->data + 1, pref->
lo_addr.
iabuf, 16);
4516 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4523 for (i = 0; (pool = pond->
ipv6_pools[i]) != NULL; i++) {
4528 status = try_client_v6_prefix(&reply->lease, pool,
4532 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4535 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4549 find_client_prefix(
struct reply_state *reply) {
4551 isc_result_t status = ISC_R_NORESOURCES;
4552 struct iasubopt *prefix, *best_prefix = NULL;
4555 struct group *group;
4557 if (reply->static_prefixes > 0) {
4560 if (reply->host == NULL)
4563 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4572 l = reply->host->fixed_prefix;
4574 memcpy(&send_pref, &l->
cidrnet,
sizeof(send_pref));
4579 memcpy(&reply->fixed_pref, &l->
cidrnet,
sizeof(send_pref));
4582 group = find_group_by_prefix(reply);
4587 if (reply->old_ia != NULL) {
4588 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4592 prefix = reply->old_ia->iasubopt[i];
4601 if (((candidate_shared != NULL) &&
4602 (candidate_shared != reply->shared)) ||
4616 best_prefix = prefix_compare(reply, prefix,
4625 status = pick_v6_prefix(reply);
4626 }
else if (best_prefix != NULL) {
4628 status = ISC_R_SUCCESS;
4632 if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
4634 log_error(
"Reclaiming abandoned prefixes is not yet " 4635 "supported. Treating this as an out of space " 4641 if (status != ISC_R_SUCCESS)
4644 if (reply->lease == NULL)
4647 scope = &reply->lease->scope;
4648 group = reply->lease->ipv6_pool->ipv6_pond->group;
4650 send_pref.lo_addr.len = 16;
4651 memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
4652 send_pref.bits = (
int) reply->lease->plen;
4655 status = reply_process_is_prefixed(reply, scope, group);
4656 if (status != ISC_R_SUCCESS)
4659 status = reply_process_send_prefix(reply, &send_pref);
4668 reply_process_is_prefixed(
struct reply_state *reply,
4671 isc_result_t status = ISC_R_SUCCESS;
4675 struct on_star *on_star;
4679 memset(&data, 0,
sizeof(data));
4688 on_star = &reply->lease->on_star;
4690 on_star = &reply->on_star;
4700 reply->packet->options, tmp_options,
4703 if (tmp_options != NULL) {
4713 reply->packet->options, reply->opt_state,
4717 for (i = reply->packet->class_count; i > 0; i--) {
4719 reply->packet->options,
4720 reply->opt_state, scope,
4721 reply->packet->classes[i - 1]->group,
4730 if (reply->host != NULL)
4732 reply->packet->options,
4733 reply->opt_state, scope,
4734 reply->host->group, group,
4738 if (reply->client_valid == 0)
4741 reply->send_valid = reply->client_valid;
4747 reply->packet->options,
4751 log_error(
"reply_process_is_prefixed: unable to " 4752 "evaluate default prefix time");
4753 status = ISC_R_FAILURE;
4757 reply->send_valid =
getULong(data.data);
4767 time_t test_time =
cur_time + reply->send_valid;
4772 if (reply->client_prefer == 0)
4773 reply->send_prefer = reply->send_valid;
4775 reply->send_prefer = reply->client_prefer;
4777 if ((reply->send_prefer >= reply->send_valid) &&
4779 reply->send_prefer = (reply->send_valid / 2) +
4780 (reply->send_valid / 8);
4786 reply->packet->options,
4790 log_error(
"reply_process_is_prefixed: unable to " 4791 "evaluate preferred prefix time");
4792 status = ISC_R_FAILURE;
4796 reply->send_prefer =
getULong(data.data);
4801 if (reply->min_prefer > reply->send_prefer)
4802 reply->min_prefer = reply->send_prefer;
4804 if (reply->min_valid > reply->send_valid)
4805 reply->min_valid = reply->send_valid;
4808 if (reply->lease != NULL) {
4810 reply->lease->prefer = reply->send_prefer;
4811 reply->lease->valid = reply->send_valid;
4819 reply->lease->soft_lifetime_end_time =
MAX_TIME;
4821 reply->lease->soft_lifetime_end_time =
4828 if (status != ISC_R_SUCCESS) {
4829 log_fatal(
"reply_process_is_prefixed: Unable to " 4830 "attach prefix to new IA_PD: %s",
4831 isc_result_totext(status));
4837 if (reply->lease->ia == NULL) {
4844 reply->packet->options, reply->reply_ia,
4848 for (i = reply->packet->class_count; i > 0; i--) {
4850 reply->packet->options,
4851 reply->reply_ia, scope,
4852 reply->packet->classes[i - 1]->group,
4860 if (reply->host != NULL)
4862 reply->packet->options,
4863 reply->reply_ia, scope,
4864 reply->host->group, group, NULL);
4867 if (data.data != NULL)
4870 if (status == ISC_R_SUCCESS)
4871 reply->client_resources++;
4878 reply_process_send_prefix(
struct reply_state *reply,
4880 isc_result_t status = ISC_R_SUCCESS;
4888 log_error(
"reply_process_send_prefix: out of memory" 4889 "allocating new IAPREFIX buffer.");
4890 status = ISC_R_NOMEMORY;
4903 log_error(
"reply_process_send_prefix: unable " 4904 "to save IAPREFIX option");
4905 status = ISC_R_FAILURE;
4909 reply->resources_included = ISC_TRUE;
4912 if (
data.data != NULL)
4920 prefix_compare(
struct reply_state *reply,
4927 if (reply->preflen >= 0) {
4928 if ((alpha->
plen == reply->preflen) &&
4929 (beta->
plen != reply->preflen))
4931 if ((beta->
plen == reply->preflen) &&
4932 (alpha->
plen != reply->preflen))
4936 switch(alpha->
state) {
4938 switch(beta->
state) {
4959 switch (beta->
state) {
4985 switch (beta->
state) {
5007 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
5021 dhcpv6_solicit(
struct data_string *reply_ret,
struct packet *packet) {
5027 if (!valid_client_msg(packet, &client_id)) {
5031 lease_to_client(reply_ret, packet, &client_id, NULL);
5046 dhcpv6_request(
struct data_string *reply_ret,
struct packet *packet) {
5053 if (!valid_client_resp(packet, &client_id, &server_id)) {
5059 if (packet->
unicast == ISC_TRUE &&
5060 is_unicast_option_defined(packet) == ISC_FALSE) {
5061 unicast_reject(reply_ret, packet, &client_id, &server_id);
5066 lease_to_client(reply_ret, packet, &client_id, &server_id);
5080 struct packet *packet)
5082 const struct packet *chk_packet;
5083 const struct in6_addr *link_addr, *first_link_addr;
5084 struct iaddr tmp_addr;
5085 struct subnet *subnet;
5086 isc_result_t status;
5088 if ((shared == NULL) || (*shared != NULL) || (packet == NULL))
5095 first_link_addr = NULL;
5097 while (chk_packet != NULL) {
5099 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
5100 !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
5101 first_link_addr = link_addr;
5112 if (first_link_addr != NULL) {
5113 tmp_addr.len =
sizeof(*first_link_addr);
5114 memcpy(tmp_addr.iabuf,
5115 first_link_addr,
sizeof(*first_link_addr));
5118 log_debug(
"No subnet found for link-address %s.",
5120 return ISC_R_NOTFOUND;
5122 status = shared_network_reference(shared,
5124 subnet_dereference(&subnet,
MDL);
5131 status = shared_network_reference(shared,
5135 log_info(
"[L2 Relay] No link address in relay packet " 5136 "assuming L2 relay and using receiving " 5146 log_error(
"No interface and no link address " 5147 "can't determine pool");
5173 dhcpv6_confirm(
struct data_string *reply_ret,
struct packet *packet) {
5175 struct subnet *subnet;
5177 struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
5179 struct iaddr cli_addr;
5181 isc_boolean_t inappropriate, has_addrs;
5182 char reply_data[65536];
5189 memset(&client_id, 0,
sizeof(client_id));
5190 if (!valid_client_msg(packet, &client_id)) {
5199 if ((ia == NULL) && (ta == NULL))
5210 opt_state = cli_enc_opt_state = NULL;
5211 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5212 memset(&iaaddr, 0,
sizeof(iaaddr));
5213 memset(&packet_oro, 0,
sizeof(packet_oro));
5220 if ((shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS) ||
5232 has_addrs = inappropriate = ISC_FALSE;
5234 while(!inappropriate) {
5238 if ((pass ==
D6O_IA_NA) && (ia == NULL)) {
5248 !get_encapsulated_IA_state(&cli_enc_opt_state,
5252 !get_encapsulated_IA_state(&cli_enc_opt_state,
5261 for ( ; oc != NULL ; oc = oc->
next) {
5267 "error evaluating IAADDR.");
5273 memcpy(cli_addr.iabuf, iaaddr.data, 16);
5278 has_addrs = ISC_TRUE;
5281 for (subnet = shared->
subnets ; subnet != NULL ;
5296 if (subnet == NULL) {
5297 inappropriate = ISC_TRUE;
5316 if (!start_reply(packet, &client_id, NULL, &opt_state, reply)) {
5323 if (inappropriate) {
5325 "Some of the addresses are not on link.",
5331 "All addresses still on link.",
5341 sizeof(reply_data)-reply_ofs,
5343 required_opts, &packet_oro);
5348 reply_ret->
len = reply_ofs;
5349 reply_ret->
buffer = NULL;
5354 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5358 if (cli_enc_opt_data.buffer != NULL)
5360 if (iaaddr.buffer != NULL)
5362 if (client_id.
buffer != NULL)
5364 if (packet_oro.buffer != NULL)
5368 if (cli_enc_opt_state != NULL)
5370 if (opt_state != NULL)
5382 dhcpv6_renew(
struct data_string *reply,
struct packet *packet) {
5389 if (!valid_client_resp(packet, &client_id, &server_id)) {
5395 if (packet->
unicast == ISC_TRUE &&
5396 is_unicast_option_defined(packet) == ISC_FALSE) {
5397 unicast_reject(reply, packet, &client_id, &server_id);
5402 lease_to_client(reply, packet, &client_id, &server_id);
5420 dhcpv6_rebind(
struct data_string *reply,
struct packet *packet) {
5423 if (!valid_client_msg(packet, &client_id)) {
5427 lease_to_client(reply, packet, &client_id, NULL);
5433 ia_na_match_decline(
const struct data_string *client_id,
5437 char tmp_addr[INET6_ADDRSTRLEN];
5439 log_error(
"Client %s reports address %s is " 5440 "already in use by another host!",
5442 inet_ntop(AF_INET6, iaaddr->
data,
5443 tmp_addr,
sizeof(tmp_addr)));
5444 if (lease != NULL) {
5452 ia_na_nomatch_decline(
const struct data_string *client_id,
5454 u_int32_t *ia_na_id,
5455 struct packet *packet,
5460 char tmp_addr[INET6_ADDRSTRLEN];
5464 log_info(
"Client %s declines address %s, which is not offered to it.",
5466 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5471 host_opt_state = NULL;
5473 log_error(
"ia_na_nomatch_decline: out of memory " 5474 "allocating option_state.");
5486 if (reply_len < (*reply_ofs + 16)) {
5488 "out of space for reply packet.");
5496 reply_len-(*reply_ofs)-16,
5497 host_opt_state, packet,
5498 required_opts_STATUS_CODE, NULL);
5508 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5510 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5512 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5513 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5518 *reply_ofs += (len + 16);
5526 struct packet *packet,
5529 const char *packet_type,
5530 void (*ia_na_match)(),
5531 void (*ia_na_nomatch)())
5543 char reply_data[65536];
5546 char status_msg[32];
5548 struct ia_xx *existing_ia_na;
5557 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5558 cli_enc_opt_state = NULL;
5559 memset(&iaaddr, 0,
sizeof(iaaddr));
5560 memset(&fixed_addr, 0,
sizeof(fixed_addr));
5581 log_error(
"iterate_over_ia_na: no memory for option_state.");
5594 (
unsigned char *)server_duid.data,
5597 "error saving server identifier.");
5604 (
unsigned char *)client_id->
data,
5608 "error saving client identifier.");
5612 snprintf(status_msg,
sizeof(status_msg),
"%s received.", packet_type);
5621 sizeof(reply_data)-reply_ofs,
5623 required_opts, NULL);
5630 ia != NULL; ia = ia->
next) {
5632 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5638 iaid =
getULong(cli_enc_opt_data.data);
5656 memset(&iaaddr, 0,
sizeof(iaaddr));
5661 "error evaluating IAADDR.");
5675 cli_enc_opt_state,
MDL)) {
5676 if (packet_host != NULL) {
5682 while (host != NULL) {
5690 "evaluating host address.");
5693 if ((iaaddr.
len >= 16) &&
5694 !memcmp(fixed_addr.data, iaaddr.
data, 16)) {
5708 (
char *)client_id->
data,
5710 MDL) != ISC_R_SUCCESS) {
5711 log_fatal(
"iterate_over_ia_na: no memory for " 5715 existing_ia_na = NULL;
5717 (
unsigned char *)key.data,
5724 struct in6_addr *in6_addr;
5727 in6_addr = &tmp->
addr;
5728 if (memcmp(in6_addr,
5729 iaaddr.
data, 16) == 0) {
5740 if ((host != NULL) || (lease != NULL)) {
5741 ia_na_match(client_id, &iaaddr, lease);
5743 ia_na_nomatch(client_id, &iaaddr,
5744 (u_int32_t *)cli_enc_opt_data.
data,
5745 packet, reply_data, &reply_ofs,
5746 sizeof(reply_data));
5749 if (lease != NULL) {
5761 reply_ret->
len = reply_ofs;
5762 reply_ret->
buffer = NULL;
5767 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5770 if (lease != NULL) {
5773 if (fixed_addr.buffer != NULL) {
5776 if (iaaddr.
buffer != NULL) {
5779 if (cli_enc_opt_state != NULL) {
5782 if (cli_enc_opt_data.buffer != NULL) {
5785 if (opt_state != NULL) {
5805 dhcpv6_decline(
struct data_string *reply,
struct packet *packet) {
5812 if (!valid_client_resp(packet, &client_id, &server_id)) {
5818 if (packet->
unicast == ISC_TRUE &&
5819 is_unicast_option_defined(packet) == ISC_FALSE) {
5820 unicast_reject(reply, packet, &client_id, &server_id);
5830 iterate_over_ia_na(reply, packet, &client_id, &server_id,
5831 "Decline", ia_na_match_decline,
5832 ia_na_nomatch_decline);
5841 ia_na_match_release(
const struct data_string *client_id,
5845 char tmp_addr[INET6_ADDRSTRLEN];
5847 log_info(
"Client %s releases address %s",
5849 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5850 if (lease != NULL) {
5858 ia_na_nomatch_release(
const struct data_string *client_id,
5860 u_int32_t *ia_na_id,
5861 struct packet *packet,
5866 char tmp_addr[INET6_ADDRSTRLEN];
5870 log_info(
"Client %s releases address %s, which is not leased to it.",
5872 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5877 host_opt_state = NULL;
5879 log_error(
"ia_na_nomatch_release: out of memory " 5880 "allocating option_state.");
5885 "Release for non-leased address.",
5893 if (reply_len < (*reply_ofs + 16)) {
5895 "out of space for reply packet.");
5903 reply_len-(*reply_ofs)-16,
5904 host_opt_state, packet,
5905 required_opts_STATUS_CODE, NULL);
5915 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5917 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5919 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5920 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5925 *reply_ofs += (len + 16);
5932 ia_pd_match_release(
const struct data_string *client_id,
5936 char tmp_addr[INET6_ADDRSTRLEN];
5938 log_info(
"Client %s releases prefix %s/%u",
5940 inet_ntop(AF_INET6, iapref->
data + 9,
5941 tmp_addr,
sizeof(tmp_addr)),
5943 if (prefix != NULL) {
5951 ia_pd_nomatch_release(
const struct data_string *client_id,
5953 u_int32_t *ia_pd_id,
5954 struct packet *packet,
5959 char tmp_addr[INET6_ADDRSTRLEN];
5963 log_info(
"Client %s releases prefix %s/%u, which is not leased to it.",
5965 inet_ntop(AF_INET6, iapref->
data + 9,
5966 tmp_addr,
sizeof(tmp_addr)),
5972 host_opt_state = NULL;
5974 log_error(
"ia_pd_nomatch_release: out of memory " 5975 "allocating option_state.");
5980 "Release for non-leased prefix.",
5988 if (reply_len < (*reply_ofs + 16)) {
5990 "out of space for reply packet.");
5998 reply_len-(*reply_ofs)-16,
5999 host_opt_state, packet,
6000 required_opts_STATUS_CODE, NULL);
6010 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
6012 memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
6014 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
6015 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
6020 *reply_ofs += (len + 16);
6028 struct packet *packet,
6031 const char *packet_type,
6032 void (*ia_pd_match)(),
6033 void (*ia_pd_nomatch)())
6046 char reply_data[65536];
6049 struct ia_xx *existing_ia_pd;
6057 memset(&reply_new, 0,
sizeof(reply_new));
6059 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
6060 cli_enc_opt_state = NULL;
6061 memset(&iaprefix, 0,
sizeof(iaprefix));
6067 reply_len =
sizeof(reply_data) - reply_ret->
len;
6081 log_error(
"iterate_over_ia_pd: no memory for option_state.");
6093 ia != NULL; ia = ia->
next) {
6095 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
6101 iaid =
getULong(cli_enc_opt_data.data);
6112 for (; oc != NULL; oc = oc->
next) {
6113 memset(&iaprefix, 0,
sizeof(iaprefix));
6118 "error evaluating IAPREFIX.");
6132 cli_enc_opt_state,
MDL)) {
6133 if (packet_host != NULL) {
6139 while (host != NULL) {
6148 if (memcmp(iaprefix.data + 9,
6153 if ((l != NULL) && (iaprefix.len >= 17))
6164 (
char *)client_id->
data,
6166 MDL) != ISC_R_SUCCESS) {
6167 log_fatal(
"iterate_over_ia_pd: no memory for " 6171 existing_ia_pd = NULL;
6173 (
unsigned char *)key.data,
6184 plen =
getUChar(iaprefix.data + 8);
6186 if ((tmp->
plen == plen) &&
6200 if ((host != NULL) || (prefix != NULL)) {
6201 ia_pd_match(client_id, &iaprefix, prefix);
6203 ia_pd_nomatch(client_id, &iaprefix,
6204 (u_int32_t *)cli_enc_opt_data.
data,
6205 packet, reply_data, &reply_ofs,
6206 reply_len - reply_ofs);
6209 if (prefix != NULL) {
6224 reply_new.len = reply_ret->
len + reply_ofs;
6228 reply_new.data = reply_new.buffer->data;
6229 memcpy(reply_new.buffer->data,
6231 memcpy(reply_new.buffer->data + reply_ret->
len,
6232 reply_data, reply_ofs);
6238 if (prefix != NULL) {
6241 if (iaprefix.buffer != NULL) {
6244 if (cli_enc_opt_state != NULL) {
6247 if (cli_enc_opt_data.buffer != NULL) {
6250 if (opt_state != NULL) {
6260 dhcpv6_release(
struct data_string *reply,
struct packet *packet) {
6267 if (!valid_client_resp(packet, &client_id, &server_id)) {
6273 if (packet->
unicast == ISC_TRUE &&
6274 is_unicast_option_defined(packet) == ISC_FALSE) {
6275 unicast_reject(reply, packet, &client_id, &server_id);
6280 iterate_over_ia_na(reply, packet, &client_id, &server_id,
6281 "Release", ia_na_match_release,
6282 ia_na_nomatch_release);
6287 iterate_over_ia_pd(reply, packet, &client_id, &server_id,
6288 "Release", ia_pd_match_release,
6289 ia_pd_nomatch_release);
6302 dhcpv6_information_request(
struct data_string *reply,
struct packet *packet) {
6309 if (!valid_client_info_req(packet, &server_id)) {
6316 memset(&client_id, 0,
sizeof(client_id));
6327 lease_to_client(reply, packet, &client_id,
6328 server_id.
data != NULL ? &server_id : NULL);
6333 if (client_id.
data != NULL) {
6350 dhcpv6_relay_forw(
struct data_string *reply_ret,
struct packet *packet) {
6353 struct packet *enc_packet;
6354 unsigned char msg_type;
6358 char link_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6359 char peer_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6362 static char reply_data[65536];
6370 memset(&a_opt, 0,
sizeof(a_opt));
6371 memset(&packet_ero, 0,
sizeof(packet_ero));
6372 memset(&enc_reply, 0,
sizeof(enc_reply));
6373 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6382 link_addr,
sizeof(link_addr));
6384 peer_addr,
sizeof(peer_addr));
6385 log_info(
"Relay-forward from %s with link address=%s and " 6386 "peer address=%s missing Relay Message option.",
6394 log_error(
"dhcpv6_forw_relay: error evaluating " 6395 "relayed message.");
6401 log_error(
"dhcpv6_forw_relay: encapsulated packet too short.");
6412 "no memory for encapsulated packet.");
6419 "no memory for encapsulated packet's options.");
6428 msg_type = enc_opt_data.
data[0];
6444 enc_opt_data.
len - relaylen,
6456 "unsupported %s message type.",
6460 forw_dhcpv4_query(packet);
6463 log_error(
"dhcpv6_relay_forw: unsupported %s message type.",
6479 enc_opt_data.
len - msglen,
6491 build_dhcpv6_reply(&enc_reply, enc_packet);
6497 if (enc_reply.data == NULL) {
6519 log_error(
"dhcpv6_relay_forw: no memory for option state.");
6533 log_error(
"dhcpv6_relay_forw: error evaluating " 6538 (
unsigned char *)a_opt.data,
6541 log_error(
"dhcpv6_relay_forw: error saving " 6552 (
unsigned char *)enc_reply.data,
6555 log_error(
"dhcpv6_relay_forw: error saving Relay MSG.");
6571 (packet_ero.len & 1)) {
6572 log_error(
"dhcpv6_relay_forw: error evaluating ERO.");
6577 for (i = 0; i < packet_ero.len; i += 2) {
6594 "evaluating option %u.", req);
6600 (
unsigned char *)a_opt.data,
6604 log_error(
"dhcpv6_relay_forw: error saving " 6613 sizeof(reply_data) - reply_ofs,
6615 required_opts_agent, &packet_ero);
6620 reply_ret->
len = reply_ofs;
6621 reply_ret->
buffer = NULL;
6626 memcpy(reply_ret->
buffer->
data, reply_data, reply_ofs);
6629 if (opt_state != NULL)
6631 if (a_opt.data != NULL) {
6634 if (packet_ero.data != NULL) {
6637 if (enc_reply.data != NULL) {
6640 if (enc_opt_data.
data != NULL) {
6643 if (enc_packet != NULL) {
6659 dhcp4o6_relay_forw(
struct data_string *reply_ret,
struct packet *packet) {
6662 struct packet *enc_packet;
6663 unsigned char msg_type;
6667 char link_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6668 char peer_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6671 static char reply_data[65536];
6679 memset(&a_opt, 0,
sizeof(a_opt));
6680 memset(&packet_ero, 0,
sizeof(packet_ero));
6681 memset(&enc_reply, 0,
sizeof(enc_reply));
6682 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6691 link_addr,
sizeof(link_addr));
6693 peer_addr,
sizeof(peer_addr));
6694 log_info(
"Relay-forward from %s with link address=%s and " 6695 "peer address=%s missing Relay Message option.",
6702 log_error(
"dhcp4o6_relay_forw: error evaluating " 6703 "relayed message.");
6709 "encapsulated packet too short.");
6718 "no memory for encapsulated packet.");
6724 "no memory for encapsulated packet's options.");
6733 msg_type = enc_opt_data.
data[0];
6749 enc_opt_data.
len - relaylen,
6769 enc_opt_data.
len - msglen,
6776 log_error(
"dhcp4o6_relay_forw: unexpected message of type %d.",
6785 build_dhcpv6_reply(&enc_reply, enc_packet);
6791 if (enc_reply.data == NULL) {
6812 log_error(
"dhcp4o6_relay_forw: no memory for option state.");
6826 log_error(
"dhcp4o6_relay_forw: error evaluating " 6831 (
unsigned char *)a_opt.data,
6834 log_error(
"dhcp4o6_relay_forw: error saving " 6845 (
unsigned char *)enc_reply.data,
6848 log_error(
"dhcp4o6_relay_forw: error saving Relay MSG.");
6864 (packet_ero.len & 1)) {
6865 log_error(
"dhcp4o6_relay_forw: error evaluating ERO.");
6870 for (i = 0; i < packet_ero.len; i += 2) {
6887 "evaluating option %u.", req);
6893 (
unsigned char *)a_opt.data,
6897 log_error(
"dhcp4o6_relay_forw: error saving " 6906 sizeof(reply_data) - reply_ofs,
6908 required_opts_agent, &packet_ero);
6913 reply_ret->
len = reply_ofs;
6914 reply_ret->
buffer = NULL;
6919 memcpy(reply_ret->
buffer->
data, reply_data, reply_ofs);
6922 if (opt_state != NULL)
6924 if (a_opt.data != NULL) {
6927 if (packet_ero.data != NULL) {
6930 if (enc_reply.data != NULL) {
6933 if (enc_opt_data.
data != NULL) {
6936 if (enc_packet != NULL) {
6951 dhcp4o6_dhcpv4_query(
struct data_string *reply_ret,
struct packet *packet) {
6954 struct packet *enc_packet;
6957 static char response_data[65536];
6965 memset(&enc_response, 0,
sizeof(enc_response));
6966 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6974 log_info(
"DHCPv4-query from %s missing DHCPv4 Message option.",
6981 log_error(
"dhcp4o6_dhcpv4_query: error evaluating " 6987 log_error(
"dhcp4o6_dhcpv4_query: DHCPv4 packet too short.");
6996 "no memory for encapsulated packet.");
7012 "discarding packet with bogus hlen.");
7018 log_error(
"dhcp4o6_dhcpv4_query: no memory for options.");
7038 memset(&dp, 0,
sizeof dp);
7064 if (enc_response.data == NULL) {
7081 log_error(
"dhcp4o6_dhcpv4_query: no memory for option state.");
7089 (
unsigned char *)enc_response.data,
7092 log_error(
"dhcp4o6_dhcpv4_query: error saving DHCPv4 MSG.");
7097 sizeof(response_data) - response_ofs,
7099 required_opts_4o6, NULL);
7104 reply_ret->
len = response_ofs;
7105 reply_ret->
buffer = NULL;
7107 log_fatal(
"dhcp4o6_dhcpv4_query: no memory to store reply.");
7110 memcpy(reply_ret->
buffer->
data, response_data, response_ofs);
7113 if (opt_state != NULL)
7115 if (enc_response.data != NULL) {
7118 if (enc_opt_data.
data != NULL) {
7121 if (enc_packet != NULL) {
7134 static void forw_dhcpv4_query(
struct packet *packet) {
7144 if ((packet->
raw == NULL) ||
7147 log_error(
"forw_dhcpv4_query: can't find initial message.");
7153 memset(&ds, 0,
sizeof(ds));
7156 "no memory for encapsulating packet.");
7159 ds.data = ds.buffer->data;
7163 strncpy((
char *)ds.buffer->data, packet->
interface->
name, 16);
7164 memcpy(ds.buffer->data + 16,
7166 memcpy(ds.buffer->data + 32,
7167 (
unsigned char *)packet->
raw,
7171 cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
7173 log_error(
"forw_dhcpv4_query: send(): %m");
7179 dhcpv6_discard(
struct packet *packet) {
7183 log_debug(
"Discarding %s from %s; message type not handled by server",
7189 build_dhcpv6_reply(
struct data_string *reply,
struct packet *packet) {
7190 memset(reply, 0,
sizeof(*reply));
7203 dhcpv6_solicit(reply, packet);
7206 dhcpv6_discard(packet);
7210 dhcpv6_request(reply, packet);
7214 dhcpv6_confirm(reply, packet);
7218 dhcpv6_renew(reply, packet);
7222 dhcpv6_rebind(reply, packet);
7225 dhcpv6_discard(packet);
7229 dhcpv6_release(reply, packet);
7233 dhcpv6_decline(reply, packet);
7236 dhcpv6_discard(packet);
7240 dhcpv6_information_request(reply, packet);
7245 dhcp4o6_relay_forw(reply, packet);
7248 dhcpv6_relay_forw(reply, packet);
7251 dhcpv6_discard(packet);
7258 dhcpv6_discard(packet);
7264 forw_dhcpv4_query(packet);
7266 dhcp4o6_dhcpv4_query(reply, packet);
7270 dhcpv6_discard(packet);
7273 dhcpv6_discard(packet);
7278 log_info(
"Discarding unknown DHCPv6 message type %d " 7285 log_packet_in(
const struct packet *packet) {
7288 char tmp_addr[INET6_ADDRSTRLEN];
7291 memset(&s, 0,
sizeof(s));
7300 "Unknown message type %d from %s port %d",
7309 inet_ntop(AF_INET6, addr,
7310 tmp_addr,
sizeof(tmp_addr)));
7313 inet_ntop(AF_INET6, addr,
7314 tmp_addr,
sizeof(tmp_addr)));
7345 dhcpv6(
struct packet *packet) {
7347 struct sockaddr_in6 to_addr;
7353 log_packet_in(packet);
7358 build_dhcpv6_reply(&reply, packet);
7360 if (reply.
data != NULL) {
7364 memset(&to_addr, 0,
sizeof(to_addr));
7365 to_addr.sin6_family = AF_INET6;
7373 #if defined (REPLY_TO_SOURCE_PORT) 7385 sizeof(to_addr.sin6_addr));
7387 log_info(
"Sending %s to %s port %d",
7390 ntohs(to_addr.sin6_port));
7393 reply.
data, reply.
len, &to_addr);
7394 if (send_ret != reply.
len) {
7395 log_error(
"dhcpv6: send_packet6() sent %d of %d bytes",
7396 send_ret, reply.
len);
7414 static void recv_dhcpv4_query(
struct data_string *raw) {
7418 struct packet *packet;
7419 unsigned char msg_type;
7427 memset(name, 0,
sizeof(name));
7428 memcpy(name, raw->
data, 16);
7430 if (!strcmp(name, ip->
name))
7434 log_error(
"recv_dhcpv4_query: can't find interface %s.",
7448 "short packet from %s, len %d, dropped",
7458 log_error(
"recv_dhcpv4_query: no memory for packet.");
7463 log_error(
"recv_dhcpv4_query: no memory for options.");
7474 msg_type = raw->
data[32];
7491 raw->
len - 32 - relaylen,
7511 raw->
len - 32 - msglen,
7519 log_error(
"recv_dhcpv4_query: unexpected message of type %d.",
7533 memset(&ds, 0,
sizeof(ds));
7540 "Unknown message type %d from %s",
7546 char tmp_addr[INET6_ADDRSTRLEN];
7551 inet_ntop(AF_INET6, addr,
7552 tmp_addr,
sizeof(tmp_addr)));
7555 inet_ntop(AF_INET6, addr,
7556 tmp_addr,
sizeof(tmp_addr)));
7570 build_dhcpv6_reply(&reply, packet);
7574 if (reply.
data == NULL)
7580 len = reply.
len + 32;
7581 memset(&ds, 0,
sizeof(ds));
7583 log_error(
"recv_dhcpv4_query: no memory.");
7586 ds.data = ds.buffer->data;
7589 memcpy(ds.buffer->data, name, 16);
7590 memcpy(ds.buffer->data + 16,
iaddr.
iabuf, 16);
7591 memcpy(ds.buffer->data + 32, reply.
data, reply.
len);
7592 cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
7594 log_error(
"recv_dhcpv4_query: send(): %m");
7609 host_reference(&hold, *hp,
MDL);
7610 host_dereference(hp,
MDL);
7612 while (seek != NULL) {
7615 else if (fixed_matches_shared(seek, shared))
7621 if ((seek == NULL) && (nofixed != NULL))
7625 host_reference(hp, seek,
MDL);
7628 static isc_boolean_t
7630 struct subnet *subnet;
7632 isc_boolean_t matched;
7638 memset(&addr, 0,
sizeof(addr));
7643 if (addr.len < 16) {
7649 memcpy(fixed.iabuf, addr.data, 16);
7651 matched = ISC_FALSE;
7652 for (subnet = shared->
subnets ; subnet != NULL ;
7683 struct packet *packet,
7687 struct reply_state reply;
7688 memset(&reply, 0x0,
sizeof(
struct reply_state));
7691 if (shared_network_from_packet6(&reply.shared, packet)
7693 log_error(
"unicast_reject: could not locate client.");
7701 if (start_reply(packet, client_id, server_id, &reply.opt_state,
7702 &reply.buf.reply)) {
7705 "Unicast not allowed by server.",
7707 log_error(
"unicast_reject: Unable to set status code.");
7717 unicast_reject_opts,
7721 reply_ret->
len = reply.cursor;
7722 reply_ret->
buffer = NULL;
7724 reply.cursor,
MDL)) {
7726 "No memory to store Reply.");
7737 if (reply.shared != NULL)
7738 shared_network_dereference(&reply.shared,
MDL);
7739 if (reply.opt_state != NULL)
7741 if (reply.packet != NULL)
7743 if (reply.client_id.
data != NULL)
7766 is_unicast_option_defined(
struct packet *packet) {
7767 isc_boolean_t is_defined = ISC_FALSE;
7774 "No memory for option state.");
7779 if (((shared_network_from_requested_addr(&shared, packet)
7780 != ISC_R_SUCCESS) &&
7781 (shared_network_from_packet6(&shared, packet) != ISC_R_SUCCESS))
7782 || (shared == NULL)) {
7786 "cannot attribute packet to a network.");
7797 is_defined = (oc != NULL ? ISC_TRUE : ISC_FALSE);
7798 log_debug(
"is_unicast_option_defined: option found : %d", is_defined);
7800 if (shared != NULL) {
7801 shared_network_dereference(&shared,
MDL);
7804 if (opt_state != NULL) {
7808 return (is_defined);
7827 shared_network_from_requested_addr (
struct shared_network **shared,
7828 struct packet* packet) {
7830 struct subnet* subnet = NULL;
7831 isc_result_t status = ISC_R_FAILURE;
7836 if ((get_first_ia_addr_val(packet,
D6O_IA_NA, &
iaddr) != ISC_R_SUCCESS)
7840 != ISC_R_SUCCESS)) {
7842 log_debug(
"share_network_from_request_addr: nothing to match");
7843 return (ISC_R_FAILURE);
7847 log_debug(
"shared_network_from_requested_addr:" 7850 status = shared_network_reference(shared,
7852 subnet_dereference(&subnet,
MDL);
7853 log_debug(
"shared_network_from_requested_addr:" 7854 " found shared network %s for address %s.",
7855 ((*shared)->name ? (*shared)->name :
"unnamed"),
7860 return (ISC_R_FAILURE);
7882 get_first_ia_addr_val (
struct packet* packet,
int addr_type,
7888 int addr_opt_offset;
7890 int addr_opt_data_len;
7893 isc_result_t status = ISC_R_FAILURE;
7894 memset(iaddr, 0,
sizeof(
struct iaddr));
7897 switch (addr_type) {
7901 addr_opt_data_len = 24;
7907 addr_opt_data_len = 24;
7913 addr_opt_data_len = 25;
7918 log_error (
"get_first_ia_addr_val: invalid opt type %d",
7920 return (ISC_R_FAILURE);
7925 ia != NULL && oc == NULL; ia = ia->
next) {
7926 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
7928 packet, ia, addr_opt_offset)) {
7930 " couldn't unroll enclosing option");
7931 return (ISC_R_FAILURE);
7947 memset(&iaddr_str, 0,
sizeof(iaddr_str));
7952 "error evaluating IA_XX option.");
7954 if (iaddr_str.len != addr_opt_data_len) {
7955 log_error(
"shared_network_from_requested_addr:" 7956 " invalid length %d, expected %d",
7957 iaddr_str.len, addr_opt_data_len);
7960 memcpy (iaddr->
iabuf,
7961 iaddr_str.data + ip_addr_offset, 16);
7962 status = ISC_R_SUCCESS;
8004 set_reply_tee_times(
struct reply_state* reply,
unsigned ia_cursor)
8012 set_tee_times = (oc &&
8015 reply->packet->options,
8027 reply->packet->options,
8037 if (
data.data != NULL)
8039 }
else if (set_tee_times) {
8045 reply->renew = 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) {
8080 reply->rebind = (reply->min_prefer / 5) * 4;
8086 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 *)
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
#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)