Import Mbed OS hard-float snapshot
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef DHCPV6_CLIENT_API_H_
|
||||
#define DHCPV6_CLIENT_API_H_
|
||||
#include <ns_types.h>
|
||||
|
||||
/* DHCP client implementation.
|
||||
*
|
||||
* Responsibilities of this module are:
|
||||
* - handle Global address queries and refresh inside network.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Initialize dhcp client.
|
||||
*
|
||||
* This instance needs to bee initialized once for each network interface.
|
||||
* if only one thread instance is supported this is needed to call only once.
|
||||
*
|
||||
* /param interface interface id of this instance.
|
||||
* /param link_type DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE, DHCPV6_DUID_HARDWARE_EUI64_TYPE or DHCPV6_DUID_HARDWARE_EUI48_TYPE
|
||||
*
|
||||
*/
|
||||
void dhcp_client_init(int8_t interface, uint16_t link_type);
|
||||
|
||||
/* Set configurations for DHCP client
|
||||
*
|
||||
* /param interface Client Inteface ID
|
||||
* /param renew_uses_solicit Instead of renew message SOLICIT is used.
|
||||
* /param one_client_for_this_interface True Interface use oneinstance for allocate address
|
||||
* /param no_address_hint IAID use address at Solicit
|
||||
*/
|
||||
void dhcp_client_configure(int8_t interface, bool renew_uses_solicit, bool one_client_for_this_interface, bool no_address_hint);
|
||||
|
||||
/* Set Timeout parameters for SOLICIT transactions
|
||||
*
|
||||
* /param timeout SOLICIT timeout initial value. 0 means use defaults
|
||||
* /param max_rt SOLICIT timeout max value.
|
||||
* /param max_rc SOLICIT re-transmission count. 0 means infinite.
|
||||
*/
|
||||
void dhcp_client_solicit_timeout_set(int8_t interface, uint16_t timeout, uint16_t max_rt, uint8_t max_rc);
|
||||
|
||||
/* Delete dhcp client.
|
||||
*
|
||||
* When this is called all addressed assigned by this module are removed from stack.
|
||||
*/
|
||||
void dhcp_client_delete(int8_t interface);
|
||||
|
||||
/* Global address handler.
|
||||
*
|
||||
* This module updates the addresses from dhcp server and sets them in stack.
|
||||
* this module makes refresh of address when needed.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* give dhcp server and prefix for global address assignment
|
||||
*
|
||||
* /param interface interface where address is got
|
||||
* /param dhcp_addr dhcp server ML16 address where address is registered.
|
||||
* /param prefix dhcp server ML16 address where address is registered.
|
||||
* /param error_cb error callback that is called if address cannot be created or becomes invalid.
|
||||
* /param register_status true if address registered.
|
||||
*
|
||||
*/
|
||||
typedef void (dhcp_client_global_adress_cb)(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status);
|
||||
|
||||
int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], dhcp_client_global_adress_cb *error_cb);
|
||||
|
||||
/* Renew all leased adddresses might be used when short address changes
|
||||
*
|
||||
* /param interface interface where address is got
|
||||
*/
|
||||
void dhcp_client_global_address_renew(int8_t interface);
|
||||
|
||||
/* Delete address from device
|
||||
* if prefix is NULL all are deleted
|
||||
*
|
||||
* /param interface interface where address is got
|
||||
* /param prefix dhcp server ML16 address where address is registered.
|
||||
*
|
||||
*/
|
||||
void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uint8_t prefix[static 16]);
|
||||
|
||||
|
||||
void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]);
|
||||
|
||||
int dhcp_client_server_address_update(int8_t interface, uint8_t *prefix, uint8_t server_address[static 16]);
|
||||
|
||||
|
||||
|
||||
#endif /* DHCPV6_CLIENT_API_H_ */
|
||||
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include <ns_types.h>
|
||||
#include <ns_trace.h>
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "ns_list.h"
|
||||
#include "common_functions.h"
|
||||
|
||||
#ifdef HAVE_DHCPV6
|
||||
#include "dhcp_service_api.h"
|
||||
#include "dhcpv6_client_api.h"
|
||||
#include "libDHCPv6/libDHCPv6.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
|
||||
#define TRACE_GROUP "DHP"
|
||||
|
||||
typedef struct {
|
||||
dhcp_client_global_adress_cb *global_address_cb;
|
||||
uint16_t service_instance;
|
||||
uint16_t relay_instance;
|
||||
uint16_t sol_timeout;
|
||||
uint16_t sol_max_rt;
|
||||
uint8_t sol_max_rc;
|
||||
uint8_t libDhcp_instance;
|
||||
dhcp_duid_options_params_t duid;
|
||||
int8_t interface;
|
||||
bool renew_uses_solicit: 1;
|
||||
bool one_instance_interface: 1;
|
||||
bool no_address_hint: 1;
|
||||
ns_list_link_t link; /*!< List link entry */
|
||||
} dhcp_client_class_t;
|
||||
|
||||
static NS_LARGE NS_LIST_DEFINE(dhcp_client_list, dhcp_client_class_t, link);
|
||||
|
||||
static bool dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr);
|
||||
void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason);
|
||||
|
||||
|
||||
|
||||
static dhcp_client_class_t *dhcpv6_client_entry_allocate(int8_t interface, uint8_t duid_length)
|
||||
{
|
||||
dhcp_client_class_t *entry = ns_dyn_mem_alloc(sizeof(dhcp_client_class_t));
|
||||
uint8_t *duid = ns_dyn_mem_alloc(duid_length);
|
||||
if (!entry || !duid) {
|
||||
ns_dyn_mem_free(entry);
|
||||
ns_dyn_mem_free(duid);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
memset(entry, 0, sizeof(dhcp_client_class_t));
|
||||
entry->interface = interface;
|
||||
entry->service_instance = dhcp_service_init(interface, DHCP_INSTANCE_CLIENT, NULL);
|
||||
entry->libDhcp_instance = libdhcpv6_nonTemporal_entry_get_unique_instance_id();
|
||||
entry->duid.duid = duid;
|
||||
entry->duid.duid_length = duid_length;
|
||||
entry->duid.type = DHCPV6_DUID_LINK_LAYER_TYPE;
|
||||
ns_list_add_to_end(&dhcp_client_list, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
//Discover DHCPv6 client
|
||||
static dhcp_client_class_t *dhcpv6_client_entry_discover(int8_t interface)
|
||||
{
|
||||
ns_list_foreach(dhcp_client_class_t, cur, &dhcp_client_list) {
|
||||
//Check All allocated address in this module
|
||||
if (cur->interface == interface) {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void dhcp_client_init(int8_t interface, uint16_t link_type)
|
||||
{
|
||||
protocol_interface_info_entry_t *interface_ptr = protocol_stack_interface_info_get_by_id(interface);
|
||||
if (!interface_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
|
||||
|
||||
if (dhcp_client) {
|
||||
dhcp_client->sol_timeout = 0;
|
||||
dhcp_client->sol_max_rt = 0;
|
||||
dhcp_client->sol_max_rc = 0;
|
||||
dhcp_client->renew_uses_solicit = false;
|
||||
dhcp_client->one_instance_interface = false;
|
||||
dhcp_client->no_address_hint = false;
|
||||
dhcp_client->service_instance = dhcp_service_init(interface, DHCP_INSTANCE_CLIENT, NULL);
|
||||
dhcp_client->libDhcp_instance = libdhcpv6_nonTemporal_entry_get_unique_instance_id();
|
||||
return;
|
||||
}
|
||||
//Allocate new
|
||||
//define DUID-LL length based on MAC64 or MAC48
|
||||
|
||||
dhcp_client = dhcpv6_client_entry_allocate(interface, libdhcpv6_duid_linktype_size(link_type) + 2);
|
||||
if (!dhcp_client) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *ptr = dhcp_client->duid.duid;
|
||||
ptr = common_write_16_bit(link_type, ptr);
|
||||
memcpy(ptr, interface_ptr->mac, libdhcpv6_duid_linktype_size(link_type));
|
||||
|
||||
//Define DUID
|
||||
|
||||
|
||||
}
|
||||
void dhcp_client_configure(int8_t interface, bool renew_uses_solicit, bool one_client_for_this_interface, bool no_address_hint)
|
||||
{
|
||||
// Set true if RENEW is not used and SOLICIT sent instead.
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
|
||||
if (!dhcp_client) {
|
||||
return;
|
||||
}
|
||||
dhcp_client->renew_uses_solicit = renew_uses_solicit;
|
||||
dhcp_client->one_instance_interface = one_client_for_this_interface;
|
||||
dhcp_client->no_address_hint = no_address_hint;
|
||||
}
|
||||
|
||||
void dhcp_client_solicit_timeout_set(int8_t interface, uint16_t timeout, uint16_t max_rt, uint8_t max_rc)
|
||||
{
|
||||
// Set the default retry values for SOLICIT and RENEW messages.
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
|
||||
if (!dhcp_client) {
|
||||
return;
|
||||
}
|
||||
dhcp_client->sol_timeout = timeout;
|
||||
dhcp_client->sol_max_rt = max_rt;
|
||||
dhcp_client->sol_max_rc = max_rc;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16])
|
||||
{
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
|
||||
if (!dhcp_client) {
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp_client->relay_instance = dhcp_service_init(interface, DHCP_INTANCE_RELAY_AGENT, NULL);
|
||||
dhcp_service_relay_instance_enable(dhcp_client->relay_instance, border_router_address);
|
||||
}
|
||||
|
||||
void dhcp_client_delete(int8_t interface)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = NULL;
|
||||
dhcpv6_client_server_data_t *srv_data_ptr;
|
||||
uint8_t temporary_address[16];
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
|
||||
if (!dhcp_client) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
dhcp_service_delete(dhcp_client->service_instance);
|
||||
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface);
|
||||
|
||||
if (!cur) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client->libDhcp_instance);
|
||||
if (srv_data_ptr != NULL) {
|
||||
tr_debug("Free DHCPv6 Client\n");
|
||||
memcpy(temporary_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, 16);
|
||||
dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
|
||||
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
|
||||
addr_delete(cur, temporary_address);
|
||||
|
||||
}
|
||||
} while (srv_data_ptr != NULL);
|
||||
dhcp_client->service_instance = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr)
|
||||
{
|
||||
if (srv_data_ptr != NULL) {
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(srv_data_ptr->interfaceId);
|
||||
if (!dhcp_client) {
|
||||
return;
|
||||
}
|
||||
|
||||
// error for Global address
|
||||
if (dhcp_client->global_address_cb != NULL) {
|
||||
dhcp_client->global_address_cb(dhcp_client->interface, srv_data_ptr->server_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* solication responce received for either global address or routter id assignment */
|
||||
int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uint8_t *msg_ptr, uint16_t msg_len)
|
||||
{
|
||||
dhcp_ia_non_temporal_params_t dhcp_ia_non_temporal_params;
|
||||
dhcp_duid_options_params_t clientId;
|
||||
dhcp_duid_options_params_t serverId;
|
||||
dhcpv6_client_server_data_t *srv_data_ptr = NULL;
|
||||
(void)instance_id;
|
||||
|
||||
//Validate that started TR ID class is still at list
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_validate_class_pointer(ptr);
|
||||
|
||||
|
||||
if (srv_data_ptr == NULL) {
|
||||
tr_error("server data not found");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(srv_data_ptr->interfaceId);
|
||||
if (!dhcp_client) {
|
||||
tr_error("No DHCPv6 client avilabale");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
|
||||
//Clear Active Transaction state
|
||||
srv_data_ptr->transActionId = 0;
|
||||
|
||||
// Validate message
|
||||
if (msg_name != DHCPV6_REPLY_TYPE) {
|
||||
tr_error("invalid response");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (libdhcpv6_reply_message_option_validate(&clientId, &serverId, &dhcp_ia_non_temporal_params, msg_ptr, msg_len) != 0) {
|
||||
tr_error("Reply Not include all Options");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (libdhcpv6_nonTemporal_entry_get_by_iaid(dhcp_ia_non_temporal_params.iaId) != srv_data_ptr) {
|
||||
/* Validate server data availability */
|
||||
tr_error("Valid instance not found");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (srv_data_ptr->IAID != dhcp_ia_non_temporal_params.iaId) {
|
||||
tr_error("Wrong IAID");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (libdhcpv6_compare_DUID(&srv_data_ptr->clientDUID, &clientId) != 0) {
|
||||
tr_error("Not Valid Client Id");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
//Allocate dynamically new Server DUID if needed
|
||||
if (!srv_data_ptr->serverDynamic_DUID || serverId.duid_length > srv_data_ptr->dyn_server_duid_length) {
|
||||
//Allocate dynamic new bigger
|
||||
srv_data_ptr->dyn_server_duid_length = 0;
|
||||
ns_dyn_mem_free(srv_data_ptr->serverDynamic_DUID);
|
||||
srv_data_ptr->serverDynamic_DUID = ns_dyn_mem_alloc(serverId.duid_length);
|
||||
if (!srv_data_ptr->serverDynamic_DUID) {
|
||||
tr_error("Dynamic DUID alloc fail");
|
||||
goto error_exit;
|
||||
}
|
||||
srv_data_ptr->dyn_server_duid_length = serverId.duid_length;
|
||||
}
|
||||
|
||||
//Copy Server DUID
|
||||
srv_data_ptr->serverDUID.duid = srv_data_ptr->serverDynamic_DUID;
|
||||
srv_data_ptr->serverDUID.type = serverId.type;
|
||||
srv_data_ptr->serverDUID.duid_length = serverId.duid_length;
|
||||
memcpy(srv_data_ptr->serverDUID.duid, serverId.duid, serverId.duid_length);
|
||||
|
||||
if (dhcp_client->one_instance_interface && memcmp(srv_data_ptr->iaNontemporalAddress.addressPrefix, dhcp_ia_non_temporal_params.nonTemporalAddress, 16)) {
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(dhcp_client->interface);
|
||||
if (cur) {
|
||||
addr_deprecate(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(srv_data_ptr->iaNontemporalAddress.addressPrefix, dhcp_ia_non_temporal_params.nonTemporalAddress, 16);
|
||||
srv_data_ptr->iaNontemporalAddress.preferredTime = dhcp_ia_non_temporal_params.preferredValidLifeTime;
|
||||
srv_data_ptr->iaNontemporalAddress.validLifetime = dhcp_ia_non_temporal_params.validLifeTime;
|
||||
srv_data_ptr->T0 = dhcp_ia_non_temporal_params.T0;
|
||||
srv_data_ptr->T1 = dhcp_ia_non_temporal_params.T1;
|
||||
|
||||
|
||||
bool status = dhcpv6_client_set_address(dhcp_client->interface, srv_data_ptr);
|
||||
|
||||
|
||||
if (dhcp_client->global_address_cb) {
|
||||
dhcp_client->global_address_cb(dhcp_client->interface, srv_data_ptr->server_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, status);
|
||||
}
|
||||
return RET_MSG_ACCEPTED;
|
||||
error_exit:
|
||||
dhcpv6_client_send_error_cb(srv_data_ptr);
|
||||
return RET_MSG_ACCEPTED;
|
||||
}
|
||||
|
||||
int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], dhcp_client_global_adress_cb *error_cb)
|
||||
{
|
||||
dhcpv6_solication_base_packet_s solPacket = {0};
|
||||
|
||||
uint8_t *payload_ptr;
|
||||
uint32_t payload_len;
|
||||
dhcpv6_client_server_data_t *srv_data_ptr;
|
||||
bool add_prefix;
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
|
||||
|
||||
if (dhcp_addr == NULL || !dhcp_client) {
|
||||
tr_error("Invalid parameters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!prefix || dhcp_client->one_instance_interface) {
|
||||
//NULL Definition will only check That Interface is not generated
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client->libDhcp_instance);
|
||||
if (srv_data_ptr) {
|
||||
//Already Created to same interface
|
||||
if (dhcp_client->one_instance_interface && prefix) {
|
||||
if (srv_data_ptr->iaNonTemporalStructValid) {
|
||||
if (memcmp(srv_data_ptr->iaNontemporalAddress.addressPrefix, prefix, 8) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface);
|
||||
if (!cur) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
|
||||
addr_deprecate(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
srv_data_ptr->iaNonTemporalStructValid = false;
|
||||
memcpy(srv_data_ptr->iaNontemporalAddress.addressPrefix, prefix, 8);
|
||||
goto dhcp_address_get;
|
||||
|
||||
} else if (dhcp_client_server_address_update(interface, prefix, dhcp_addr) == 0) {
|
||||
//DHCP server address OK
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
} else if (dhcp_client_server_address_update(interface, prefix, dhcp_addr) == 0) {
|
||||
//No need for allocate new
|
||||
return 0;
|
||||
}
|
||||
|
||||
tr_debug("GEN new Dhcpv6 client %u", dhcp_client->libDhcp_instance);
|
||||
srv_data_ptr = libdhcvp6_nontemporalAddress_server_data_allocate(interface, dhcp_client->libDhcp_instance, prefix, dhcp_addr);
|
||||
|
||||
if (!srv_data_ptr) {
|
||||
tr_error("OOM srv_data_ptr");
|
||||
return -1;
|
||||
}
|
||||
//SET DUID
|
||||
srv_data_ptr->clientDUID = dhcp_client->duid;
|
||||
|
||||
dhcp_address_get:
|
||||
|
||||
if (!prefix || dhcp_client->no_address_hint) {
|
||||
add_prefix = false;
|
||||
} else {
|
||||
add_prefix = prefix != NULL;
|
||||
}
|
||||
|
||||
payload_len = libdhcpv6_solication_message_length(srv_data_ptr->clientDUID.duid_length, add_prefix, 0);
|
||||
|
||||
|
||||
payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
|
||||
if (!payload_ptr) {
|
||||
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
|
||||
tr_error("OOM payload_ptr");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dhcp_client->global_address_cb = error_cb; //TODO Only supporting one instance globaly if we need more for different instances needs code.
|
||||
srv_data_ptr->GlobalAddress = true;
|
||||
// Build solicit
|
||||
solPacket.clientDUID = srv_data_ptr->clientDUID;
|
||||
solPacket.iaID = srv_data_ptr->IAID;
|
||||
solPacket.messageType = DHCPV6_SOLICATION_TYPE;
|
||||
solPacket.transActionId = libdhcpv6_txid_get();
|
||||
/*Non Temporal Address */
|
||||
|
||||
if (prefix && !dhcp_client->no_address_hint) {
|
||||
dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0};
|
||||
nonTemporalAddress.requestedAddress = prefix;
|
||||
libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &solPacket, &nonTemporalAddress, NULL);
|
||||
} else {
|
||||
libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &solPacket, NULL, NULL);
|
||||
}
|
||||
|
||||
// send solicit
|
||||
srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client->service_instance, 0, srv_data_ptr, dhcp_addr, payload_ptr, payload_len, dhcp_solicit_resp_cb);
|
||||
if (srv_data_ptr->transActionId == 0) {
|
||||
ns_dyn_mem_free(payload_ptr);
|
||||
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
|
||||
return -1;
|
||||
}
|
||||
srv_data_ptr->iaNonTemporalStructValid = false;
|
||||
if (dhcp_client->sol_timeout != 0) {
|
||||
// Default retry values are modified from specification update to message
|
||||
dhcp_service_set_retry_timers(srv_data_ptr->transActionId, dhcp_client->sol_timeout, dhcp_client->sol_max_rt, dhcp_client->sol_max_rc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_client_server_address_update(int8_t interface, uint8_t *prefix, uint8_t server_address[static 16])
|
||||
{
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
|
||||
if (!dhcp_client) {
|
||||
tr_debug("Interface not match");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dhcpv6_client_server_data_t *srv_data_ptr = NULL;
|
||||
|
||||
if (prefix) {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
|
||||
} else if (dhcp_client->one_instance_interface) {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client->libDhcp_instance);
|
||||
}
|
||||
if (!srv_data_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(srv_data_ptr->server_address, server_address, 16) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(srv_data_ptr->server_address, server_address, 16);
|
||||
if (srv_data_ptr->transActionId) {
|
||||
dhcp_service_update_server_address(srv_data_ptr->transActionId, server_address);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void dhcp_client_global_address_renew(int8_t interface)
|
||||
{
|
||||
(void)interface;
|
||||
return;
|
||||
}
|
||||
|
||||
void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uint8_t prefix[static 16])
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
dhcpv6_client_server_data_t *srv_data_ptr;
|
||||
dhcp_client_class_t *dhcp_client;
|
||||
(void) dhcp_addr;
|
||||
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface, prefix);
|
||||
cur = protocol_stack_interface_info_get_by_id(interface);
|
||||
dhcp_client = dhcpv6_client_entry_discover(interface);
|
||||
|
||||
if (cur == NULL || srv_data_ptr == NULL || !dhcp_client) {
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
|
||||
if (dhcp_client->one_instance_interface) {
|
||||
addr_deprecate(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
} else {
|
||||
addr_delete(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
}
|
||||
|
||||
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
|
||||
}
|
||||
|
||||
void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason)
|
||||
{
|
||||
|
||||
uint8_t *payload_ptr;
|
||||
uint32_t payload_len;
|
||||
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface->id);
|
||||
if (!dhcp_client) {
|
||||
return;
|
||||
}
|
||||
|
||||
dhcpv6_client_server_data_t *srv_data_ptr;
|
||||
if (addr) {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_prefix(interface->id, addr->address);
|
||||
} else {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client->libDhcp_instance);
|
||||
}
|
||||
|
||||
if (srv_data_ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
if (reason == ADDR_CALLBACK_INVALIDATED) {
|
||||
dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
|
||||
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
|
||||
tr_warn("Dhcp address lost");
|
||||
return;
|
||||
}
|
||||
|
||||
if (reason != ADDR_CALLBACK_TIMER) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (srv_data_ptr->transActionId) {
|
||||
//Do not trig new Renew process
|
||||
tr_warn("Do not trig new pending renew request");
|
||||
return;
|
||||
}
|
||||
|
||||
payload_len = libdhcpv6_address_request_message_len(srv_data_ptr->clientDUID.duid_length, srv_data_ptr->serverDUID.duid_length, 0, !dhcp_client->no_address_hint);
|
||||
payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
|
||||
if (payload_ptr == NULL) {
|
||||
if (addr) {
|
||||
addr->state_timer = 200; //Retry after 20 seconds
|
||||
}
|
||||
tr_error("Out of memory");
|
||||
return ;
|
||||
}
|
||||
dhcpv6_solication_base_packet_s packetReq = {
|
||||
.messageType = DHCPV6_RENEW_TYPE,
|
||||
.clientDUID = srv_data_ptr->clientDUID,
|
||||
.requestedOptionCnt = 0,
|
||||
.iaID = srv_data_ptr->IAID,
|
||||
.timerT0 = srv_data_ptr->T0,
|
||||
.timerT1 = srv_data_ptr->T1,
|
||||
.requestedOptionList = NULL,
|
||||
};
|
||||
|
||||
if (dhcp_client->renew_uses_solicit) {
|
||||
packetReq.messageType = DHCPV6_SOLICATION_TYPE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (dhcp_client->no_address_hint && dhcp_client->renew_uses_solicit) {
|
||||
packetReq.timerT0 = 0;
|
||||
packetReq.timerT1 = 0;
|
||||
libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &packetReq, NULL, &srv_data_ptr->serverDUID);
|
||||
} else {
|
||||
// Set Address information
|
||||
dhcpv6_ia_non_temporal_address_s nonTemporalAddress = {0};
|
||||
nonTemporalAddress.requestedAddress = srv_data_ptr->iaNontemporalAddress.addressPrefix;
|
||||
nonTemporalAddress.preferredLifeTime = srv_data_ptr->iaNontemporalAddress.preferredTime;
|
||||
nonTemporalAddress.validLifeTime = srv_data_ptr->iaNontemporalAddress.validLifetime;
|
||||
libdhcpv6_generic_nontemporal_address_message_write(payload_ptr, &packetReq, &nonTemporalAddress, &srv_data_ptr->serverDUID);
|
||||
}
|
||||
// send solicit
|
||||
uint8_t *server_address = dhcp_service_relay_global_addres_get(dhcp_client->relay_instance);
|
||||
if (!server_address) {
|
||||
server_address = srv_data_ptr->server_address;
|
||||
}
|
||||
|
||||
srv_data_ptr->transActionId = dhcp_service_send_req(dhcp_client->service_instance, 0, srv_data_ptr, server_address, payload_ptr, payload_len, dhcp_solicit_resp_cb);
|
||||
if (srv_data_ptr->transActionId == 0) {
|
||||
ns_dyn_mem_free(payload_ptr);
|
||||
if (addr) {
|
||||
addr->state_timer = 200; //Retry after 20 seconds
|
||||
}
|
||||
tr_error("DHCP renew send failed");
|
||||
}
|
||||
if (packetReq.messageType == DHCPV6_SOLICATION_TYPE && dhcp_client->sol_timeout != 0) {
|
||||
// Default retry values are modified from specification update to message
|
||||
dhcp_service_set_retry_timers(srv_data_ptr->transActionId, dhcp_client->sol_timeout, dhcp_client->sol_max_rt, dhcp_client->sol_max_rc);
|
||||
}
|
||||
tr_info("DHCP renew send OK");
|
||||
}
|
||||
|
||||
static bool dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_data_t *srv_data_ptr)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = NULL;
|
||||
if_address_entry_t *address_entry = NULL;
|
||||
uint32_t renewTimer;
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur) {
|
||||
return false;
|
||||
}
|
||||
renewTimer = libdhcpv6_renew_time_define(srv_data_ptr);
|
||||
|
||||
srv_data_ptr->iaNonTemporalStructValid = true;
|
||||
address_entry = addr_get_entry(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
if (address_entry == NULL) {
|
||||
// create new
|
||||
address_entry = addr_add(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix, 64, ADDR_SOURCE_DHCP, srv_data_ptr->iaNontemporalAddress.validLifetime, srv_data_ptr->iaNontemporalAddress.preferredTime, false);
|
||||
} else {
|
||||
addr_set_valid_lifetime(cur, address_entry, srv_data_ptr->iaNontemporalAddress.validLifetime);
|
||||
addr_set_preferred_lifetime(cur, address_entry, srv_data_ptr->iaNontemporalAddress.preferredTime);
|
||||
}
|
||||
|
||||
if (address_entry == NULL) {
|
||||
tr_error("Address add failed");
|
||||
srv_data_ptr->iaNonTemporalStructValid = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (renewTimer) {
|
||||
// translate seconds to 100ms ticks
|
||||
if (renewTimer < 0xffffffff / 10) {
|
||||
renewTimer *= 10;
|
||||
} else {
|
||||
renewTimer = 0xfffffffe;
|
||||
}
|
||||
}
|
||||
address_entry->state_timer = renewTimer;
|
||||
address_entry->cb = dhcpv6_renew;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user