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,
33 u_int8_t rsp_opt_exist;
37 static int offset_data4o6 = 36;
73 unsigned client_resources;
74 isc_boolean_t resources_included;
75 isc_boolean_t static_lease;
76 unsigned static_prefixes;
90 u_int32_t renew, rebind, min_prefer, min_valid;
93 u_int32_t client_valid, client_prefer;
96 u_int32_t send_valid, send_prefer;
108 unsigned char data[65536];
116 static int get_encapsulated_IA_state(
struct option_state **enc_opt_state,
122 static isc_result_t shared_network_from_packet6(
struct shared_network **shared,
124 static void seek_shared_host(
struct host_decl **hp,
126 static isc_boolean_t fixed_matches_shared(
struct host_decl *host,
128 static isc_result_t reply_process_ia_na(
struct reply_state *reply,
130 static isc_result_t reply_process_ia_ta(
struct reply_state *reply,
132 static isc_result_t reply_process_addr(
struct reply_state *reply,
134 static isc_boolean_t address_is_owned(
struct reply_state *reply,
136 static isc_boolean_t temporary_is_available(
struct reply_state *reply,
138 static isc_result_t find_client_temporaries(
struct reply_state *reply);
139 static isc_result_t reply_process_try_addr(
struct reply_state *reply,
141 static isc_result_t find_client_address(
struct reply_state *reply);
142 static isc_result_t reply_process_is_addressed(
struct reply_state *reply,
145 static isc_result_t reply_process_send_addr(
struct reply_state *reply,
149 static isc_result_t reply_process_ia_pd(
struct reply_state *reply,
151 static struct group *find_group_by_prefix(
struct reply_state *reply);
152 static isc_result_t reply_process_prefix(
struct reply_state *reply,
154 static isc_boolean_t prefix_is_owned(
struct reply_state *reply,
156 static isc_result_t find_client_prefix(
struct reply_state *reply);
157 static isc_result_t reply_process_try_prefix(
struct reply_state *reply,
159 static isc_result_t reply_process_is_prefixed(
struct reply_state *reply,
162 static isc_result_t reply_process_send_prefix(
struct reply_state *reply,
164 static struct iasubopt *prefix_compare(
struct reply_state *reply,
167 static void schedule_lease_timeout_reply(
struct reply_state *reply);
169 static int eval_prefix_mode(
int thislen,
int preflen,
int prefix_mode);
170 static isc_result_t pick_v6_prefix_helper(
struct reply_state *reply,
177 static isc_boolean_t is_unicast_option_defined(
struct packet *
packet);
178 static isc_result_t shared_network_from_requested_addr (
struct shared_network 181 static isc_result_t get_first_ia_addr_val (
struct packet*
packet,
int addr_type,
185 set_reply_tee_times(
struct reply_state* reply,
unsigned ia_cursor);
187 static const char *iasubopt_plen_str(
struct iasubopt *
lease);
188 static int release_on_roam(
struct reply_state *reply);
190 static int reuse_lease6(
struct reply_state *reply,
struct iasubopt *
lease);
191 static void shorten_lifetimes(
struct reply_state *reply,
struct iasubopt *
lease,
192 time_t age,
int threshold);
193 static void write_to_packet(
struct reply_state *reply,
unsigned ia_cursor);
194 static const char *iasubopt_plen_str(
struct iasubopt *
lease);
197 static void ddns_update_static6(
struct reply_state* reply);
217 if (h->type != dhcp4o6_type)
220 cc = recv(dhcp4o6_fd, buf,
sizeof(buf), 0);
223 return ISC_R_UNEXPECTED;
224 memset(&raw, 0,
sizeof(raw));
226 log_error(
"dhcpv4o6_handler: no memory buffer.");
227 return ISC_R_NOMEMORY;
229 raw.data = raw.buffer->data;
231 memcpy(raw.buffer->data, buf, cc);
234 send_dhcpv4_response(&raw);
236 recv_dhcpv4_query(&raw);
241 return ISC_R_SUCCESS;
252 static void send_dhcpv4_response(
struct data_string *raw) {
255 struct sockaddr_in6 to_addr;
256 char pbuf[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
257 struct udp_data4o6 udp_data;
260 memset(name, 0,
sizeof(name));
261 memcpy(name, raw->
data, 16);
263 if (!strcmp(name,
ip->name))
267 log_error(
"send_dhcpv4_response: can't find interface %s.",
272 memset(&to_addr, 0,
sizeof(to_addr));
273 to_addr.sin6_family = AF_INET6;
274 memcpy(&to_addr.sin6_addr, raw->
data + 16, 16);
275 memset(&udp_data, 0,
sizeof(udp_data));
276 memcpy(&udp_data, raw->
data + 32, 4);
279 if (udp_data.rsp_opt_exist) {
280 to_addr.sin6_port = udp_data.src_port;
288 log_info(
"send_dhcpv4_response(): sending %s on %s to %s port %d",
291 inet_ntop(AF_INET6, raw->
data + 16, pbuf,
sizeof(pbuf)),
292 ntohs(to_addr.sin6_port));
296 log_error(
"send_dhcpv4_response: send_packet6(): %m");
297 }
else if (send_ret != raw->
len - 36) {
298 log_error(
"send_dhcpv4_response: send_packet6() " 299 "sent %d of %d bytes",
300 send_ret, raw->
len - 36);
311 schedule_lease_timeout_reply(
struct reply_state *reply) {
316 if ((reply == NULL) || (reply->ia == NULL) || (reply->ia->iasubopt == NULL))
320 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
321 tmp = reply->ia->iasubopt[i];
331 duid_time(time_t when) {
368 return (server_duid.data != NULL);
406 isc_result_t ret_val;
419 ret_val = ISC_R_NOTFOUND;
421 memset(&option_duid, 0,
sizeof(option_duid));
425 ret_val = ISC_R_UNEXPECTED;
429 ret_val = ISC_R_SUCCESS;
448 static int server_duid_type =
DUID_LLT;
455 server_duid_type = type;
472 log_error(
"Invalid DUID type %d specified, " 473 "only LL and LLT types supported", server_duid_type);
486 log_error(
"Can not generate DUID from interfaces which do not have hardware addresses, please configure server-duid!");
490 return ISC_R_UNEXPECTED;
496 memset(&generated_duid, 0,
sizeof(generated_duid));
498 time_val = duid_time(time(NULL));
501 generated_duid.len,
MDL)) {
504 generated_duid.data = generated_duid.buffer->data;
506 putUShort(generated_duid.buffer->data + 2,
508 putULong(generated_duid.buffer->data + 4, time_val);
509 memcpy(generated_duid.buffer->data + 8,
511 }
else if (server_duid_type ==
DUID_LL) {
514 generated_duid.len,
MDL)) {
517 generated_duid.data = generated_duid.buffer->data;
519 putUShort(generated_duid.buffer->data + 2,
521 memcpy(generated_duid.buffer->data + 4,
524 log_fatal(
"Unsupported server DUID type %d.", server_duid_type);
530 return ISC_R_SUCCESS;
543 if ((client_id->
data != NULL) || (client_id->
len != 0)) {
549 return ISC_R_NOTFOUND;
555 return ISC_R_FAILURE;
558 return ISC_R_SUCCESS;
575 memset(client_id, 0,
sizeof(*client_id));
583 "client identifier missing",
588 log_error(
"Error processing %s from %s; " 589 "unable to evaluate Client Identifier",
599 log_debug(
"Discarding %s from %s; packet sent unicast " 614 "server identifier found " 615 "(CLIENTID %s, SERVERID %s)",
619 client_id->
data, 60),
624 "server identifier found " 628 client_id->
data, 60),
642 if (client_id->
len > 0) {
672 memset(client_id, 0,
sizeof(*client_id));
673 memset(server_id, 0,
sizeof(*server_id));
680 "client identifier missing",
685 log_error(
"Error processing %s from %s; " 686 "unable to evaluate Client Identifier",
695 "server identifier missing (CLIENTID %s)",
704 log_error(
"Error processing %s from %s; " 705 "unable to evaluate Server Identifier (CLIENTID %s)",
711 if ((server_duid.len != server_id->
len) ||
712 (memcmp(server_duid.data, server_id->
data, server_duid.len) != 0)) {
714 "not our server identifier " 715 "(CLIENTID %s, SERVERID %s, server DUID %s)",
720 print_hex_3(server_duid.len, server_duid.data, 60));
729 if (server_id->
len > 0) {
732 if (client_id->
len > 0) {
755 char client_id_str[80];
759 memset(server_id, 0,
sizeof(*server_id));
760 memset(&client_id, 0,
sizeof(client_id));
771 snprintf(client_id_str,
sizeof(client_id_str),
" (CLIENTID %s)",
775 client_id_str[0] =
'\0';
782 log_debug(
"Discarding %s from %s; packet sent unicast%s",
791 "IA_NA option present%s",
799 "IA_TA option present%s",
807 "IA_PD option present%s",
818 log_error(
"Error processing %s from %s; " 819 "unable to evaluate Server Identifier%s",
824 if ((server_duid.len != server_id->
len) ||
825 (memcmp(server_duid.data, server_id->
data,
826 server_duid.len) != 0)) {
828 "not our server identifier " 829 "(SERVERID %s, server DUID %s)%s",
833 server_id->
data, 60),
835 server_duid.data, 60),
846 if (server_id->
len > 0) {
857 static const int required_opts[] = {
864 static const int required_opts_solicit[] = {
876 static const int required_opts_agent[] = {
878 #if defined(RELAY_PORT) 884 static const int required_opts_IA[] = {
889 static const int required_opts_IA_PD[] = {
894 static const int required_opts_STATUS_CODE[] = {
899 static const int required_opts_4o6[] = {
905 static const int unicast_reject_opts[] = {
920 get_encapsulated_IA_state(
struct option_state **enc_opt_state,
929 memset(enc_opt_data, 0,
sizeof(*enc_opt_data));
934 "error evaluating raw option.");
937 if (enc_opt_data->
len < offset) {
938 log_error(
"get_encapsulated_IA_state: raw option too small.");
947 *enc_opt_state = NULL;
949 log_error(
"get_encapsulated_IA_state: no memory for options.");
954 enc_opt_data->
data + offset,
955 enc_opt_data->
len - offset,
957 log_error(
"get_encapsulated_IA_state: error parsing options.");
967 set_status_code(u_int16_t status_code,
const char *status_message,
973 memset(&d, 0,
sizeof(d));
974 d.len =
sizeof(status_code) + strlen(status_message);
976 log_fatal(
"set_status_code: no memory for status code.");
978 d.data = d.buffer->data;
980 memcpy(d.buffer->data +
sizeof(status_code),
981 status_message, d.len -
sizeof(status_code));
983 d.buffer, (
unsigned char *)d.data, d.len,
985 log_error(
"set_status_code: error saving status code.");
994 void check_pool6_threshold(
struct reply_state *reply,
998 isc_uint64_t used, count, high_threshold;
999 int poolhigh = 0, poollow = 0;
1000 char *shared_name =
"no name";
1001 char tmp_addr[INET6_ADDRSTRLEN];
1003 if ((
lease->ipv6_pool == NULL) || (
lease->ipv6_pool->ipv6_pond == NULL))
1005 pond =
lease->ipv6_pool->ipv6_pond;
1035 log_error(
"Pool threshold reset - shared subnet: %s; " 1036 "address: %s; low threshold %llu/%llu.",
1038 inet_ntop(AF_INET6, &
lease->addr,
1039 tmp_addr,
sizeof(tmp_addr)),
1047 NULL, reply->packet->options, reply->opt_state,
1055 if ((poolhigh <= 0) || (poolhigh > 100)) {
1062 if (used < high_threshold) {
1068 log_error(
"Pool threshold exceeded - shared subnet: %s; " 1069 "address: %s; high threshold %d%% %llu/%llu.",
1071 inet_ntop(AF_INET6, &
lease->addr, tmp_addr,
sizeof(tmp_addr)),
1072 poolhigh, used, count);
1077 NULL, reply->packet->options, reply->opt_state,
1089 if (poollow < poolhigh) {
1107 const unsigned char *server_id_data;
1115 log_error(
"start_reply: no memory for option_state.");
1183 if (server_id == NULL) {
1184 server_id_data = server_duid.data;
1185 server_id_len = server_duid.len;
1187 server_id_data = server_id->
data;
1188 server_id_len = server_id->
len;
1191 NULL, (
unsigned char *)server_id_data,
1194 "error saving server identifier.");
1199 if (client_id->
buffer != NULL) {
1202 (
unsigned char *)client_id->
data,
1206 "client identifier.");
1222 NULL, (
unsigned char *)
"", 0,
1225 "error saving RECONF_ACCEPT option.");
1243 try_client_v6_address(
struct iasubopt **addr,
1247 struct in6_addr tmp_addr;
1248 isc_result_t result;
1250 if (requested_addr->
len <
sizeof(tmp_addr)) {
1253 memcpy(&tmp_addr, requested_addr->
data,
sizeof(tmp_addr));
1254 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
1255 return ISC_R_FAILURE;
1263 return ISC_R_ADDRNOTAVAIL;
1267 return ISC_R_ADDRINUSE;
1270 result = iasubopt_allocate(addr,
MDL);
1271 if (result != ISC_R_SUCCESS) {
1274 (*addr)->addr = tmp_addr;
1279 if (result != ISC_R_SUCCESS) {
1307 pick_v6_address(
struct reply_state *reply)
1313 unsigned int attempts;
1314 char tmp_buf[INET6_ADDRSTRLEN];
1316 isc_uint64_t total = 0;
1317 isc_uint64_t active = 0;
1318 isc_uint64_t abandoned = 0;
1319 int jumbo_range = 0;
1320 char *shared_name = (reply->shared->name ?
1321 reply->shared->name :
"(no name)");
1327 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1331 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1341 log_debug(
"Unable to pick client address: " 1342 "no IPv6 pools on this shared network");
1343 return ISC_R_NORESOURCES;
1357 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1358 isc_result_t result = ISC_R_FAILURE;
1369 if (pond->use_eui_64 &&
1370 !valid_eui_64_duid(&reply->ia->iaid_duid,
IAID_LEN)) {
1381 if (pond->use_eui_64) {
1383 create_lease6_eui_64(p,
addr,
1384 &reply->ia->iaid_duid,
1392 &reply->ia->iaid_duid,
1397 if (result == ISC_R_SUCCESS) {
1415 tmp_buf,
sizeof(tmp_buf)));
1416 return (ISC_R_SUCCESS);
1424 }
while (i != start_pool);
1426 if (result == ISC_R_NORESOURCES) {
1438 if (jumbo_range != 0) {
1439 log_debug(
"Unable to pick client address: " 1440 "no addresses available - shared network %s: " 1441 " 2^64-1 < total, %llu active, %llu abandoned",
1442 shared_name, active - abandoned, abandoned);
1444 log_debug(
"Unable to pick client address: " 1445 "no addresses available - shared network %s: " 1446 "%llu total, %llu active, %llu abandoned",
1447 shared_name, total, active - abandoned, abandoned);
1450 return ISC_R_NORESOURCES;
1462 try_client_v6_prefix(
struct iasubopt **pref,
1467 struct in6_addr tmp_pref;
1469 isc_result_t result;
1471 if (requested_pref->
len <
sizeof(tmp_plen) +
sizeof(tmp_pref)) {
1475 tmp_plen = (
int) requested_pref->
data[0];
1476 if ((tmp_plen < 3) || (tmp_plen > 128)) {
1477 return ISC_R_FAILURE;
1480 memcpy(&tmp_pref, requested_pref->
data + 1,
sizeof(tmp_pref));
1481 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_pref)) {
1482 return ISC_R_FAILURE;
1486 memcpy(&ia.iabuf, &tmp_pref, 16);
1488 return ISC_R_FAILURE;
1492 ((
int)tmp_plen !=
pool->units)) {
1493 return ISC_R_ADDRNOTAVAIL;
1497 return ISC_R_ADDRINUSE;
1500 result = iasubopt_allocate(pref,
MDL);
1501 if (result != ISC_R_SUCCESS) {
1505 (*pref)->addr = tmp_pref;
1506 (*pref)->plen = tmp_plen;
1510 if (result != ISC_R_SUCCESS) {
1557 pick_v6_prefix(
struct reply_state *reply) {
1561 isc_result_t result;
1567 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1571 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1581 log_debug(
"Unable to pick client prefix: " 1582 "no IPv6 pools on this shared network");
1583 return ISC_R_NORESOURCES;
1586 if (reply->preflen <= 0) {
1589 result = pick_v6_prefix_helper(reply,
PLM_IGNORE);
1595 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1596 if (result != ISC_R_SUCCESS) {
1597 result = pick_v6_prefix_helper(reply,
1604 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1611 result = pick_v6_prefix_helper(reply,
PLM_EXACT);
1612 if (result != ISC_R_SUCCESS) {
1613 result = pick_v6_prefix_helper(reply,
1620 result = pick_v6_prefix_helper(reply,
PLM_IGNORE);
1625 if (result == ISC_R_SUCCESS) {
1626 char tmp_buf[INET6_ADDRSTRLEN];
1629 inet_ntop(AF_INET6, &(reply->lease->addr),
1630 tmp_buf,
sizeof(tmp_buf)),
1631 (
unsigned)(reply->lease->plen));
1632 return (ISC_R_SUCCESS);
1639 log_debug(
"Unable to pick client prefix: no prefixes available");
1640 return ISC_R_NORESOURCES;
1667 pick_v6_prefix_helper(
struct reply_state *reply,
int prefix_mode) {
1671 unsigned int attempts;
1672 struct iasubopt **pref = &reply->lease;
1674 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
1681 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
1683 (eval_prefix_mode(p->
units, reply->preflen,
1684 prefix_mode) == 1) &&
1686 &reply->ia->iaid_duid,
1687 cur_time + 120) == ISC_R_SUCCESS)) {
1688 return (ISC_R_SUCCESS);
1693 return ISC_R_NORESOURCES;
1711 eval_prefix_mode(
int len,
int preflen,
int prefix_mode) {
1713 switch (prefix_mode) {
1715 use_it = (len == preflen);
1719 use_it = (len >= preflen);
1723 use_it = (len <= preflen);
1774 static struct reply_state reply;
1779 memset(&packet_oro, 0,
sizeof(packet_oro));
1782 if (shared_network_from_packet6(&reply.shared,
1783 packet) != ISC_R_SUCCESS)
1792 if (!start_reply(
packet, client_id, server_id, &reply.opt_state,
1808 log_error(
"lease_to_client: error evaluating ORO.");
1819 seek_shared_host(&reply.host, reply.shared);
1826 for (; oc != NULL ; oc = oc->
next) {
1827 isc_result_t status;
1830 reply.client_resources = 0;
1831 reply.resources_included = ISC_FALSE;
1833 status = reply_process_ia_na(&reply, oc);
1839 if ((status != ISC_R_SUCCESS) &&
1840 (status != ISC_R_NORESOURCES))
1844 for (; oc != NULL ; oc = oc->
next) {
1845 isc_result_t status;
1848 reply.client_resources = 0;
1849 reply.resources_included = ISC_FALSE;
1851 status = reply_process_ia_ta(&reply, oc);
1857 if ((status != ISC_R_SUCCESS) &&
1858 (status != ISC_R_NORESOURCES))
1865 for (; oc != NULL ; oc = oc->
next) {
1866 isc_result_t status;
1869 reply.client_resources = 0;
1870 reply.resources_included = ISC_FALSE;
1872 status = reply_process_ia_pd(&reply, oc);
1878 if ((status != ISC_R_SUCCESS) &&
1879 (status != ISC_R_NORESOURCES))
1887 if ((reply.ia_count == 0) && (reply.pd_count == 0)) {
1888 if (reply.packet->dhcpv6_msg_type !=
1898 reply.packet->options,
1904 for (i = reply.packet->class_count; i > 0; i--) {
1907 reply.packet->options,
1910 reply.packet->classes[i - 1]->group,
1911 reply.shared->group, NULL);
1915 if (reply.host != NULL)
1918 reply.packet->options,
1922 reply.shared->group, NULL);
1957 reply.cursor +=
store_options6((
char *)reply.buf.data + reply.cursor,
1958 sizeof(reply.buf) - reply.cursor,
1959 reply.opt_state, reply.packet,
1960 required_opts_solicit,
1964 reply_ret->
len = reply.cursor;
1965 reply_ret->
buffer = NULL;
1969 memcpy(reply_ret->
buffer->
data, reply.buf.data, reply.cursor);
1977 if (reply.shared != NULL)
1978 shared_network_dereference(&reply.shared,
MDL);
1979 if (reply.host != NULL)
1980 host_dereference(&reply.host,
MDL);
1981 if (reply.opt_state != NULL)
1983 if (reply.packet != NULL)
1985 if (reply.client_id.data != NULL)
1987 if (packet_oro.buffer != NULL)
1989 reply.renew = reply.rebind = reply.min_prefer = reply.min_valid = 0;
1997 reply_process_ia_na(
struct reply_state *reply,
struct option_cache *ia) {
1998 isc_result_t status = ISC_R_SUCCESS;
2007 memset(&ia_data, 0,
sizeof(ia_data));
2014 if ((reply->cursor +
IA_NA_OFFSET + 4) >
sizeof(reply->buf)) {
2015 log_error(
"reply_process_ia_na: Reply too long for IA.");
2016 return ISC_R_NOSPACE;
2021 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2023 log_error(
"reply_process_ia_na: error evaluating ia");
2024 status = ISC_R_FAILURE;
2030 reply->renew =
getULong(ia_data.data + 4);
2031 reply->rebind =
getULong(ia_data.data + 8);
2034 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
2035 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
2036 log_error(
"reply_process_ia_na: no memory for ia.");
2037 status = ISC_R_NOMEMORY;
2044 (
unsigned char *)reply->ia->iaid_duid.data,
2045 reply->ia->iaid_duid.len,
MDL);
2052 status = ISC_R_NOMEMORY;
2057 if ((reply->host != NULL) && (reply->host->fixed_addr != NULL)) {
2058 struct iaddr tmp_addr;
2062 reply->host->fixed_addr,
MDL)) {
2063 log_error(
"reply_process_ia_na: unable to evaluate " 2065 status = ISC_R_FAILURE;
2069 if (reply->fixed.len < 16) {
2070 log_error(
"reply_process_ia_na: invalid fixed address.");
2077 memcpy(tmp_addr.iabuf, reply->fixed.data, 16);
2080 tmp_addr,
MDL) == 0)
2083 reply->static_lease = ISC_TRUE;
2085 reply->static_lease = ISC_FALSE;
2093 ia_cursor = reply->cursor;
2100 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
2104 putULong(reply->buf.data + reply->cursor, iaid);
2108 putULong(reply->buf.data + reply->cursor, reply->renew);
2112 putULong(reply->buf.data + reply->cursor, reply->rebind);
2126 reply->client_valid = reply->client_prefer = 0;
2127 for (; oc != NULL ; oc = oc->
next) {
2128 status = reply_process_addr(reply, oc);
2136 if (status == ISC_R_CANCELED)
2139 if ((status != ISC_R_SUCCESS) &&
2140 (status != ISC_R_ADDRINUSE) &&
2141 (status != ISC_R_ADDRNOTAVAIL))
2151 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
2152 status = find_client_address(reply);
2154 if (status == ISC_R_NORESOURCES) {
2155 switch (reply->packet->dhcpv6_msg_type) {
2178 "memory for option state " 2180 status = ISC_R_NOMEMORY;
2185 "No addresses available " 2186 "for this interface.",
2188 log_error(
"reply_process_ia_na: Unable " 2189 "to set NoAddrsAvail status " 2191 status = ISC_R_FAILURE;
2195 status = ISC_R_SUCCESS;
2215 if (reply->resources_included)
2216 status = ISC_R_SUCCESS;
2223 if (status != ISC_R_SUCCESS)
2231 if (status == ISC_R_CANCELED) {
2234 write_to_packet(reply, ia_cursor);
2242 if (reply->static_lease) {
2243 char tmp_addr[INET6_ADDRSTRLEN];
2244 log_info(
"%s NA: address %s to client with duid %s iaid = %d " 2247 inet_ntop(AF_INET6, reply->fixed.data, tmp_addr,
2250 reply->client_id.data, 60),
2254 write_to_packet(reply, ia_cursor);
2257 ddns_update_static6(reply);
2260 (reply->on_star.on_commit != NULL)) {
2262 reply->packet->options,
2263 reply->opt_state, NULL,
2264 reply->on_star.on_commit, NULL);
2266 (&reply->on_star.on_commit,
MDL);
2274 if (reply->ia->num_iasubopt != 0) {
2277 char tmp_addr[INET6_ADDRSTRLEN];
2279 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2280 tmp = reply->ia->iasubopt[i];
2282 log_info(
"%s NA: address %s to client with duid %s " 2283 "iaid = %d valid for %u seconds",
2285 inet_ntop(AF_INET6, &tmp->
addr,
2286 tmp_addr,
sizeof(tmp_addr)),
2288 reply->client_id.data, 60),
2308 if ((reply->ia->num_iasubopt != 0) &&
2310 int must_commit = 0;
2315 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
2316 tmp = reply->ia->iasubopt[i];
2317 if (tmp->
ia != NULL) {
2327 reply->packet->options,
2336 #if defined (NSUPDATE) 2344 reply->packet->options,
2349 tmp, NULL, reply->opt_state);
2352 if (!reuse_lease6(reply, tmp)) {
2359 check_pool6_threshold(reply, tmp);
2364 write_to_packet(reply, ia_cursor);
2367 if (reply->old_ia != NULL) {
2368 if (!release_on_roam(reply)) {
2369 ia_id = &reply->old_ia->iaid_duid;
2371 (
unsigned char *)ia_id->
data,
2380 ia_id = &reply->ia->iaid_duid;
2382 ia_id->
len, reply->ia,
MDL);
2391 write_to_packet(reply, ia_cursor);
2392 schedule_lease_timeout_reply(reply);
2396 if (packet_ia != NULL)
2398 if (reply->reply_ia != NULL)
2400 if (ia_data.data != NULL)
2402 if (
data.data != NULL)
2404 if (reply->ia != NULL)
2406 if (reply->old_ia != NULL)
2408 if (reply->lease != NULL)
2410 if (reply->fixed.data != NULL)
2412 if (reply->subnet != NULL)
2413 subnet_dereference(&reply->subnet,
MDL);
2414 if (reply->on_star.on_expiry != NULL)
2416 (&reply->on_star.on_expiry,
MDL);
2417 if (reply->on_star.on_release != NULL)
2419 (&reply->on_star.on_release,
MDL);
2426 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
2433 write_to_packet(
struct reply_state *reply,
unsigned ia_cursor) {
2434 reply->cursor +=
store_options6((
char *)reply->buf.data + reply->cursor,
2435 sizeof(reply->buf) - reply->cursor,
2436 reply->reply_ia, reply->packet,
2438 required_opts_IA : required_opts_IA_PD),
2442 putUShort(reply->buf.data + ia_cursor + 2,
2443 reply->cursor - (ia_cursor + 4));
2447 set_reply_tee_times(reply, ia_cursor);
2458 reply_process_addr(
struct reply_state *reply,
struct option_cache *addr) {
2459 u_int32_t pref_life, valid_life;
2463 struct iaddr tmp_addr;
2466 isc_result_t status = ISC_R_SUCCESS;
2468 int invalid_for_eui_64 = 0;
2472 memset(&iaaddr, 0,
sizeof(iaaddr));
2480 if ((reply->cursor + 28) >
sizeof(reply->buf)) {
2481 log_error(
"reply_process_addr: Out of room for address.");
2482 return ISC_R_NOSPACE;
2490 log_error(
"reply_process_addr: error evaluating IAADDR.");
2491 status = ISC_R_FAILURE;
2496 pref_life =
getULong(iaaddr.data + 16);
2497 valid_life =
getULong(iaaddr.data + 20);
2499 if ((reply->client_valid == 0) ||
2500 (reply->client_valid > valid_life))
2501 reply->client_valid = valid_life;
2503 if ((reply->client_prefer == 0) ||
2504 (reply->client_prefer > pref_life))
2505 reply->client_prefer = pref_life;
2512 memset(tmp_addr.iabuf, 0, 16);
2513 if (!memcmp(iaaddr.data, tmp_addr.iabuf, 16)) {
2519 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2524 for (
subnet = reply->shared->subnets ;
subnet != NULL ;
2538 struct in6_addr* addr = (
struct in6_addr*)(iaaddr.data);
2540 && (
pool->ipv6_pond->use_eui_64) &&
2541 (!valid_for_eui_64_pool(
pool, &reply->client_id, 0, addr))) {
2543 " not valid for EUI-64 pool",
2545 invalid_for_eui_64 = 1;
2552 if ((
subnet == NULL) || invalid_for_eui_64) {
2580 log_error(
"reply_process_addr: No memory for " 2581 "option state wipe.");
2582 status = ISC_R_NOMEMORY;
2588 "Address not for use on this " 2589 "link.", reply->reply_ia)) {
2590 log_error(
"reply_process_addr: Failure " 2591 "setting status code.");
2592 status = ISC_R_FAILURE;
2597 status = ISC_R_CANCELED;
2609 if ((reply->packet->dhcpv6_msg_type !=
DHCPV6_RENEW) &&
2611 log_error(
"It is impossible to lease a client that is " 2612 "not sending a solicit, request, renew, or " 2614 status = ISC_R_FAILURE;
2618 reply->send_prefer = reply->send_valid = 0;
2624 if (!address_is_owned(reply, &tmp_addr)) {
2635 status = reply_process_try_addr(reply, &tmp_addr);
2642 if ((status != ISC_R_SUCCESS) &&
2643 (status != ISC_R_ADDRINUSE) &&
2644 (status != ISC_R_ADDRNOTAVAIL))
2652 if (reply->lease == NULL) {
2653 if (reply->packet->dhcpv6_msg_type ==
2655 reply->send_prefer = 0;
2656 reply->send_valid = 0;
2673 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
2677 log_error(
"reply_process_addr: No memory for " 2678 "option state wipe.");
2679 status = ISC_R_NOMEMORY;
2685 "Address not bound to this " 2686 "interface.", reply->reply_ia)) {
2687 log_error(
"reply_process_addr: Unable to " 2688 "attach status code.");
2689 status = ISC_R_FAILURE;
2694 status = ISC_R_CANCELED;
2697 log_error(
"It is impossible to lease a client that is " 2698 "not sending a solicit, request, renew, or " 2700 status = ISC_R_FAILURE;
2705 if (reply->static_lease) {
2706 if (reply->host == NULL)
2710 group = reply->subnet->group;
2712 if (reply->lease == NULL)
2715 scope = &reply->lease->scope;
2716 group = reply->lease->ipv6_pool->ipv6_pond->group;
2725 if (reply->client_resources != 0) {
2738 reply->packet->options,
2742 log_error(
"reply_process_addr: unable to " 2743 "evaluate addrs-per-ia value.");
2744 status = ISC_R_FAILURE;
2756 if (reply->client_resources >= limit)
2760 status = reply_process_is_addressed(reply, scope,
group);
2761 if (status != ISC_R_SUCCESS)
2765 status = reply_process_send_addr(reply, &tmp_addr);
2768 if (iaaddr.data != NULL)
2770 if (data.data != NULL)
2772 if (reply->lease != NULL)
2784 static isc_boolean_t
2785 address_is_owned(
struct reply_state *reply,
struct iaddr *addr) {
2792 if (reply->static_lease) {
2793 if (reply->fixed.data == NULL)
2796 if (memcmp(addr->
iabuf, reply->fixed.data, 16) == 0)
2802 if ((reply->old_ia == NULL) || (reply->old_ia->num_iasubopt == 0))
2805 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
2808 tmp = reply->old_ia->iasubopt[i];
2810 if (memcmp(
addr->iabuf, &tmp->
addr, 16) == 0) {
2835 reply_process_ia_ta(
struct reply_state *reply,
struct option_cache *
ia) {
2836 isc_result_t status = ISC_R_SUCCESS;
2843 u_int32_t pref_life, valid_life;
2844 struct iaddr tmp_addr;
2848 memset(&ia_data, 0,
sizeof(ia_data));
2849 memset(&data, 0,
sizeof(data));
2850 memset(&iaaddr, 0,
sizeof(iaaddr));
2853 if ((reply->cursor +
IA_TA_OFFSET + 4) >
sizeof(reply->buf)) {
2854 log_error(
"reply_process_ia_ta: Reply too long for IA.");
2855 return ISC_R_NOSPACE;
2860 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
2862 log_error(
"reply_process_ia_ta: error evaluating ia");
2863 status = ISC_R_FAILURE;
2871 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
2872 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
2873 log_error(
"reply_process_ia_ta: no memory for ia.");
2874 status = ISC_R_NOMEMORY;
2881 (
unsigned char *)reply->ia->iaid_duid.data,
2882 reply->ia->iaid_duid.len,
MDL);
2889 status = ISC_R_NOMEMORY;
2896 reply->static_lease = ISC_FALSE;
2904 ia_cursor = reply->cursor;
2911 putUShort(reply->buf.data + reply->cursor, 0x04u);
2915 putULong(reply->buf.data + reply->cursor, iaid);
2923 reply->client_valid = reply->client_prefer = 0;
2925 for (; oc != NULL; oc = oc->
next) {
2926 memset(&iaaddr, 0,
sizeof(iaaddr));
2929 reply->packet->options, NULL,
2933 "evaluating IAADDR.");
2934 status = ISC_R_FAILURE;
2938 pref_life =
getULong(iaaddr.data + 16);
2939 valid_life =
getULong(iaaddr.data + 20);
2941 if ((reply->client_valid == 0) ||
2942 (reply->client_valid > valid_life))
2943 reply->client_valid = valid_life;
2945 if ((reply->client_prefer == 0) ||
2946 (reply->client_prefer > pref_life))
2947 reply->client_prefer = pref_life;
2950 if (status == ISC_R_CANCELED)
2954 memcpy(tmp_addr.iabuf, iaaddr.data, 16);
2955 if (!temporary_is_available(reply, &tmp_addr))
2957 status = reply_process_is_addressed(reply,
2958 &reply->lease->scope,
2959 reply->lease->ipv6_pool->ipv6_pond->group);
2960 if (status != ISC_R_SUCCESS)
2962 status = reply_process_send_addr(reply, &tmp_addr);
2963 if (status != ISC_R_SUCCESS)
2965 if (reply->lease != NULL)
2973 status = ISC_R_NOMEMORY;
2976 status = ISC_R_CANCELED;
2977 reply->client_resources = 0;
2978 reply->resources_included = ISC_FALSE;
2979 if (reply->lease != NULL)
2987 if (reply->client_resources != 0)
2989 status = find_client_temporaries(reply);
2990 if (status == ISC_R_NORESOURCES) {
2991 switch (reply->packet->dhcpv6_msg_type) {
3012 "memory for option state wipe.");
3013 status = ISC_R_NOMEMORY;
3018 "No addresses available " 3019 "for this interface.",
3021 log_error(
"reply_process_ia_ta: Unable " 3022 "to set NoAddrsAvail status code.");
3023 status = ISC_R_FAILURE;
3027 status = ISC_R_SUCCESS;
3036 if (reply->resources_included)
3037 status = ISC_R_SUCCESS;
3042 }
else if (status != ISC_R_SUCCESS)
3051 if (status == ISC_R_CANCELED) {
3054 write_to_packet(reply, ia_cursor);
3061 if (reply->ia->num_iasubopt != 0) {
3064 char tmp_addr[INET6_ADDRSTRLEN];
3066 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3067 tmp = reply->ia->iasubopt[i];
3069 log_info(
"%s TA: address %s to client with duid %s " 3070 "iaid = %d valid for %u seconds",
3072 inet_ntop(AF_INET6, &tmp->
addr,
3073 tmp_addr,
sizeof(tmp_addr)),
3075 reply->client_id.data, 60),
3089 if ((reply->ia->num_iasubopt != 0) &&
3091 int must_commit = 0;
3096 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
3097 tmp = reply->ia->iasubopt[i];
3099 if (tmp->
ia != NULL)
3107 reply->packet->options,
3116 #if defined (NSUPDATE) 3125 reply->packet->options,
3130 tmp, NULL, reply->opt_state);
3134 if (!reuse_lease6(reply, tmp)) {
3141 check_pool6_threshold(reply, tmp);
3146 write_to_packet(reply, ia_cursor);
3149 if (reply->old_ia != NULL) {
3150 if (!release_on_roam(reply)) {
3151 ia_id = &reply->old_ia->iaid_duid;
3153 (
unsigned char *)ia_id->
data,
3162 ia_id = &reply->ia->iaid_duid;
3164 ia_id->
len, reply->ia,
MDL);
3173 write_to_packet(reply, ia_cursor);
3174 schedule_lease_timeout_reply(reply);
3178 if (packet_ia != NULL)
3180 if (iaaddr.data != NULL)
3182 if (reply->reply_ia != NULL)
3184 if (ia_data.data != NULL)
3186 if (
data.data != NULL)
3188 if (reply->ia != NULL)
3190 if (reply->old_ia != NULL)
3192 if (reply->lease != NULL)
3200 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
3216 reuse_lease6(
struct reply_state *reply,
struct iasubopt *
lease) {
3229 (
lease->hard_lifetime_end_time == 0) ||
3240 reply->packet->options, reply->opt_state,
3242 if (d1.len == 1 && (d1.data[0] < 100)) {
3243 threshold = d1.data[0];
3249 if (threshold <= 0) {
3257 log_debug (
"reusing infinite lease for: %s%s",
3263 if (
lease->valid <= (INT_MAX / threshold))
3264 limit =
lease->valid * threshold / 100;
3266 limit =
lease->valid / 100 * threshold;
3270 shorten_lifetimes(reply,
lease, age, threshold);
3291 void shorten_lifetimes(
struct reply_state *reply,
struct iasubopt *
lease,
3292 time_t age,
int threshold) {
3317 for (; oc != NULL ; oc = oc->
next) {
3325 if (!memcmp(oc->
data.
data + addr_offset, &
lease->addr, 16) &&
3334 if (pref_life < MAX_TIME && pref_life > age) {
3337 pref_offset, pref_life);
3339 if (reply->min_prefer > pref_life) {
3340 reply->min_prefer = pref_life;
3344 if (valid_life < MAX_TIME && valid_life > age) {
3347 val_offset, valid_life);
3349 if (reply->min_valid > reply->send_valid) {
3350 reply->min_valid = valid_life;
3355 "age %ld secs < %d%%," 3356 " sending shortened lifetimes -" 3357 " preferred: %u, valid %u",
3359 iasubopt_plen_str(
lease),
3360 (
long)age, threshold,
3361 pref_life, valid_life);
3370 static isc_boolean_t
3371 temporary_is_available(
struct reply_state *reply,
struct iaddr *addr) {
3372 struct in6_addr tmp_addr;
3378 memcpy(&tmp_addr, addr->
iabuf,
sizeof(tmp_addr));
3384 if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr))
3390 for (
subnet = reply->shared->subnets ;
subnet != NULL ;
3404 if (address_is_owned(reply, addr))
3410 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3433 if (iasubopt_allocate(&reply->lease,
MDL) != ISC_R_SUCCESS)
3435 reply->lease->addr = tmp_addr;
3436 reply->lease->plen = 0;
3448 find_client_temporaries(
struct reply_state *reply) {
3452 isc_result_t status = ISC_R_NORESOURCES;;
3453 unsigned int attempts;
3454 struct iaddr send_addr;
3460 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3464 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3474 log_debug(
"Unable to get client addresses: " 3475 "no IPv6 pools on this shared network");
3476 return ISC_R_NORESOURCES;
3486 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3493 for (i = 0; (p = pond->
ipv6_pools[i]) != NULL; i++) {
3505 if (status != ISC_R_SUCCESS) {
3506 log_debug(
"Unable to get a temporary address.");
3510 status = reply_process_is_addressed(reply,
3511 &reply->lease->scope,
3513 if (status != ISC_R_SUCCESS) {
3517 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3518 status = reply_process_send_addr(reply, &send_addr);
3519 if (status != ISC_R_SUCCESS) {
3531 if (reply->lease != NULL) {
3542 reply_process_try_addr(
struct reply_state *reply,
struct iaddr *addr) {
3543 isc_result_t status = ISC_R_ADDRNOTAVAIL;
3549 if ((reply == NULL) || (reply->shared == NULL) ||
3550 (addr == NULL) || (reply->lease != NULL))
3557 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3561 for (i = 0; ; i++) {
3563 if ((
pool == NULL) ||
3573 return (ISC_R_ADDRNOTAVAIL);
3576 memset(&data_addr, 0,
sizeof(data_addr));
3577 data_addr.len = addr->
len;
3578 data_addr.data = addr->
iabuf;
3591 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
3602 status = try_client_v6_address(&reply->lease,
pool,
3604 if (status == ISC_R_SUCCESS)
3608 if (status == ISC_R_SUCCESS)
3623 find_client_address(
struct reply_state *reply) {
3624 struct iaddr send_addr;
3625 isc_result_t status = ISC_R_NORESOURCES;
3631 if (reply->static_lease) {
3632 if (reply->host == NULL)
3636 memcpy(send_addr.iabuf, reply->fixed.data, 16);
3639 group = reply->subnet->group;
3643 if (reply->old_ia != NULL) {
3644 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
3648 lease = reply->old_ia->iasubopt[i];
3649 candidate_shared =
lease->ipv6_pool->shared_network;
3650 pond =
lease->ipv6_pool->ipv6_pond;
3657 if ((candidate_shared != reply->shared) ||
3667 best_lease = lease_compare(
lease, best_lease);
3675 status = pick_v6_address(reply);
3676 }
else if (best_lease != NULL) {
3678 status = ISC_R_SUCCESS;
3682 if ((status == ISC_R_NORESOURCES) && (best_lease != NULL)) {
3684 log_error(
"Best match for DUID %s is an abandoned address," 3685 " This may be a result of multiple clients attempting" 3686 " to use this DUID",
3688 reply->client_id.data, 60));
3693 if (status != ISC_R_SUCCESS)
3696 if (reply->lease == NULL)
3703 scope = &reply->lease->scope;
3704 group = reply->lease->ipv6_pool->ipv6_pond->group;
3707 memcpy(send_addr.iabuf, &reply->lease->addr, 16);
3710 status = reply_process_is_addressed(reply, scope,
group);
3711 if (status != ISC_R_SUCCESS)
3714 status = reply_process_send_addr(reply, &send_addr);
3723 reply_process_is_addressed(
struct reply_state *reply,
3726 isc_result_t status = ISC_R_SUCCESS;
3734 memset(&data, 0,
sizeof(data));
3743 on_star = &reply->lease->on_star;
3755 reply->packet->options, tmp_options,
3758 if (tmp_options != NULL) {
3768 reply->packet->options, reply->opt_state,
3772 for (i = reply->packet->class_count; i > 0; i--) {
3774 reply->packet->options,
3775 reply->opt_state, scope,
3776 reply->packet->classes[i - 1]->group,
3785 if (reply->host != NULL)
3787 reply->packet->options,
3788 reply->opt_state, scope,
3789 reply->host->group,
group,
3793 if (reply->client_valid == 0)
3796 reply->send_valid = reply->client_valid;
3802 reply->packet->options,
3806 log_error(
"reply_process_is_addressed: unable to " 3807 "evaluate default lease time");
3808 status = ISC_R_FAILURE;
3812 reply->send_valid =
getULong(data.data);
3822 time_t test_time =
cur_time + reply->send_valid;
3827 if (reply->client_prefer == 0)
3828 reply->send_prefer = reply->send_valid;
3830 reply->send_prefer = reply->client_prefer;
3832 if ((reply->send_prefer >= reply->send_valid) &&
3834 reply->send_prefer = (reply->send_valid / 2) +
3835 (reply->send_valid / 8);
3841 reply->packet->options,
3845 log_error(
"reply_process_is_addressed: unable to " 3846 "evaluate preferred lease time");
3847 status = ISC_R_FAILURE;
3851 reply->send_prefer =
getULong(data.data);
3856 if (reply->min_prefer > reply->send_prefer)
3857 reply->min_prefer = reply->send_prefer;
3859 if (reply->min_valid > reply->send_valid)
3860 reply->min_valid = reply->send_valid;
3872 if (reply->host != NULL)
3874 reply->client_id->len);
3878 if (reply->lease != NULL) {
3880 reply->lease->prefer = reply->send_prefer;
3881 reply->lease->valid = reply->send_valid;
3889 reply->lease->soft_lifetime_end_time =
MAX_TIME;
3891 reply->lease->soft_lifetime_end_time =
3898 if (status != ISC_R_SUCCESS) {
3899 log_fatal(
"reply_process_is_addressed: Unable to " 3900 "attach lease to new IA: %s",
3901 isc_result_totext(status));
3907 if (reply->lease->ia == NULL) {
3914 reply->packet->options, reply->reply_ia,
3918 for (i = reply->packet->class_count; i > 0; i--) {
3920 reply->packet->options,
3921 reply->reply_ia, scope,
3922 reply->packet->classes[i - 1]->group,
3930 if (reply->host != NULL)
3932 reply->packet->options,
3933 reply->reply_ia, scope,
3934 reply->host->group,
group, NULL);
3937 if (data.data != NULL)
3940 if (status == ISC_R_SUCCESS)
3941 reply->client_resources++;
3948 reply_process_send_addr(
struct reply_state *reply,
struct iaddr *addr) {
3949 isc_result_t status = ISC_R_SUCCESS;
3957 log_error(
"reply_process_send_addr: out of memory" 3958 "allocating new IAADDR buffer.");
3959 status = ISC_R_NOMEMORY;
3964 memcpy(
data.buffer->data, addr->
iabuf, 16);
3971 log_error(
"reply_process_send_addr: unable " 3972 "to save IAADDR option");
3973 status = ISC_R_FAILURE;
3977 reply->resources_included = ISC_TRUE;
3980 if (
data.data != NULL)
3994 switch(alpha->
state) {
3996 switch(beta->
state) {
4017 switch (beta->
state) {
4043 switch (beta->
state) {
4065 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
4073 reply_process_ia_pd(
struct reply_state *reply,
struct option_cache *
ia) {
4074 isc_result_t status = ISC_R_SUCCESS;
4083 memset(&ia_data, 0,
sizeof(ia_data));
4090 if ((reply->cursor +
IA_PD_OFFSET + 4) >
sizeof(reply->buf)) {
4091 log_error(
"reply_process_ia_pd: Reply too long for IA.");
4092 return ISC_R_NOSPACE;
4097 if (!get_encapsulated_IA_state(&packet_ia, &ia_data, reply->packet,
4099 log_error(
"reply_process_ia_pd: error evaluating ia");
4100 status = ISC_R_FAILURE;
4106 reply->renew =
getULong(ia_data.data + 4);
4107 reply->rebind =
getULong(ia_data.data + 8);
4110 if (
ia_allocate(&reply->ia, iaid, (
char *)reply->client_id.data,
4111 reply->client_id.len,
MDL) != ISC_R_SUCCESS) {
4112 log_error(
"reply_process_ia_pd: no memory for ia.");
4113 status = ISC_R_NOMEMORY;
4120 (
unsigned char *)reply->ia->iaid_duid.data,
4121 reply->ia->iaid_duid.len,
MDL);
4128 status = ISC_R_NOMEMORY;
4133 reply->static_prefixes = 0;
4134 if ((reply->host != NULL) && (reply->host->fixed_prefix != NULL)) {
4137 for (fp = reply->host->fixed_prefix; fp != NULL;
4139 reply->static_prefixes += 1;
4149 ia_cursor = reply->cursor;
4156 putUShort(reply->buf.data + reply->cursor, 0x0Cu);
4160 putULong(reply->buf.data + reply->cursor, iaid);
4164 putULong(reply->buf.data + reply->cursor, reply->renew);
4168 putULong(reply->buf.data + reply->cursor, reply->rebind);
4176 reply->client_valid = reply->client_prefer = 0;
4177 reply->preflen = -1;
4178 for (; oc != NULL ; oc = oc->
next) {
4179 status = reply_process_prefix(reply, oc);
4187 if (status == ISC_R_CANCELED)
4190 if ((status != ISC_R_SUCCESS) &&
4191 (status != ISC_R_ADDRINUSE) &&
4192 (status != ISC_R_ADDRNOTAVAIL))
4202 if ((status != ISC_R_CANCELED) && (reply->client_resources == 0)) {
4203 status = find_client_prefix(reply);
4205 if (status == ISC_R_NORESOURCES) {
4206 switch (reply->packet->dhcpv6_msg_type) {
4221 "memory for option state " 4223 status = ISC_R_NOMEMORY;
4228 "No prefixes available " 4229 "for this interface.",
4233 "NoPrefixAvail status " 4235 status = ISC_R_FAILURE;
4239 status = ISC_R_SUCCESS;
4243 if (reply->resources_included)
4244 status = ISC_R_SUCCESS;
4251 if (status != ISC_R_SUCCESS)
4259 if (status == ISC_R_CANCELED) {
4262 write_to_packet(reply, ia_cursor);
4270 if (reply->static_prefixes != 0) {
4271 char tmp_addr[INET6_ADDRSTRLEN];
4272 log_info(
"%s PD: address %s/%d to client with duid %s " 4275 inet_ntop(AF_INET6, reply->fixed_pref.lo_addr.iabuf,
4276 tmp_addr,
sizeof(tmp_addr)),
4277 reply->fixed_pref.bits,
4279 reply->client_id.data, 60),
4283 write_to_packet(reply, ia_cursor);
4286 (reply->on_star.on_commit != NULL)) {
4288 reply->packet->options,
4290 NULL, reply->on_star.on_commit,
4293 (&reply->on_star.on_commit,
MDL);
4301 if (reply->ia->num_iasubopt != 0) {
4304 char tmp_addr[INET6_ADDRSTRLEN];
4306 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
4307 tmp = reply->ia->iasubopt[i];
4309 log_info(
"%s PD: address %s/%d to client with duid %s" 4310 " iaid = %d valid for %u seconds",
4312 inet_ntop(AF_INET6, &tmp->
addr,
4313 tmp_addr,
sizeof(tmp_addr)),
4316 reply->client_id.data, 60),
4334 (reply->ia->num_iasubopt != 0)) {
4335 int must_commit = 0;
4340 for (i = 0 ; i < reply->ia->num_iasubopt ; i++) {
4341 tmp = reply->ia->iasubopt[i];
4343 if (tmp->
ia != NULL)
4351 reply->packet->options,
4360 if (!reuse_lease6(reply, tmp)) {
4367 check_pool6_threshold(reply, tmp);
4372 write_to_packet(reply, ia_cursor);
4375 if (reply->old_ia != NULL) {
4376 if (!release_on_roam(reply)) {
4377 ia_id = &reply->old_ia->iaid_duid;
4379 (
unsigned char *)ia_id->
data,
4388 ia_id = &reply->ia->iaid_duid;
4390 ia_id->
len, reply->ia,
MDL);
4399 write_to_packet(reply, ia_cursor);
4400 schedule_lease_timeout_reply(reply);
4404 if (packet_ia != NULL)
4406 if (reply->reply_ia != NULL)
4408 if (ia_data.data != NULL)
4410 if (
data.data != NULL)
4412 if (reply->ia != NULL)
4414 if (reply->old_ia != NULL)
4416 if (reply->lease != NULL)
4418 if (reply->on_star.on_expiry != NULL)
4420 (&reply->on_star.on_expiry,
MDL);
4421 if (reply->on_star.on_release != NULL)
4423 (&reply->on_star.on_release,
MDL);
4430 return((status == ISC_R_CANCELED) ? ISC_R_SUCCESS : status);
4452 static struct group *
4453 find_group_by_prefix(
struct reply_state *reply) {
4457 struct iaddr tmp_addr;
4462 reply->fixed_pref.lo_addr,
MDL) != 0) {
4471 memset(&fixed_addr, 0,
sizeof(fixed_addr));
4473 if ((reply->host->fixed_addr != NULL) &&
4476 reply->host->fixed_addr,
MDL))) {
4477 if (fixed_addr.len >= 16) {
4479 memcpy(tmp_addr.iabuf, fixed_addr.data, 16);
4481 tmp_addr,
MDL) != 0) {
4500 reply_process_prefix(
struct reply_state *reply,
struct option_cache *pref) {
4501 u_int32_t pref_life, valid_life;
4506 isc_result_t status = ISC_R_SUCCESS;
4510 memset(&iapref, 0,
sizeof(iapref));
4511 memset(&data, 0,
sizeof(data));
4518 if ((reply->cursor + 29) >
sizeof(reply->buf)) {
4519 log_error(
"reply_process_prefix: Out of room for prefix.");
4520 return ISC_R_NOSPACE;
4528 log_error(
"reply_process_prefix: error evaluating IAPREFIX.");
4529 status = ISC_R_FAILURE;
4538 valid_life =
getULong(iapref.data + 4);
4540 if ((reply->client_valid == 0) ||
4541 (reply->client_valid > valid_life))
4542 reply->client_valid = valid_life;
4544 if ((reply->client_prefer == 0) ||
4545 (reply->client_prefer > pref_life))
4546 reply->client_prefer = pref_life;
4552 tmp_pref.lo_addr.len = 16;
4553 memset(tmp_pref.lo_addr.iabuf, 0, 16);
4554 if ((iapref.data[8] == 0) &&
4555 (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0)) {
4564 tmp_pref.bits = (
int) iapref.data[8];
4565 if (reply->preflen < 0) {
4567 reply->preflen = tmp_pref.bits;
4569 if (memcmp(iapref.data + 9, tmp_pref.lo_addr.iabuf, 16) == 0) {
4573 memcpy(tmp_pref.lo_addr.iabuf, iapref.data + 9, 16);
4576 if (!prefix_is_owned(reply, &tmp_pref)) {
4581 status = reply_process_try_prefix(reply, &tmp_pref);
4584 if ((status != ISC_R_SUCCESS) &&
4585 (status != ISC_R_ADDRINUSE) &&
4586 (status != ISC_R_ADDRNOTAVAIL))
4589 if (reply->lease == NULL) {
4590 if (reply->packet->dhcpv6_msg_type ==
4592 reply->send_prefer = 0;
4593 reply->send_valid = 0;
4612 }
else if (reply->packet->dhcpv6_msg_type ==
DHCPV6_RENEW) {
4616 log_error(
"reply_process_prefix: No memory " 4617 "for option state wipe.");
4618 status = ISC_R_NOMEMORY;
4624 "Prefix not bound to this " 4625 "interface.", reply->reply_ia)) {
4626 log_error(
"reply_process_prefix: Unable to " 4627 "attach status code.");
4628 status = ISC_R_FAILURE;
4633 status = ISC_R_CANCELED;
4636 log_error(
"It is impossible to lease a client that is " 4637 "not sending a solicit, request, renew, or " 4639 status = ISC_R_FAILURE;
4644 if (reply->static_prefixes > 0) {
4645 if (reply->host == NULL)
4651 memcpy(&reply->fixed_pref, &tmp_pref,
sizeof(tmp_pref));
4654 group = find_group_by_prefix(reply);
4656 if (reply->lease == NULL)
4659 scope = &reply->lease->scope;
4660 group = reply->lease->ipv6_pool->ipv6_pond->group;
4669 if (reply->client_resources != 0) {
4682 reply->packet->options,
4686 log_error(
"reply_process_prefix: unable to " 4687 "evaluate prefs-per-ia value.");
4688 status = ISC_R_FAILURE;
4700 if (reply->client_resources >= limit)
4704 status = reply_process_is_prefixed(reply, scope,
group);
4705 if (status != ISC_R_SUCCESS)
4709 status = reply_process_send_prefix(reply, &tmp_pref);
4712 if (iapref.data != NULL)
4714 if (data.data != NULL)
4716 if (reply->lease != NULL)
4728 static isc_boolean_t
4729 prefix_is_owned(
struct reply_state *reply,
struct iaddrcidrnet *pref) {
4737 if (reply->static_prefixes > 0) {
4738 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4747 if ((reply->old_ia == NULL) ||
4748 (reply->old_ia->num_iasubopt == 0))
4751 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4754 tmp = reply->old_ia->iasubopt[i];
4756 if ((pref->
bits == (
int) tmp->
plen) &&
4782 reply_process_try_prefix(
struct reply_state *reply,
4784 isc_result_t status = ISC_R_ADDRNOTAVAIL;
4790 if ((reply == NULL) || (reply->shared == NULL) ||
4791 (pref == NULL) || (reply->lease != NULL))
4798 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4812 return (ISC_R_ADDRNOTAVAIL);
4815 memset(&data_pref, 0,
sizeof(data_pref));
4818 log_error(
"reply_process_try_prefix: out of memory.");
4819 return (ISC_R_NOMEMORY);
4821 data_pref.data = data_pref.buffer->data;
4822 data_pref.buffer->data[0] = (u_int8_t) pref->
bits;
4823 memcpy(data_pref.buffer->data + 1, pref->
lo_addr.
iabuf, 16);
4833 for (pond = reply->shared->ipv6_pond; pond != NULL; pond = pond->
next) {
4845 status = try_client_v6_prefix(&reply->lease,
pool,
4849 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4852 if ( (status == ISC_R_SUCCESS) || (status == ISC_R_ADDRINUSE) )
4866 find_client_prefix(
struct reply_state *reply) {
4868 isc_result_t status = ISC_R_NORESOURCES;
4869 struct iasubopt *prefix, *best_prefix = NULL;
4874 if (reply->static_prefixes > 0) {
4877 if (reply->host == NULL)
4880 for (l = reply->host->fixed_prefix; l != NULL; l = l->
next) {
4889 l = reply->host->fixed_prefix;
4891 memcpy(&send_pref, &l->
cidrnet,
sizeof(send_pref));
4896 memcpy(&reply->fixed_pref, &l->
cidrnet,
sizeof(send_pref));
4899 group = find_group_by_prefix(reply);
4904 if (reply->old_ia != NULL) {
4905 for (i = 0 ; i < reply->old_ia->num_iasubopt ; i++) {
4909 prefix = reply->old_ia->iasubopt[i];
4918 if (((candidate_shared != NULL) &&
4919 (candidate_shared != reply->shared)) ||
4933 best_prefix = prefix_compare(reply, prefix,
4943 if (best_prefix && (reply->preflen > 0)
4945 && (reply->preflen != best_prefix->
plen)
4955 status = pick_v6_prefix(reply);
4956 }
else if (best_prefix != NULL) {
4958 status = ISC_R_SUCCESS;
4962 if ((status == ISC_R_NORESOURCES) && (best_prefix != NULL)) {
4964 log_error(
"Reclaiming abandoned prefixes is not yet " 4965 "supported. Treating this as an out of space " 4971 if (status != ISC_R_SUCCESS)
4974 if (reply->lease == NULL)
4977 scope = &reply->lease->scope;
4978 group = reply->lease->ipv6_pool->ipv6_pond->group;
4980 send_pref.lo_addr.len = 16;
4981 memcpy(send_pref.lo_addr.iabuf, &reply->lease->addr, 16);
4982 send_pref.bits = (
int) reply->lease->plen;
4985 status = reply_process_is_prefixed(reply, scope,
group);
4986 if (status != ISC_R_SUCCESS)
4989 status = reply_process_send_prefix(reply, &send_pref);
4998 reply_process_is_prefixed(
struct reply_state *reply,
5001 isc_result_t status = ISC_R_SUCCESS;
5009 memset(&data, 0,
sizeof(data));
5018 on_star = &reply->lease->on_star;
5030 reply->packet->options, tmp_options,
5033 if (tmp_options != NULL) {
5043 reply->packet->options, reply->opt_state,
5047 for (i = reply->packet->class_count; i > 0; i--) {
5049 reply->packet->options,
5050 reply->opt_state, scope,
5051 reply->packet->classes[i - 1]->group,
5060 if (reply->host != NULL)
5062 reply->packet->options,
5063 reply->opt_state, scope,
5064 reply->host->group,
group,
5068 if (reply->client_valid == 0)
5071 reply->send_valid = reply->client_valid;
5077 reply->packet->options,
5081 log_error(
"reply_process_is_prefixed: unable to " 5082 "evaluate default prefix time");
5083 status = ISC_R_FAILURE;
5087 reply->send_valid =
getULong(data.data);
5097 time_t test_time =
cur_time + reply->send_valid;
5102 if (reply->client_prefer == 0)
5103 reply->send_prefer = reply->send_valid;
5105 reply->send_prefer = reply->client_prefer;
5107 if ((reply->send_prefer >= reply->send_valid) &&
5109 reply->send_prefer = (reply->send_valid / 2) +
5110 (reply->send_valid / 8);
5116 reply->packet->options,
5120 log_error(
"reply_process_is_prefixed: unable to " 5121 "evaluate preferred prefix time");
5122 status = ISC_R_FAILURE;
5126 reply->send_prefer =
getULong(data.data);
5131 if (reply->min_prefer > reply->send_prefer)
5132 reply->min_prefer = reply->send_prefer;
5134 if (reply->min_valid > reply->send_valid)
5135 reply->min_valid = reply->send_valid;
5138 if (reply->lease != NULL) {
5140 reply->lease->prefer = reply->send_prefer;
5141 reply->lease->valid = reply->send_valid;
5149 reply->lease->soft_lifetime_end_time =
MAX_TIME;
5151 reply->lease->soft_lifetime_end_time =
5158 if (status != ISC_R_SUCCESS) {
5159 log_fatal(
"reply_process_is_prefixed: Unable to " 5160 "attach prefix to new IA_PD: %s",
5161 isc_result_totext(status));
5167 if (reply->lease->ia == NULL) {
5174 reply->packet->options, reply->reply_ia,
5178 for (i = reply->packet->class_count; i > 0; i--) {
5180 reply->packet->options,
5181 reply->reply_ia, scope,
5182 reply->packet->classes[i - 1]->group,
5190 if (reply->host != NULL)
5192 reply->packet->options,
5193 reply->reply_ia, scope,
5194 reply->host->group,
group, NULL);
5197 if (data.data != NULL)
5200 if (status == ISC_R_SUCCESS)
5201 reply->client_resources++;
5208 reply_process_send_prefix(
struct reply_state *reply,
5210 isc_result_t status = ISC_R_SUCCESS;
5218 log_error(
"reply_process_send_prefix: out of memory" 5219 "allocating new IAPREFIX buffer.");
5220 status = ISC_R_NOMEMORY;
5233 log_error(
"reply_process_send_prefix: unable " 5234 "to save IAPREFIX option");
5235 status = ISC_R_FAILURE;
5239 reply->resources_included = ISC_TRUE;
5242 if (
data.data != NULL)
5250 prefix_compare(
struct reply_state *reply,
5257 if (reply->preflen >= 0) {
5258 if ((alpha->
plen == reply->preflen) &&
5259 (beta->
plen != reply->preflen))
5261 if ((beta->
plen == reply->preflen) &&
5262 (alpha->
plen != reply->preflen))
5266 switch(alpha->
state) {
5268 switch(beta->
state) {
5289 switch (beta->
state) {
5315 switch (beta->
state) {
5337 log_fatal(
"Triple impossible condition at %s:%d.",
MDL);
5357 if (!valid_client_msg(
packet, &client_id)) {
5361 lease_to_client(reply_ret,
packet, &client_id, NULL);
5383 if (!valid_client_resp(
packet, &client_id, &server_id)) {
5390 is_unicast_option_defined(
packet) == ISC_FALSE) {
5391 unicast_reject(reply_ret,
packet, &client_id, &server_id);
5396 lease_to_client(reply_ret,
packet, &client_id, &server_id);
5412 const struct packet *chk_packet;
5413 const struct in6_addr *link_addr, *first_link_addr;
5414 struct iaddr tmp_addr;
5416 isc_result_t status;
5418 if ((shared == NULL) || (*shared != NULL) || (
packet == NULL))
5425 first_link_addr = NULL;
5427 while (chk_packet != NULL) {
5429 if (!IN6_IS_ADDR_UNSPECIFIED(link_addr) &&
5430 !IN6_IS_ADDR_LINKLOCAL(link_addr)) {
5431 first_link_addr = link_addr;
5442 if (first_link_addr != NULL) {
5443 tmp_addr.len =
sizeof(*first_link_addr);
5444 memcpy(tmp_addr.iabuf,
5445 first_link_addr,
sizeof(*first_link_addr));
5448 log_debug(
"No subnet found for link-address %s.",
5450 return ISC_R_NOTFOUND;
5452 status = shared_network_reference(shared,
5461 status = shared_network_reference(shared,
5465 log_info(
"[L2 Relay] No link address in relay packet " 5466 "assuming L2 relay and using receiving " 5476 log_error(
"No interface and no link address " 5477 "can't determine pool");
5507 struct data_string cli_enc_opt_data, iaaddr, client_id, packet_oro;
5509 struct iaddr cli_addr;
5511 isc_boolean_t inappropriate, has_addrs;
5512 char reply_data[65536];
5519 memset(&client_id, 0,
sizeof(client_id));
5520 if (!valid_client_msg(
packet, &client_id)) {
5529 if ((ia == NULL) && (ta == NULL))
5540 opt_state = cli_enc_opt_state = NULL;
5541 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5542 memset(&iaaddr, 0,
sizeof(iaaddr));
5543 memset(&packet_oro, 0,
sizeof(packet_oro));
5550 if ((shared_network_from_packet6(&shared,
packet) != ISC_R_SUCCESS) ||
5562 has_addrs = inappropriate = ISC_FALSE;
5564 while(!inappropriate) {
5568 if ((pass ==
D6O_IA_NA) && (ia == NULL)) {
5578 !get_encapsulated_IA_state(&cli_enc_opt_state,
5582 !get_encapsulated_IA_state(&cli_enc_opt_state,
5591 for ( ; oc != NULL ; oc = oc->
next) {
5597 "error evaluating IAADDR.");
5603 memcpy(cli_addr.iabuf, iaaddr.data, 16);
5608 has_addrs = ISC_TRUE;
5627 inappropriate = ISC_TRUE;
5646 if (!start_reply(
packet, &client_id, NULL, &opt_state, reply)) {
5653 if (inappropriate) {
5655 "Some of the addresses are not on link.",
5661 "All addresses still on link.",
5671 sizeof(reply_data)-reply_ofs,
5673 required_opts, &packet_oro);
5678 reply_ret->
len = reply_ofs;
5679 reply_ret->
buffer = NULL;
5684 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
5688 if (cli_enc_opt_data.buffer != NULL)
5690 if (iaaddr.buffer != NULL)
5692 if (client_id.
buffer != NULL)
5694 if (packet_oro.buffer != NULL)
5698 if (cli_enc_opt_state != NULL)
5700 if (opt_state != NULL)
5719 if (!valid_client_resp(
packet, &client_id, &server_id)) {
5726 is_unicast_option_defined(
packet) == ISC_FALSE) {
5727 unicast_reject(reply,
packet, &client_id, &server_id);
5732 lease_to_client(reply,
packet, &client_id, &server_id);
5753 if (!valid_client_msg(
packet, &client_id)) {
5757 lease_to_client(reply,
packet, &client_id, NULL);
5763 ia_na_match_decline(
const struct data_string *client_id,
5767 char tmp_addr[INET6_ADDRSTRLEN];
5769 log_error(
"Client %s reports address %s is " 5770 "already in use by another host!",
5772 inet_ntop(AF_INET6, iaaddr->
data,
5773 tmp_addr,
sizeof(tmp_addr)));
5774 if (
lease != NULL) {
5782 ia_na_nomatch_decline(
const struct data_string *client_id,
5784 u_int32_t *ia_na_id,
5790 char tmp_addr[INET6_ADDRSTRLEN];
5794 log_info(
"Client %s declines address %s, which is not offered to it.",
5796 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
5801 host_opt_state = NULL;
5803 log_error(
"ia_na_nomatch_decline: out of memory " 5804 "allocating option_state.");
5816 if (reply_len < (*reply_ofs + 16)) {
5818 "out of space for reply packet.");
5826 reply_len-(*reply_ofs)-16,
5828 required_opts_STATUS_CODE, NULL);
5838 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
5840 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
5842 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
5843 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
5848 *reply_ofs += (len + 16);
5859 const char *packet_type,
5860 void (*ia_na_match)(),
5861 void (*ia_na_nomatch)())
5873 char reply_data[65536];
5876 char status_msg[32];
5878 struct ia_xx *existing_ia_na;
5887 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
5888 cli_enc_opt_state = NULL;
5889 memset(&iaaddr, 0,
sizeof(iaaddr));
5890 memset(&fixed_addr, 0,
sizeof(fixed_addr));
5911 log_error(
"iterate_over_ia_na: no memory for option_state.");
5924 (
unsigned char *)server_duid.data,
5927 "error saving server identifier.");
5934 (
unsigned char *)client_id->
data,
5938 "error saving client identifier.");
5942 snprintf(status_msg,
sizeof(status_msg),
"%s received.", packet_type);
5951 sizeof(reply_data)-reply_ofs,
5953 required_opts, NULL);
5960 ia != NULL; ia = ia->
next) {
5962 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
5968 iaid =
getULong(cli_enc_opt_data.data);
5986 memset(&iaaddr, 0,
sizeof(iaaddr));
5991 "error evaluating IAADDR.");
6005 cli_enc_opt_state,
MDL)) {
6006 if (packet_host != NULL) {
6012 while (host != NULL) {
6020 "evaluating host address.");
6023 if ((iaaddr.
len >= 16) &&
6024 !memcmp(fixed_addr.data, iaaddr.
data, 16)) {
6038 (
char *)client_id->
data,
6040 MDL) != ISC_R_SUCCESS) {
6041 log_fatal(
"iterate_over_ia_na: no memory for " 6045 existing_ia_na = NULL;
6047 (
unsigned char *)key.data,
6054 struct in6_addr *in6_addr;
6057 in6_addr = &tmp->
addr;
6058 if (memcmp(in6_addr,
6059 iaaddr.
data, 16) == 0) {
6070 if ((host != NULL) || (
lease != NULL)) {
6071 ia_na_match(client_id, &iaaddr,
lease);
6073 ia_na_nomatch(client_id, &iaaddr,
6074 (u_int32_t *)cli_enc_opt_data.data,
6075 packet, reply_data, &reply_ofs,
6076 sizeof(reply_data));
6079 if (
lease != NULL) {
6091 reply_ret->
len = reply_ofs;
6092 reply_ret->
buffer = NULL;
6097 memcpy(reply_ret->
buffer->
data, reply, reply_ofs);
6100 if (
lease != NULL) {
6103 if (fixed_addr.buffer != NULL) {
6106 if (iaaddr.
buffer != NULL) {
6109 if (cli_enc_opt_state != NULL) {
6112 if (cli_enc_opt_data.buffer != NULL) {
6115 if (opt_state != NULL) {
6142 if (!valid_client_resp(
packet, &client_id, &server_id)) {
6149 is_unicast_option_defined(
packet) == ISC_FALSE) {
6150 unicast_reject(reply,
packet, &client_id, &server_id);
6160 iterate_over_ia_na(reply,
packet, &client_id, &server_id,
6161 "Decline", ia_na_match_decline,
6162 ia_na_nomatch_decline);
6171 ia_na_match_release(
const struct data_string *client_id,
6175 char tmp_addr[INET6_ADDRSTRLEN];
6177 log_info(
"Client %s releases address %s",
6179 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
6180 if (
lease != NULL) {
6188 ia_na_nomatch_release(
const struct data_string *client_id,
6190 u_int32_t *ia_na_id,
6196 char tmp_addr[INET6_ADDRSTRLEN];
6200 log_info(
"Client %s releases address %s, which is not leased to it.",
6202 inet_ntop(AF_INET6, iaaddr->
data, tmp_addr,
sizeof(tmp_addr)));
6207 host_opt_state = NULL;
6209 log_error(
"ia_na_nomatch_release: out of memory " 6210 "allocating option_state.");
6215 "Release for non-leased address.",
6223 if (reply_len < (*reply_ofs + 16)) {
6225 "out of space for reply packet.");
6233 reply_len-(*reply_ofs)-16,
6235 required_opts_STATUS_CODE, NULL);
6245 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
6247 memcpy(reply_data+(*reply_ofs)+4, ia_na_id, 4);
6249 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
6250 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
6255 *reply_ofs += (len + 16);
6262 ia_pd_match_release(
const struct data_string *client_id,
6266 char tmp_addr[INET6_ADDRSTRLEN];
6268 log_info(
"Client %s releases prefix %s/%u",
6270 inet_ntop(AF_INET6, iapref->
data + 9,
6271 tmp_addr,
sizeof(tmp_addr)),
6273 if (prefix != NULL) {
6281 ia_pd_nomatch_release(
const struct data_string *client_id,
6283 u_int32_t *ia_pd_id,
6289 char tmp_addr[INET6_ADDRSTRLEN];
6293 log_info(
"Client %s releases prefix %s/%u, which is not leased to it.",
6295 inet_ntop(AF_INET6, iapref->
data + 9,
6296 tmp_addr,
sizeof(tmp_addr)),
6302 host_opt_state = NULL;
6304 log_error(
"ia_pd_nomatch_release: out of memory " 6305 "allocating option_state.");
6310 "Release for non-leased prefix.",
6318 if (reply_len < (*reply_ofs + 16)) {
6320 "out of space for reply packet.");
6328 reply_len-(*reply_ofs)-16,
6330 required_opts_STATUS_CODE, NULL);
6340 putUShort((
unsigned char *)reply_data+(*reply_ofs)+2, len + 12);
6342 memcpy(reply_data+(*reply_ofs)+4, ia_pd_id, 4);
6344 putULong((
unsigned char *)reply_data+(*reply_ofs)+8, 0);
6345 putULong((
unsigned char *)reply_data+(*reply_ofs)+12, 0);
6350 *reply_ofs += (len + 16);
6361 const char *packet_type,
6362 void (*ia_pd_match)(),
6363 void (*ia_pd_nomatch)())
6376 char reply_data[65536];
6379 struct ia_xx *existing_ia_pd;
6387 memset(&reply_new, 0,
sizeof(reply_new));
6389 memset(&cli_enc_opt_data, 0,
sizeof(cli_enc_opt_data));
6390 cli_enc_opt_state = NULL;
6391 memset(&iaprefix, 0,
sizeof(iaprefix));
6397 reply_len =
sizeof(reply_data) - reply_ret->
len;
6411 log_error(
"iterate_over_ia_pd: no memory for option_state.");
6423 ia != NULL; ia = ia->
next) {
6425 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
6431 iaid =
getULong(cli_enc_opt_data.data);
6442 for (; oc != NULL; oc = oc->
next) {
6443 memset(&iaprefix, 0,
sizeof(iaprefix));
6448 "error evaluating IAPREFIX.");
6462 cli_enc_opt_state,
MDL)) {
6463 if (packet_host != NULL) {
6469 while (host != NULL) {
6478 if (memcmp(iaprefix.data + 9,
6483 if ((l != NULL) && (iaprefix.len >= 17))
6494 (
char *)client_id->
data,
6496 MDL) != ISC_R_SUCCESS) {
6497 log_fatal(
"iterate_over_ia_pd: no memory for " 6501 existing_ia_pd = NULL;
6503 (
unsigned char *)key.data,
6530 if ((host != NULL) || (prefix != NULL)) {
6531 ia_pd_match(client_id, &iaprefix, prefix);
6533 ia_pd_nomatch(client_id, &iaprefix,
6534 (u_int32_t *)cli_enc_opt_data.data,
6535 packet, reply_data, &reply_ofs,
6536 reply_len - reply_ofs);
6539 if (prefix != NULL) {
6554 reply_new.len = reply_ret->
len + reply_ofs;
6558 reply_new.data = reply_new.buffer->data;
6559 memcpy(reply_new.buffer->data,
6561 memcpy(reply_new.buffer->data + reply_ret->
len,
6562 reply_data, reply_ofs);
6568 if (prefix != NULL) {
6571 if (iaprefix.buffer != NULL) {
6574 if (cli_enc_opt_state != NULL) {
6577 if (cli_enc_opt_data.buffer != NULL) {
6580 if (opt_state != NULL) {
6597 if (!valid_client_resp(
packet, &client_id, &server_id)) {
6604 is_unicast_option_defined(
packet) == ISC_FALSE) {
6605 unicast_reject(reply,
packet, &client_id, &server_id);
6610 iterate_over_ia_na(reply,
packet, &client_id, &server_id,
6611 "Release", ia_na_match_release,
6612 ia_na_nomatch_release);
6617 iterate_over_ia_pd(reply,
packet, &client_id, &server_id,
6618 "Release", ia_pd_match_release,
6619 ia_pd_nomatch_release);
6639 if (!valid_client_info_req(
packet, &server_id)) {
6646 memset(&client_id, 0,
sizeof(client_id));
6657 lease_to_client(reply,
packet, &client_id,
6658 server_id.
data != NULL ? &server_id : NULL);
6663 if (client_id.
data != NULL) {
6683 struct packet *enc_packet;
6684 unsigned char msg_type;
6688 char link_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6689 char peer_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
6692 static char reply_data[65536];
6700 memset(&a_opt, 0,
sizeof(a_opt));
6701 memset(&packet_ero, 0,
sizeof(packet_ero));
6702 memset(&enc_reply, 0,
sizeof(enc_reply));
6703 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
6712 link_addr,
sizeof(link_addr));
6714 peer_addr,
sizeof(peer_addr));
6715 log_info(
"Relay-forward from %s with link address=%s and " 6716 "peer address=%s missing Relay Message option.",
6724 log_error(
"dhcpv6_forw_relay: error evaluating " 6725 "relayed message.");
6731 log_error(
"dhcpv6_forw_relay: encapsulated packet too short.");
6742 "no memory for encapsulated packet.");
6749 "no memory for encapsulated packet's options.");
6774 enc_opt_data.
len - relaylen,
6786 "unsupported %s message type.",
6790 forw_dhcpv4_query(
packet);
6793 log_error(
"dhcpv6_relay_forw: unsupported %s message type.",
6809 enc_opt_data.
len - msglen,
6821 build_dhcpv6_reply(&enc_reply, enc_packet);
6827 if (enc_reply.data == NULL) {
6849 log_error(
"dhcpv6_relay_forw: no memory for option state.");
6863 log_error(
"dhcpv6_relay_forw: error evaluating " 6868 (
unsigned char *)a_opt.data,
6871 log_error(
"dhcpv6_relay_forw: error saving " 6878 #if defined(RELAY_PORT) 6889 log_error(
"dhcpv6_relay_forw: error evaluating " 6890 "Relay Source Port.");
6894 (
unsigned char *)a_opt.data,
6897 log_error(
"dhcpv6_relay_forw: error saving " 6898 "Relay Source Port.");
6911 (
unsigned char *)enc_reply.data,
6914 log_error(
"dhcpv6_relay_forw: error saving Relay MSG.");
6930 (packet_ero.len & 1)) {
6931 log_error(
"dhcpv6_relay_forw: error evaluating ERO.");
6936 for (i = 0; i < packet_ero.len; i += 2) {
6953 "evaluating option %u.", req);
6959 (
unsigned char *)a_opt.data,
6963 log_error(
"dhcpv6_relay_forw: error saving " 6972 sizeof(reply_data) - reply_ofs,
6974 required_opts_agent, &packet_ero);
6979 reply_ret->
len = reply_ofs;
6980 reply_ret->
buffer = NULL;
6985 memcpy(reply_ret->
buffer->
data, reply_data, reply_ofs);
6988 if (opt_state != NULL)
6990 if (a_opt.data != NULL) {
6993 if (packet_ero.data != NULL) {
6996 if (enc_reply.data != NULL) {
6999 if (enc_opt_data.
data != NULL) {
7002 if (enc_packet != NULL) {
7021 struct packet *enc_packet;
7022 unsigned char msg_type;
7026 char link_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
7027 char peer_addr[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
7030 static char reply_data[65536];
7038 memset(&a_opt, 0,
sizeof(a_opt));
7039 memset(&packet_ero, 0,
sizeof(packet_ero));
7040 memset(&enc_reply, 0,
sizeof(enc_reply));
7041 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
7050 link_addr,
sizeof(link_addr));
7052 peer_addr,
sizeof(peer_addr));
7053 log_info(
"Relay-forward from %s with link address=%s and " 7054 "peer address=%s missing Relay Message option.",
7061 log_error(
"dhcp4o6_relay_forw: error evaluating " 7062 "relayed message.");
7068 "encapsulated packet too short.");
7077 "no memory for encapsulated packet.");
7083 "no memory for encapsulated packet's options.");
7108 enc_opt_data.
len - relaylen,
7128 enc_opt_data.
len - msglen,
7135 log_error(
"dhcp4o6_relay_forw: unexpected message of type %d.",
7144 build_dhcpv6_reply(&enc_reply, enc_packet);
7150 if (enc_reply.data == NULL) {
7171 log_error(
"dhcp4o6_relay_forw: no memory for option state.");
7185 log_error(
"dhcp4o6_relay_forw: error evaluating " 7190 (
unsigned char *)a_opt.data,
7193 log_error(
"dhcp4o6_relay_forw: error saving " 7200 #if defined(RELAY_PORT) 7211 log_error(
"dhcpv4o6_relay_forw: error evaluating " 7212 "Relay Source Port.");
7216 (
unsigned char *)a_opt.data,
7219 log_error(
"dhcpv4o6_relay_forw: error saving " 7220 "Relay Source Port.");
7233 (
unsigned char *)enc_reply.data,
7236 log_error(
"dhcp4o6_relay_forw: error saving Relay MSG.");
7252 (packet_ero.len & 1)) {
7253 log_error(
"dhcp4o6_relay_forw: error evaluating ERO.");
7258 for (i = 0; i < packet_ero.len; i += 2) {
7275 "evaluating option %u.", req);
7281 (
unsigned char *)a_opt.data,
7285 log_error(
"dhcp4o6_relay_forw: error saving " 7294 sizeof(reply_data) - reply_ofs,
7296 required_opts_agent, &packet_ero);
7301 reply_ret->
len = reply_ofs;
7302 reply_ret->
buffer = NULL;
7307 memcpy(reply_ret->
buffer->
data, reply_data, reply_ofs);
7310 if (opt_state != NULL)
7312 if (a_opt.data != NULL) {
7315 if (packet_ero.data != NULL) {
7318 if (enc_reply.data != NULL) {
7321 if (enc_opt_data.
data != NULL) {
7324 if (enc_packet != NULL) {
7342 struct packet *enc_packet;
7345 static char response_data[65536];
7353 memset(&enc_response, 0,
sizeof(enc_response));
7354 memset(&enc_opt_data, 0,
sizeof(enc_opt_data));
7362 log_info(
"DHCPv4-query from %s missing DHCPv4 Message option.",
7369 log_error(
"dhcp4o6_dhcpv4_query: error evaluating " 7375 log_error(
"dhcp4o6_dhcpv4_query: DHCPv4 packet too short.");
7384 "no memory for encapsulated packet.");
7400 "discarding packet with bogus hlen.");
7406 log_error(
"dhcp4o6_dhcpv4_query: no memory for options.");
7426 memset(&dp, 0,
sizeof dp);
7452 if (enc_response.data == NULL) {
7469 log_error(
"dhcp4o6_dhcpv4_query: no memory for option state.");
7477 (
unsigned char *)enc_response.data,
7480 log_error(
"dhcp4o6_dhcpv4_query: error saving DHCPv4 MSG.");
7485 sizeof(response_data) - response_ofs,
7487 required_opts_4o6, NULL);
7492 reply_ret->
len = response_ofs;
7493 reply_ret->
buffer = NULL;
7495 log_fatal(
"dhcp4o6_dhcpv4_query: no memory to store reply.");
7498 memcpy(reply_ret->
buffer->
data, response_data, response_ofs);
7501 if (opt_state != NULL)
7503 if (enc_response.data != NULL) {
7506 if (enc_opt_data.
data != NULL) {
7509 if (enc_packet != NULL) {
7524 struct udp_data4o6 udp_data;
7536 log_error(
"forw_dhcpv4_query: can't find initial message.");
7542 memset(&ds, 0,
sizeof(ds));
7545 "no memory for encapsulating packet.");
7548 ds.data = ds.buffer->data;
7553 memcpy(ds.buffer->data + 16,
7555 memset(&udp_data, 0,
sizeof(udp_data));
7557 memcpy(ds.buffer->data + 32, &udp_data, 4);
7558 memcpy(ds.buffer->data + 36,
7563 cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
7565 log_error(
"forw_dhcpv4_query: send(): %m");
7575 log_debug(
"Discarding %s from %s; message type not handled by server",
7582 memset(reply, 0,
sizeof(*reply));
7595 dhcpv6_solicit(reply,
packet);
7602 dhcpv6_request(reply,
packet);
7606 dhcpv6_confirm(reply,
packet);
7610 dhcpv6_renew(reply,
packet);
7614 dhcpv6_rebind(reply,
packet);
7621 dhcpv6_release(reply,
packet);
7625 dhcpv6_decline(reply,
packet);
7632 dhcpv6_information_request(reply,
packet);
7637 dhcp4o6_relay_forw(reply,
packet);
7640 dhcpv6_relay_forw(reply,
packet);
7656 forw_dhcpv4_query(
packet);
7658 dhcp4o6_dhcpv4_query(reply,
packet);
7670 log_info(
"Discarding unknown DHCPv6 message type %d " 7680 char tmp_addr[INET6_ADDRSTRLEN];
7683 memset(&s, 0,
sizeof(s));
7692 "Unknown message type %d from %s port %d",
7701 inet_ntop(AF_INET6, addr,
7702 tmp_addr,
sizeof(tmp_addr)));
7705 inet_ntop(AF_INET6, addr,
7706 tmp_addr,
sizeof(tmp_addr)));
7739 struct sockaddr_in6 to_addr;
7750 build_dhcpv6_reply(&reply,
packet);
7752 if (reply.
data != NULL) {
7756 memset(&to_addr, 0,
sizeof(to_addr));
7757 to_addr.sin6_family = AF_INET6;
7765 #if defined (REPLY_TO_SOURCE_PORT) 7776 #if defined(RELAY_PORT) 7786 sizeof(to_addr.sin6_addr));
7788 log_info(
"Sending %s to %s port %d",
7791 ntohs(to_addr.sin6_port));
7794 reply.
data, reply.
len, &to_addr);
7795 if (send_ret != reply.
len) {
7796 log_error(
"dhcpv6: send_packet6() sent %d of %d bytes",
7797 send_ret, reply.
len);
7815 static void recv_dhcpv4_query(
struct data_string *raw) {
7820 unsigned char msg_type;
7825 struct udp_data4o6 udp_data;
7829 memset(name, 0,
sizeof(name));
7830 memcpy(name, raw->
data, 16);
7832 if (!strcmp(name,
ip->name))
7836 log_error(
"recv_dhcpv4_query: can't find interface %s.",
7844 memset(&udp_data, 0,
sizeof(udp_data));
7845 memcpy(&udp_data, raw->
data + 32, 4);
7853 "short packet from %s, len %d, dropped",
7863 log_error(
"recv_dhcpv4_query: no memory for packet.");
7868 log_error(
"recv_dhcpv4_query: no memory for options.");
7879 msg_type = raw->
data[36];
7896 raw->
len - 36 - relaylen,
7916 raw->
len - 36 - msglen,
7924 log_error(
"recv_dhcpv4_query: unexpected message of type %d.",
7938 memset(&ds, 0,
sizeof(ds));
7945 "Unknown message type %d from %s",
7951 char tmp_addr[INET6_ADDRSTRLEN];
7956 inet_ntop(AF_INET6, addr,
7957 tmp_addr,
sizeof(tmp_addr)));
7960 inet_ntop(AF_INET6, addr,
7961 tmp_addr,
sizeof(tmp_addr)));
7975 build_dhcpv6_reply(&reply,
packet);
7977 if (reply.
data == NULL) {
7985 len = reply.
len + 36;
7986 memset(&ds, 0,
sizeof(ds));
7988 log_error(
"recv_dhcpv4_query: no memory.");
7992 ds.data = ds.buffer->data;
7995 memcpy(ds.buffer->data, name, 16);
7996 memcpy(ds.buffer->data + 16,
iaddr.
iabuf, 16);
7998 memcpy(ds.buffer->data + 32, &udp_data, 4);
7999 memcpy(ds.buffer->data + 36, reply.
data, reply.
len);
8006 cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
8008 log_error(
"recv_dhcpv4_query: send(): %m");
8023 host_reference(&hold, *hp,
MDL);
8024 host_dereference(hp,
MDL);
8026 while (seek != NULL) {
8029 else if (fixed_matches_shared(seek, shared))
8035 if ((seek == NULL) && (nofixed != NULL))
8039 host_reference(hp, seek,
MDL);
8042 static isc_boolean_t
8046 isc_boolean_t matched;
8052 memset(&addr, 0,
sizeof(addr));
8057 if (addr.len < 16) {
8063 memcpy(fixed.iabuf, addr.data, 16);
8065 matched = ISC_FALSE;
8101 struct reply_state reply;
8102 memset(&reply, 0x0,
sizeof(
struct reply_state));
8105 if (shared_network_from_packet6(&reply.shared,
packet)
8107 log_error(
"unicast_reject: could not locate client.");
8115 if (start_reply(
packet, client_id, server_id, &reply.opt_state,
8116 &reply.buf.reply)) {
8119 "Unicast not allowed by server.",
8121 log_error(
"unicast_reject: Unable to set status code.");
8131 unicast_reject_opts,
8135 reply_ret->
len = reply.cursor;
8136 reply_ret->
buffer = NULL;
8138 reply.cursor,
MDL)) {
8140 "No memory to store Reply.");
8151 if (reply.shared != NULL)
8152 shared_network_dereference(&reply.shared,
MDL);
8153 if (reply.opt_state != NULL)
8155 if (reply.packet != NULL)
8157 if (reply.client_id.
data != NULL)
8181 isc_boolean_t is_defined = ISC_FALSE;
8188 "No memory for option state.");
8193 if (((shared_network_from_requested_addr(&shared,
packet)
8194 != ISC_R_SUCCESS) &&
8195 (shared_network_from_packet6(&shared,
packet) != ISC_R_SUCCESS))
8196 || (shared == NULL)) {
8200 "cannot attribute packet to a network.");
8211 is_defined = (oc != NULL ? ISC_TRUE : ISC_FALSE);
8212 log_debug(
"is_unicast_option_defined: option found : %d", is_defined);
8214 if (shared != NULL) {
8215 shared_network_dereference(&shared,
MDL);
8218 if (opt_state != NULL) {
8222 return (is_defined);
8241 shared_network_from_requested_addr (
struct shared_network **shared,
8245 isc_result_t status = ISC_R_FAILURE;
8254 != ISC_R_SUCCESS)) {
8256 log_debug(
"share_network_from_request_addr: nothing to match");
8257 return (ISC_R_FAILURE);
8261 log_debug(
"shared_network_from_requested_addr:" 8264 status = shared_network_reference(shared,
8267 log_debug(
"shared_network_from_requested_addr:" 8268 " found shared network %s for address %s.",
8269 ((*shared)->name ? (*shared)->name :
"unnamed"),
8274 return (ISC_R_FAILURE);
8296 get_first_ia_addr_val (
struct packet*
packet,
int addr_type,
8302 int addr_opt_offset;
8304 int addr_opt_data_len;
8307 isc_result_t status = ISC_R_FAILURE;
8311 switch (addr_type) {
8315 addr_opt_data_len = 24;
8321 addr_opt_data_len = 24;
8327 addr_opt_data_len = 25;
8332 log_error (
"get_first_ia_addr_val: invalid opt type %d",
8334 return (ISC_R_FAILURE);
8339 ia != NULL && oc == NULL; ia = ia->
next) {
8340 if (!get_encapsulated_IA_state(&cli_enc_opt_state,
8342 packet, ia, addr_opt_offset)) {
8344 " couldn't unroll enclosing option");
8345 return (ISC_R_FAILURE);
8361 memset(&iaddr_str, 0,
sizeof(iaddr_str));
8366 "error evaluating IA_XX option.");
8368 if (iaddr_str.len != addr_opt_data_len) {
8369 log_error(
"shared_network_from_requested_addr:" 8370 " invalid length %d, expected %d",
8371 iaddr_str.len, addr_opt_data_len);
8375 iaddr_str.data + ip_addr_offset, 16);
8376 status = ISC_R_SUCCESS;
8418 set_reply_tee_times(
struct reply_state* reply,
unsigned ia_cursor)
8426 set_tee_times = (oc &&
8429 reply->packet->options,
8441 reply->packet->options,
8451 if (
data.data != NULL)
8453 }
else if (set_tee_times) {
8459 reply->renew = reply->min_prefer / 2;
8465 putULong(reply->buf.data + ia_cursor + 8, reply->renew);
8476 reply->packet->options,
8486 if (
data.data != NULL)
8488 }
else if (set_tee_times) {
8494 reply->rebind = (reply->min_prefer / 5) * 4;
8500 putULong(reply->buf.data + ia_cursor + 12, reply->rebind);
8510 release_on_roam(
struct reply_state* reply) {
8511 struct ia_xx* old_ia = reply->old_ia;
8525 if (
lease->ipv6_pool->shared_network == reply->shared) {
8534 log_info(
"Client: %s roamed to new network," 8535 " releasing lease: %s%s",
8537 reply->client_id.data, 60),
8554 static char prefix_buf[16];
8557 sprintf(prefix_buf,
"/%-d",
lease->plen);
8560 return (prefix_buf);
8574 void ddns_update_static6(
struct reply_state* reply) {
8582 reply->packet->options,
8583 reply->opt_state, NULL,
8593 reply->packet->options,
8594 reply->opt_state, NULL,
8599 if (iasubopt_allocate(&iasub,
MDL) != ISC_R_SUCCESS) {
8609 memcpy(iasub->
addr.s6_addr, reply->fixed.data, 16);
8616 log_fatal(
"Out of memory for binding scope.");
8621 ddns_updates(reply->packet, NULL, NULL, iasub, NULL, reply->opt_state);
struct iaddrcidrnet cidrnet
#define IASUBOPT_PD_VALID_OFFSET
#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)
struct dhcp_ddns_cb * ddns_cb
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)
struct lease_state * state
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)
#define IASUBOPT_NA_PREF_OFFSET
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
#define D6O_RELAY_SOURCE_PORT
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)
#define IASUBOPT_NA_ADDR_OFFSET
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)
#define IASUBOPT_PD_PREF_OFFSET
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
int binding_scope_allocate(struct binding_scope **ptr, const char *file, int line)
ssize_t send_packet6(struct interface_info *, const unsigned char *, size_t, struct sockaddr_in6 *)
void putULong(unsigned char *, u_int32_t)
#define DEFAULT_CACHE_THRESHOLD
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 IASUBOPT_NA_VALID_OFFSET
#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)
const char * pin6_addr(const struct in6_addr *)
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
isc_result_t find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type, const struct in6_addr *addr)
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 IASUBOPT_PD_PREFIX_OFFSET
#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)
int binding_scope_reference(struct binding_scope **ptr, struct binding_scope *bp, const char *file, int line)
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]
#define SV_CACHE_THRESHOLD
time_t soft_lifetime_end_time
#define SV_DEFAULT_LEASE_TIME
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
isc_boolean_t relay_source_port
#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)
struct binding_scope * scope
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
#define SV_UPDATE_STATIC_LEASES
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)
#define IASUBOPT_PD_PREFLEN_OFFSET