mirror of https://github.com/ARMmbed/mbed-os.git
Merge commit '0b6ccc5816e44df9fe89c476514cb7043dfb483b'
* commit '0b6ccc5816e44df9fe89c476514cb7043dfb483b': Squashed 'features/nanostack/sal-stack-nanostack/' changes from 0824752..9b3e144pull/11889/head
commit
12d4497ab7
|
@ -264,6 +264,7 @@ typedef enum {
|
|||
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
|
||||
macDefaultKeySource = 0x7c, /*<Default key source*/
|
||||
//NON standard extension
|
||||
macDeviceDescriptionPanIDUpdate = 0xf7, /*<Thread pending link update case this will update device descrioton list pan-id to new one*/
|
||||
macTXPower = 0xf8, /*<TX output power*/
|
||||
macCCAThreshold = 0xf9, /*<CCA threshold*/
|
||||
macMultiCSMAParameters = 0xfa, /*<Multi CSMA parameters*/
|
||||
|
|
|
@ -70,7 +70,9 @@ typedef struct nwk_stats_t {
|
|||
/* ETX */
|
||||
uint16_t etx_1st_parent; /**< Primary parent ETX. */
|
||||
uint16_t etx_2nd_parent; /**< Secondary parent ETX. */
|
||||
|
||||
/* MAC */
|
||||
uint16_t adapt_layer_tx_queue_size; /**< Adaptation layer direct TX queue size. */
|
||||
uint16_t adapt_layer_tx_queue_peak; /**< Adaptation layer direct TX queue size peak. */
|
||||
} nwk_stats_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -79,6 +79,7 @@ extern "C" {
|
|||
#define NETWORK_SIZE_SMALL 0x01
|
||||
#define NETWORK_SIZE_MEDIUM 0x08
|
||||
#define NETWORK_SIZE_LARGE 0x10
|
||||
#define NETWORK_SIZE_CERTIFICATE 0xFF
|
||||
|
||||
|
||||
/** Temporary API change flag. this will be removed when new version of API is implemented on applications
|
||||
|
@ -246,9 +247,10 @@ int ws_management_fhss_timing_configure(
|
|||
* Change the default configuration for Wi-SUN FHSS operation.
|
||||
* if application defined is used the behaviour is undefined
|
||||
*
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param channel_function Unicast channel function.
|
||||
* \param fixed_channel Used channel when channel function is fixed channel. If 0xFFFF, randomly chosen channel is used.
|
||||
* \param fixed_channel Used channel when channel function is fixed channel.
|
||||
* \param dwell_interval Used dwell interval when channel function is TR51 or DH1.
|
||||
*
|
||||
* \return 0, Init OK.
|
||||
|
@ -266,9 +268,10 @@ int ws_management_fhss_unicast_channel_function_configure(
|
|||
* Change the default configuration for Wi-SUN FHSS operation.
|
||||
* if application defined is used the behaviour is undefined
|
||||
*
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param channel_function Broadcast channel function.
|
||||
* \param fixed_channel Used channel when channel function is fixed channel. If 0xFFFF, randomly chosen channel is used.
|
||||
* \param fixed_channel Used channel when channel function is fixed channel.
|
||||
* \param dwell_interval Broadcast channel dwell interval.
|
||||
* \param broadcast_interval Broadcast interval.
|
||||
*
|
||||
|
|
|
@ -837,26 +837,47 @@ int8_t mac_helper_link_frame_counter_read(int8_t interface_id, uint32_t *seq_ptr
|
|||
if (!cur || !cur->mac_api || !seq_ptr) {
|
||||
return -1;
|
||||
}
|
||||
mlme_get_t get_req;
|
||||
get_req.attr = macFrameCounter;
|
||||
get_req.attr_index = cur->mac_parameters->mac_default_key_attribute_id;
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
|
||||
*seq_ptr = cur->mac_parameters->security_frame_counter;
|
||||
|
||||
return 0;
|
||||
return mac_helper_key_link_frame_counter_read(interface_id, seq_ptr, cur->mac_parameters->mac_default_key_attribute_id);
|
||||
}
|
||||
|
||||
|
||||
int8_t mac_helper_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur || !cur->mac_api) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mac_helper_key_link_frame_counter_set(interface_id, seq_ptr, cur->mac_parameters->mac_default_key_attribute_id);
|
||||
}
|
||||
|
||||
int8_t mac_helper_key_link_frame_counter_read(int8_t interface_id, uint32_t *seq_ptr, uint8_t descriptor)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur || !cur->mac_api || !seq_ptr) {
|
||||
return -1;
|
||||
}
|
||||
mlme_get_t get_req;
|
||||
get_req.attr = macFrameCounter;
|
||||
get_req.attr_index = descriptor;
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
|
||||
*seq_ptr = cur->mac_parameters->security_frame_counter;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t mac_helper_key_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr, uint8_t descriptor)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
|
||||
if (!cur || !cur->mac_api) {
|
||||
return -1;
|
||||
}
|
||||
mlme_set_t set_req;
|
||||
set_req.attr = macFrameCounter;
|
||||
set_req.attr_index = cur->mac_parameters->mac_default_key_attribute_id;
|
||||
set_req.attr_index = descriptor;
|
||||
set_req.value_pointer = &seq_ptr;
|
||||
set_req.value_size = 4;
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
||||
|
@ -929,3 +950,20 @@ int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int8_t mac_helper_mac_device_description_pan_id_update(int8_t interface_id, uint16_t pan_id)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !cur->mac_api) {
|
||||
return -1;
|
||||
}
|
||||
mlme_set_t set_req;
|
||||
set_req.attr = macDeviceDescriptionPanIDUpdate;
|
||||
set_req.attr_index = 0;
|
||||
set_req.value_pointer = &pan_id;
|
||||
set_req.value_size = sizeof(pan_id);
|
||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -115,6 +115,10 @@ int8_t mac_helper_link_frame_counter_read(int8_t interface_id, uint32_t *seq_ptr
|
|||
|
||||
int8_t mac_helper_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr);
|
||||
|
||||
int8_t mac_helper_key_link_frame_counter_read(int8_t interface_id, uint32_t *seq_ptr, uint8_t descriptor);
|
||||
|
||||
int8_t mac_helper_key_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr, uint8_t descriptor);
|
||||
|
||||
void mac_helper_devicetable_remove(struct mac_api_s *mac_api, uint8_t attribute_index, uint8_t *mac64);
|
||||
|
||||
void mac_helper_device_description_write(struct protocol_interface_info_entry *cur, mlme_device_descriptor_t *device_desc, uint8_t *mac64, uint16_t mac16, uint32_t frame_counter, bool exempt);
|
||||
|
@ -122,4 +126,6 @@ void mac_helper_device_description_write(struct protocol_interface_info_entry *c
|
|||
void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_dec, struct protocol_interface_info_entry *cur, uint8_t attribute_index, uint8_t keyID, bool force_set);
|
||||
int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set);
|
||||
|
||||
int8_t mac_helper_mac_device_description_pan_id_update(int8_t interface_id, uint16_t pan_id);
|
||||
|
||||
#endif // MAC_HELPER_H
|
||||
|
|
|
@ -755,6 +755,8 @@ int thread_link_configuration_activate(protocol_interface_info_entry_t *cur, lin
|
|||
return -1;
|
||||
}
|
||||
|
||||
mac_helper_mac_device_description_pan_id_update(cur->id, linkConfiguration->panId);
|
||||
|
||||
thread_configuration_thread_activate(cur, linkConfiguration);
|
||||
thread_configuration_security_activate(cur, linkConfiguration);
|
||||
thread_configuration_6lowpan_activate(cur);
|
||||
|
@ -899,7 +901,7 @@ void thread_interface_init(protocol_interface_info_entry_t *cur)
|
|||
{
|
||||
thread_discovery_reset(cur->id);
|
||||
thread_routing_set_mesh_callbacks(cur);
|
||||
dhcp_client_init(cur->id);
|
||||
dhcp_client_init(cur->id, DHCPV6_DUID_HARDWARE_EUI64_TYPE);
|
||||
dhcp_client_configure(cur->id, false, false, false);
|
||||
thread_management_client_init(cur->id);
|
||||
thread_bootstrap_address_registration_init();
|
||||
|
@ -2886,7 +2888,7 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
|
|||
thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info);
|
||||
/* Do not allow multiple DHCP solicits from one prefix => delete previous */
|
||||
dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix);
|
||||
if (dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE, thread_dhcp_client_gua_error_cb) == 0) {
|
||||
if (dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, thread_dhcp_client_gua_error_cb) == 0) {
|
||||
tr_debug("GP Address Requested");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,7 @@ typedef struct {
|
|||
fragmenter_tx_entry_t active_unicast_tx_buf; //Current active direct unicast tx process
|
||||
fragmenter_tx_entry_t active_broadcast_tx_buf; //Current active direct broadcast tx process
|
||||
buffer_list_t directTxQueue; //Waiting free tx process
|
||||
uint16_t directTxQueue_size;
|
||||
uint16_t indirect_big_packet_threshold;
|
||||
uint16_t max_indirect_big_packets_total;
|
||||
uint16_t max_indirect_small_packets_per_child;
|
||||
|
@ -216,6 +217,8 @@ static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_p
|
|||
} else {
|
||||
ns_list_add_to_end(&interface_ptr->directTxQueue, buf);
|
||||
}
|
||||
interface_ptr->directTxQueue_size++;
|
||||
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
|
||||
}
|
||||
|
||||
static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr, protocol_interface_info_entry_t *cur)
|
||||
|
@ -231,6 +234,8 @@ static buffer_t *lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interfa
|
|||
} else if ((buf->link_specific.ieee802_15_4.requestAck && !interface_ptr->active_unicast_tx_buf.buf)
|
||||
|| (!buf->link_specific.ieee802_15_4.requestAck && !interface_ptr->active_broadcast_tx_buf.buf)) {
|
||||
ns_list_remove(&interface_ptr->directTxQueue, buf);
|
||||
interface_ptr->directTxQueue_size--;
|
||||
protocol_stats_update(STATS_AL_TX_QUEUE_SIZE, interface_ptr->directTxQueue_size);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
|
||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "DHCPv6_Server/DHCPv6_server_service.h"
|
||||
#include "DHCPv6_client/dhcpv6_client_api.h"
|
||||
|
||||
#include "ws_bbr_api.h"
|
||||
|
||||
|
@ -44,6 +45,8 @@
|
|||
|
||||
#define RPL_INSTANCE_ID 1
|
||||
|
||||
static uint8_t current_instance_id = RPL_INSTANCE_ID;
|
||||
|
||||
#ifdef HAVE_WS_BORDER_ROUTER
|
||||
|
||||
#define WS_ULA_LIFETIME 24*3600
|
||||
|
@ -59,7 +62,8 @@
|
|||
static int8_t backbone_interface_id = -1; // BBR backbone information
|
||||
static uint16_t configuration = 0;
|
||||
|
||||
static uint8_t static_dodag_prefix[8] = {0xfd, 0x00, 0x61, 0x72, 0x6d};
|
||||
static uint8_t static_dodag_prefix[8] = {0xfd, 0x00, 0x72, 0x83, 0x7e};
|
||||
static uint8_t static_dodag_id_prefix[8] = {0xfd, 0x00, 0x61, 0x72, 0x6d};
|
||||
static uint8_t current_dodag_id[16] = {0};
|
||||
static uint8_t current_local_prefix[8] = {0};
|
||||
static uint8_t current_global_prefix[8] = {0};
|
||||
|
@ -71,17 +75,17 @@ static rpl_dodag_conf_t rpl_conf = {
|
|||
.default_lifetime = 120,
|
||||
.lifetime_unit = 60,
|
||||
.objective_code_point = 1, // MRHOF algorithm used
|
||||
.authentication = 0,
|
||||
.authentication = false,
|
||||
.path_control_size = 7,
|
||||
.dag_max_rank_increase = 2048,
|
||||
.min_hop_rank_increase = 196,
|
||||
.dag_max_rank_increase = WS_RPL_MAX_HOP_RANK_INCREASE,
|
||||
.min_hop_rank_increase = WS_RPL_MIN_HOP_RANK_INCREASE,
|
||||
// DIO configuration
|
||||
.dio_interval_min = WS_RPL_DIO_IMIN,
|
||||
.dio_interval_doublings = WS_RPL_DIO_DOUBLING,
|
||||
.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY
|
||||
};
|
||||
|
||||
void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy)
|
||||
void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase)
|
||||
{
|
||||
if (imin == 0 || doubling == 0) {
|
||||
// use default values
|
||||
|
@ -89,15 +93,22 @@ void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy)
|
|||
doubling = WS_RPL_DIO_DOUBLING;
|
||||
redundancy = WS_RPL_DIO_REDUNDANCY;
|
||||
}
|
||||
|
||||
if (rpl_conf.dio_interval_min == imin &&
|
||||
rpl_conf.dio_interval_doublings == doubling &&
|
||||
rpl_conf.dio_redundancy_constant == redundancy) {
|
||||
rpl_conf.dio_redundancy_constant == redundancy &&
|
||||
rpl_conf.dag_max_rank_increase == dag_max_rank_increase &&
|
||||
rpl_conf.min_hop_rank_increase == min_hop_rank_increase) {
|
||||
// Same values no update needed
|
||||
return;
|
||||
}
|
||||
|
||||
rpl_conf.dio_interval_min = imin;
|
||||
rpl_conf.dio_interval_doublings = doubling;
|
||||
rpl_conf.dio_redundancy_constant = redundancy;
|
||||
rpl_conf.dag_max_rank_increase = dag_max_rank_increase;
|
||||
rpl_conf.min_hop_rank_increase = min_hop_rank_increase;
|
||||
|
||||
if (protocol_6lowpan_rpl_root_dodag) {
|
||||
rpl_control_update_dodag_config(protocol_6lowpan_rpl_root_dodag, &rpl_conf);
|
||||
rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
|
||||
|
@ -112,9 +123,10 @@ static void ws_bbr_rpl_root_start(uint8_t *dodag_id)
|
|||
if (protocol_6lowpan_rpl_root_dodag) {
|
||||
rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
|
||||
protocol_6lowpan_rpl_root_dodag = NULL;
|
||||
current_instance_id++;
|
||||
}
|
||||
|
||||
protocol_6lowpan_rpl_root_dodag = rpl_control_create_dodag_root(protocol_6lowpan_rpl_domain, RPL_INSTANCE_ID, dodag_id, &rpl_conf, rpl_conf.min_hop_rank_increase, RPL_GROUNDED | RPL_MODE_NON_STORING | RPL_DODAG_PREF(0));
|
||||
protocol_6lowpan_rpl_root_dodag = rpl_control_create_dodag_root(protocol_6lowpan_rpl_domain, current_instance_id, dodag_id, &rpl_conf, rpl_conf.min_hop_rank_increase, RPL_GROUNDED | RPL_MODE_NON_STORING | RPL_DODAG_PREF(0));
|
||||
if (!protocol_6lowpan_rpl_root_dodag) {
|
||||
tr_err("RPL dodag init failed");
|
||||
return;
|
||||
|
@ -129,6 +141,7 @@ static void ws_bbr_rpl_root_stop(void)
|
|||
if (protocol_6lowpan_rpl_root_dodag) {
|
||||
rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
|
||||
protocol_6lowpan_rpl_root_dodag = NULL;
|
||||
current_instance_id++;
|
||||
}
|
||||
memset(current_local_prefix, 0, 8);
|
||||
memset(current_global_prefix, 0, 8);
|
||||
|
@ -162,6 +175,24 @@ int ws_border_router_proxy_state_update(int8_t caller_interface_id, int8_t handl
|
|||
return 0;
|
||||
}
|
||||
|
||||
static if_address_entry_t *ws_bbr_slaac_generate(protocol_interface_info_entry_t *cur, uint8_t *ula_prefix)
|
||||
{
|
||||
if_address_entry_t *add_entry = icmpv6_slaac_address_add(cur, ula_prefix, 64, 0xffffffff, 0xffffffff, true, SLAAC_IID_FIXED);
|
||||
if (!add_entry) {
|
||||
tr_err("ula create failed");
|
||||
return NULL;
|
||||
}
|
||||
addr_policy_table_add_entry(ula_prefix, 64, 2, WS_NON_PREFFRED_LABEL);
|
||||
return add_entry;
|
||||
}
|
||||
|
||||
static void ws_bbr_slaac_remove(protocol_interface_info_entry_t *cur, uint8_t *ula_prefix)
|
||||
{
|
||||
icmpv6_slaac_prefix_update(cur, ula_prefix, 64, 0, 0);
|
||||
addr_policy_table_delete_entry(ula_prefix, 64);
|
||||
}
|
||||
|
||||
|
||||
static int ws_bbr_static_dodagid_create(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (memcmp(current_dodag_id, ADDR_UNSPECIFIED, 16) != 0) {
|
||||
|
@ -169,14 +200,13 @@ static int ws_bbr_static_dodagid_create(protocol_interface_info_entry_t *cur)
|
|||
return 0;
|
||||
}
|
||||
// This address is only used if no other address available.
|
||||
if_address_entry_t *add_entry = icmpv6_slaac_address_add(cur, static_dodag_prefix, 64, 0xffffffff, 0xffffffff, true, SLAAC_IID_FIXED);
|
||||
if_address_entry_t *add_entry = ws_bbr_slaac_generate(cur, static_dodag_id_prefix);
|
||||
if (!add_entry) {
|
||||
tr_err("dodagid create failed");
|
||||
return -1;
|
||||
}
|
||||
memcpy(current_dodag_id, add_entry->address, 16);
|
||||
tr_info("BBR generate DODAGID %s", trace_ipv6(current_dodag_id));
|
||||
addr_policy_table_add_entry(static_dodag_prefix, 64, 2, WS_NON_PREFFRED_LABEL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -211,7 +241,7 @@ static void ws_bbr_dodag_get(uint8_t *local_prefix_ptr, uint8_t *global_prefix_p
|
|||
memset(global_prefix_ptr, 0, 8);
|
||||
|
||||
// By default static dodagID prefix is used as local prefix
|
||||
memcpy(local_prefix_ptr, current_dodag_id, 8);
|
||||
memcpy(local_prefix_ptr, static_dodag_prefix, 8);
|
||||
ws_bbr_bb_static_prefix_get(local_prefix_ptr);
|
||||
|
||||
if (arm_net_address_get(backbone_interface_id, ADDR_IPV6_GP, global_address) != 0) {
|
||||
|
@ -285,8 +315,13 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8
|
|||
}
|
||||
static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_t *global_id)
|
||||
{
|
||||
tr_debug("DHCP server deactivate %s", trace_ipv6(global_id));
|
||||
uint8_t temp_address[16];
|
||||
memcpy(temp_address, global_id, 8);
|
||||
memset(temp_address + 8, 0, 8);
|
||||
tr_debug("DHCP server deactivate %s", trace_ipv6(temp_address));
|
||||
DHCPv6_server_service_delete(cur->id, global_id, false);
|
||||
//Delete Client
|
||||
dhcp_client_global_address_delete(cur->id, NULL, temp_address);
|
||||
|
||||
}
|
||||
|
||||
|
@ -342,9 +377,16 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
|
|||
// Start static ULA prefix and routing always
|
||||
if (memcmp(current_local_prefix, ADDR_UNSPECIFIED, 8) != 0) {
|
||||
// Remove Old ULA prefix
|
||||
ws_bbr_slaac_remove(cur, current_local_prefix);
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, current_local_prefix, 64, PIO_A, 0, 0, true);
|
||||
memset(current_local_prefix, 0, 8);
|
||||
}
|
||||
|
||||
if (memcmp(local_prefix, ADDR_UNSPECIFIED, 8) != 0) {
|
||||
if (!ws_bbr_slaac_generate(cur, local_prefix)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tr_info("RPL Local prefix activate %s", trace_ipv6_prefix(local_prefix, 64));
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, local_prefix, 64, PIO_A, WS_ULA_LIFETIME, WS_ULA_LIFETIME, false);
|
||||
memcpy(current_local_prefix, local_prefix, 8);
|
||||
|
@ -354,7 +396,7 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
|
|||
/*
|
||||
* Check if backup ULA prefix is needed
|
||||
*/
|
||||
if (memcmp(global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
|
||||
if ((configuration & BBR_ULA_C) == 0 && memcmp(global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
|
||||
//Global prefix not available count if backup ULA should be created
|
||||
global_prefix_unavailable_timer += BBR_CHECK_INTERVAL;
|
||||
tr_debug("Check for backup prefix %"PRIu32"", global_prefix_unavailable_timer);
|
||||
|
@ -479,13 +521,6 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds
|
|||
if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC) {
|
||||
ws_common_network_size_configure(cur, cur->ws_info->pan_information.pan_size);
|
||||
}
|
||||
// We update the RPL version in same time to allow nodes to reselect parent
|
||||
// As configuration is made so that devices cant move downward in dodag this allows it
|
||||
// Version number update is only done if DoDAG MAX Rank Increase parameter is 0
|
||||
if (rpl_conf.dag_max_rank_increase == 0 && cur->ws_info->pan_information.pan_version && cur->ws_info->pan_information.pan_version % RPL_VERSION_LIFETIME / cur->ws_info->pan_version_timer == 0) {
|
||||
// Third the rate of configuration version change at default 5 hours
|
||||
rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -510,7 +545,7 @@ uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur)
|
|||
prefix_ptr = current_local_prefix;
|
||||
}
|
||||
|
||||
rpl_control_get_instance_dao_target_count(cur->rpl_domain, RPL_INSTANCE_ID, NULL, prefix_ptr, &result);
|
||||
rpl_control_get_instance_dao_target_count(cur->rpl_domain, current_instance_id, NULL, prefix_ptr, &result);
|
||||
if (result > 0) {
|
||||
// remove the Border router from the PAN size
|
||||
result--;
|
||||
|
@ -581,6 +616,7 @@ void ws_bbr_stop(int8_t interface_id)
|
|||
|
||||
rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
|
||||
protocol_6lowpan_rpl_root_dodag = NULL;
|
||||
current_instance_id++;
|
||||
|
||||
#else
|
||||
(void)interface_id;
|
||||
|
@ -593,7 +629,7 @@ int ws_bbr_configure(int8_t interface_id, uint16_t options)
|
|||
(void)interface_id;
|
||||
if (protocol_6lowpan_rpl_root_dodag &&
|
||||
options != configuration) {
|
||||
//Configuration changed delete previus setup
|
||||
//Configuration changed delete previous setup
|
||||
ws_bbr_rpl_root_stop();
|
||||
}
|
||||
configuration = options;
|
||||
|
|
|
@ -27,7 +27,7 @@ void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds
|
|||
|
||||
uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur);
|
||||
|
||||
void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy);
|
||||
void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy, uint16_t dag_max_rank_increase, uint16_t min_hop_rank_increase);
|
||||
|
||||
bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur);
|
||||
|
||||
|
@ -36,7 +36,7 @@ bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur);
|
|||
|
||||
#define ws_bbr_seconds_timer( cur, seconds)
|
||||
#define ws_bbr_pan_size(cur) 0
|
||||
#define ws_bbr_rpl_config( imin, doubling, redundancy)
|
||||
#define ws_bbr_rpl_config( imin, doubling, redundancy, dag_max_rank_increase, min_hop_rank_increase)
|
||||
#define ws_bbr_ready_to_start(cur) true
|
||||
|
||||
#endif //HAVE_WS_BORDER_ROUTER
|
||||
|
|
|
@ -76,9 +76,9 @@
|
|||
|
||||
static void ws_bootstrap_event_handler(arm_event_s *event);
|
||||
static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state);
|
||||
//static bool ws_bootstrap_state_active(struct protocol_interface_info_entry *cur);
|
||||
//static bool ws_bootstrap_state_wait_rpl(struct protocol_interface_info_entry *cur);
|
||||
static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur);
|
||||
static bool ws_bootstrap_state_active(struct protocol_interface_info_entry *cur);
|
||||
static bool ws_bootstrap_state_wait_rpl(struct protocol_interface_info_entry *cur);
|
||||
static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t interface_id, arm_library_event_priority_e priority, void *event_data);
|
||||
|
||||
static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new);
|
||||
|
@ -90,15 +90,19 @@ static void ws_bootstrap_mac_security_enable(protocol_interface_info_entry_t *cu
|
|||
static void ws_bootstrap_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t operation, uint8_t index, uint8_t *key);
|
||||
static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint8_t slot);
|
||||
static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index);
|
||||
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter);
|
||||
static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter);
|
||||
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, bool success);
|
||||
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter, uint8_t slot);
|
||||
static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter, uint8_t slot);
|
||||
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64);
|
||||
static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur);
|
||||
static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor);
|
||||
static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr);
|
||||
static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data);
|
||||
static bool ws_rpl_dio_new_parent_accept(struct protocol_interface_info_entry *interface);
|
||||
|
||||
|
||||
static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur);
|
||||
static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create);
|
||||
|
||||
typedef enum {
|
||||
WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/
|
||||
WS_PARENT_HARD_SYNCH, /**< Synch FHSS with latest synch information*/
|
||||
|
@ -417,7 +421,7 @@ static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur)
|
|||
{
|
||||
fhss_api_t *fhss_api = ns_sw_mac_get_fhss_api(cur->mac_api);
|
||||
|
||||
if (!fhss_api) {
|
||||
if (!fhss_api || (fhss_api && cur->ws_info->fhss_owner)) {
|
||||
// When FHSS doesn't exist yet, create one
|
||||
fhss_ws_configuration_t fhss_configuration;
|
||||
memset(&fhss_configuration, 0, sizeof(fhss_ws_configuration_t));
|
||||
|
@ -434,12 +438,25 @@ static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur)
|
|||
fhss_configuration.fhss_bc_dwell_interval = cur->ws_info->fhss_bc_dwell_interval;
|
||||
fhss_configuration.fhss_broadcast_interval = cur->ws_info->fhss_bc_interval;
|
||||
|
||||
fhss_api = ns_fhss_ws_create(&fhss_configuration, cur->ws_info->fhss_timer_ptr);
|
||||
if (!fhss_api) {
|
||||
tr_error("fhss create failed");
|
||||
return -1;
|
||||
fhss_api = ns_fhss_ws_create(&fhss_configuration, cur->ws_info->fhss_timer_ptr);
|
||||
if (!fhss_api) {
|
||||
tr_error("fhss create failed");
|
||||
return -1;
|
||||
}
|
||||
ns_sw_mac_fhss_register(cur->mac_api, fhss_api);
|
||||
cur->ws_info->fhss_owner = true;
|
||||
} else {
|
||||
//Configuration set
|
||||
ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration);
|
||||
|
||||
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
||||
ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0);
|
||||
} else {
|
||||
//Clear OWN HOP
|
||||
ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0xff);
|
||||
}
|
||||
}
|
||||
ns_sw_mac_fhss_register(cur->mac_api, fhss_api);
|
||||
} else {
|
||||
// Read defaults from the configuration to help FHSS testing
|
||||
const fhss_ws_configuration_t *fhss_configuration = ns_fhss_ws_configuration_get(fhss_api);
|
||||
|
@ -453,6 +470,8 @@ static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur)
|
|||
cur->ws_info->fhss_bc_dwell_interval = fhss_configuration->fhss_bc_dwell_interval;
|
||||
cur->ws_info->fhss_bc_interval = fhss_configuration->fhss_broadcast_interval;
|
||||
cur->ws_info->fhss_uc_dwell_interval = fhss_configuration->fhss_uc_dwell_interval;
|
||||
cur->ws_info->fhss_bc_fixed_channel = fhss_configuration->broadcast_fixed_channel;
|
||||
cur->ws_info->fhss_uc_fixed_channel = fhss_configuration->unicast_fixed_channel;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -510,16 +529,15 @@ static int8_t ws_fhss_discovery_configure(protocol_interface_info_entry_t *cur)
|
|||
memcpy(&fhss_configuration, ns_fhss_ws_configuration_get(cur->ws_info->fhss_api), sizeof(fhss_ws_configuration_t));
|
||||
}
|
||||
|
||||
fhss_configuration.fhss_uc_dwell_interval = 0;
|
||||
fhss_configuration.ws_uc_channel_function = WS_FIXED_CHANNEL;
|
||||
fhss_configuration.ws_bc_channel_function = WS_FIXED_CHANNEL;
|
||||
fhss_configuration.fhss_bc_dwell_interval = 0;
|
||||
fhss_configuration.fhss_broadcast_interval = 0;
|
||||
uint8_t tmp_uc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_uc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels);
|
||||
uint8_t tmp_bc_fixed_channel = ws_randomize_fixed_channel(cur->ws_info->fhss_bc_fixed_channel, cur->ws_info->hopping_schdule.number_of_channels);
|
||||
fhss_configuration.unicast_fixed_channel = tmp_uc_fixed_channel;
|
||||
fhss_configuration.broadcast_fixed_channel = tmp_bc_fixed_channel;
|
||||
ns_fhss_ws_configuration_set(cur->ws_info->fhss_api, &fhss_configuration);
|
||||
ns_fhss_ws_set_hop_count(cur->ws_info->fhss_api, 0xff);
|
||||
ws_bootstrap_llc_hopping_update(cur, &fhss_configuration);
|
||||
|
||||
return 0;
|
||||
|
@ -591,7 +609,7 @@ void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur,
|
|||
return;
|
||||
}
|
||||
|
||||
if (memcmp(neighbor_info->neighbor->mac64, cur->ws_info->parent_info.addr, 8)) {
|
||||
if (ws_bootstrap_candidate_parent_get(cur, neighbor_info->neighbor->mac64, false) == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -755,13 +773,15 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
|
|||
/*Replace NS handler to disable multicast address queries */
|
||||
cur->if_ns_transmit = ws_bootstrap_nd_ns_transmit;
|
||||
|
||||
dhcp_client_init(cur->id);
|
||||
dhcp_client_init(cur->id, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE);
|
||||
dhcp_client_configure(cur->id, true, true, true); //RENEW uses SOLICIT, Interface will use 1 instance for address get, IAID address hint is not used.
|
||||
dhcp_client_solicit_timeout_set(cur->id, WS_DHCP_SOLICIT_TIMEOUT, WS_DHCP_SOLICIT_MAX_RT, WS_DHCP_SOLICIT_MAX_RC);
|
||||
|
||||
|
||||
ws_nud_table_reset(cur);
|
||||
|
||||
ws_bootstrap_candidate_table_reset(cur);
|
||||
|
||||
blacklist_params_set(
|
||||
WS_BLACKLIST_ENTRY_LIFETIME,
|
||||
WS_BLACKLIST_TIMER_MAX_TIMEOUT,
|
||||
|
@ -796,6 +816,7 @@ static int8_t ws_bootstrap_down(protocol_interface_info_entry_t *cur)
|
|||
ws_eapol_relay_delete(cur);
|
||||
ws_eapol_auth_relay_delete(cur);
|
||||
ws_pae_controller_stop(cur);
|
||||
ws_bootstrap_candidate_table_reset(cur);
|
||||
blacklist_clear();
|
||||
|
||||
return nwk_6lowpan_down(cur);
|
||||
|
@ -859,7 +880,7 @@ static bool ws_bootstrap_network_name_matches(const struct mcps_data_ie_list *ie
|
|||
|
||||
static void ws_bootstrap_pan_advertisement_analyse_active(struct protocol_interface_info_entry *cur, ws_pan_information_t *pan_information)
|
||||
{
|
||||
/* TODO In Active state
|
||||
/* In Active state
|
||||
*
|
||||
* A consistent transmission is defined as a PAN Advertisement received by a node with PAN ID and
|
||||
* NETNAME-IE / Network Name matching that of the receiving node, and with a PAN-IE / Routing Cost
|
||||
|
@ -874,18 +895,207 @@ static void ws_bootstrap_pan_advertisement_analyse_active(struct protocol_interf
|
|||
*
|
||||
*/
|
||||
|
||||
if (pan_information->routing_cost >= cur->ws_info->pan_information.routing_cost) {
|
||||
#ifdef WISUN_1_0_ERRATA_FIX
|
||||
// All messages are considered as consistent only Solicit will cause inconsistent
|
||||
trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement);
|
||||
#else
|
||||
// Wi-SUN 1.0 specified functionality, causes extra inconsistencies when we hear higher rank advertisements
|
||||
if (pan_information->routing_cost >= ws_bootstrap_routing_cost_calculate(cur)) {
|
||||
trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement);
|
||||
} else {
|
||||
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement, &cur->ws_info->trickle_params_pan_discovery);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// automatic network size adjustment
|
||||
if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC &&
|
||||
cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER &&
|
||||
cur->ws_info->pan_information.pan_size != pan_information->pan_size) {
|
||||
ws_common_network_size_configure(cur, pan_information->pan_size);
|
||||
static parent_info_t *ws_bootstrap_candidate_parent_get_best(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) {
|
||||
tr_info("candidate list a:%s panid:%x cost:%d size:%d rssi:%d age:%"PRIu32, trace_array(entry->addr, 8), entry->pan_id, entry->pan_information.routing_cost, entry->pan_information.pan_size, entry->signal_dbm, protocol_core_monotonic_time - entry->age);
|
||||
}
|
||||
|
||||
return ns_list_get_first(&cur->ws_info->parent_list_reserved);
|
||||
}
|
||||
|
||||
static void ws_bootstrap_candidate_parent_store(parent_info_t *parent, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us, ws_pan_information_t *pan_information)
|
||||
{
|
||||
parent->ws_utt = *ws_utt;
|
||||
// Saved from unicast IE
|
||||
parent->ws_us = *ws_us;
|
||||
|
||||
// Saved from Pan information, do not overwrite pan_version as it is not valid here
|
||||
parent->pan_information.pan_size = pan_information->pan_size;
|
||||
parent->pan_information.routing_cost = pan_information->routing_cost;
|
||||
parent->pan_information.use_parent_bs = pan_information->use_parent_bs;
|
||||
parent->pan_information.rpl_routing_method = pan_information->rpl_routing_method;
|
||||
parent->pan_information.version = pan_information->version;
|
||||
|
||||
// Saved from message
|
||||
parent->timestamp = data->timestamp;
|
||||
parent->pan_id = data->SrcPANId;
|
||||
parent->link_quality = data->mpduLinkQuality;
|
||||
parent->signal_dbm = data->signal_dbm;
|
||||
memcpy(parent->addr, data->SrcAddr, 8);
|
||||
|
||||
parent->age = protocol_core_monotonic_time;
|
||||
}
|
||||
|
||||
static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
//Empty active list
|
||||
ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_free) {
|
||||
ns_list_remove(&cur->ws_info->parent_list_free, entry);
|
||||
}
|
||||
|
||||
//Empty free list
|
||||
ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) {
|
||||
ns_list_remove(&cur->ws_info->parent_list_reserved, entry);
|
||||
}
|
||||
//Add to free list to full
|
||||
for (int i = 0; i < WS_PARENT_LIST_SIZE; i++) {
|
||||
ns_list_add_to_end(&cur->ws_info->parent_list_free, &cur->ws_info->parent_info[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static parent_info_t *ws_bootstrap_candidate_parent_allocate(protocol_interface_info_entry_t *cur, const uint8_t *addr)
|
||||
{
|
||||
parent_info_t *entry = ns_list_get_first(&cur->ws_info->parent_list_free);
|
||||
if (entry) {
|
||||
memcpy(entry->addr, addr, 8);
|
||||
ns_list_remove(&cur->ws_info->parent_list_free, entry);
|
||||
ns_list_add_to_end(&cur->ws_info->parent_list_reserved, entry);
|
||||
} else {
|
||||
// If there is no free entries always allocate the last one of reserved as it is the worst
|
||||
entry = ns_list_get_last(&cur->ws_info->parent_list_reserved);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
static void ws_bootstrap_candidate_parent_free(protocol_interface_info_entry_t *cur, uint8_t *addr)
|
||||
{
|
||||
ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) {
|
||||
if (memcmp(entry->addr, addr, 8) == 0) {
|
||||
ns_list_remove(&cur->ws_info->parent_list_reserved, entry);
|
||||
ns_list_add_to_end(&cur->ws_info->parent_list_free, entry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create)
|
||||
{
|
||||
ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) {
|
||||
if (memcmp(entry->addr, addr, 8) == 0) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
if (create) {
|
||||
return ws_bootstrap_candidate_parent_allocate(cur, addr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool ws_bootstrap_candidate_parent_compare(parent_info_t *p1, parent_info_t *p2)
|
||||
{
|
||||
// Return true if P2 is better
|
||||
// signal lower than threshold for both
|
||||
// pan_cost
|
||||
// signal quality
|
||||
|
||||
if (ws_neighbor_class_rsl_from_dbm_calculate(p1->signal_dbm) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) &&
|
||||
ws_neighbor_class_rsl_from_dbm_calculate(p2->signal_dbm) > (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) {
|
||||
// above threshold is always better than not.
|
||||
return true;
|
||||
}
|
||||
if (ws_neighbor_class_rsl_from_dbm_calculate(p2->signal_dbm) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) &&
|
||||
ws_neighbor_class_rsl_from_dbm_calculate(p1->signal_dbm) > (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) {
|
||||
// P2 is less than threshold and P1 is larger so P1 is always better.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Select the lowest PAN cost
|
||||
uint16_t p1_pan_cost = (p1->pan_information.routing_cost / PRC_WEIGHT_FACTOR) + (p1->pan_information.pan_size / PS_WEIGHT_FACTOR);
|
||||
uint16_t p2_pan_cost = (p2->pan_information.routing_cost / PRC_WEIGHT_FACTOR) + (p2->pan_information.pan_size / PS_WEIGHT_FACTOR);
|
||||
if (p1_pan_cost > p2_pan_cost) {
|
||||
return true;
|
||||
} else if (p1_pan_cost < p2_pan_cost) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If pan cost is the same then we select the one we hear highest
|
||||
if (p1->signal_dbm < p2->signal_dbm) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ws_bootstrap_candidate_list_clean(struct protocol_interface_info_entry *cur, uint8_t pan_max, uint32_t current_time, uint16_t pan_id)
|
||||
{
|
||||
int pan_count = 0;
|
||||
|
||||
ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) {
|
||||
if ((current_time - entry->age) > WS_PARENT_LIST_MAX_AGE) {
|
||||
ns_list_remove(&cur->ws_info->parent_list_reserved, entry);
|
||||
ns_list_add_to_end(&cur->ws_info->parent_list_free, entry);
|
||||
continue;
|
||||
}
|
||||
if (entry->pan_id == pan_id) {
|
||||
// Same panid if there is more than limited amount free those
|
||||
pan_count++;
|
||||
if (pan_count > pan_max) {
|
||||
ns_list_remove(&cur->ws_info->parent_list_reserved, entry);
|
||||
ns_list_add_to_end(&cur->ws_info->parent_list_free, entry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_bootstrap_candidate_parent_sort(struct protocol_interface_info_entry *cur, parent_info_t *new_entry)
|
||||
{
|
||||
ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) {
|
||||
if (entry == new_entry) {
|
||||
// own entry skip it
|
||||
continue;
|
||||
}
|
||||
if (ws_bootstrap_candidate_parent_compare(entry, new_entry)) {
|
||||
// New entry is better
|
||||
//tr_debug("candidate list new is better");
|
||||
ns_list_remove(&cur->ws_info->parent_list_reserved, new_entry);
|
||||
ns_list_add_before(&cur->ws_info->parent_list_reserved, entry, new_entry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_bootstrap_pan_information_store(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us, ws_pan_information_t *pan_information)
|
||||
{
|
||||
|
||||
parent_info_t *new_entry;
|
||||
/* Have List of 20 heard neighbours
|
||||
* Order those as best based on pan cost
|
||||
* In single pan order based on signal quality
|
||||
* in single PAN limit the amount of devices to 5
|
||||
* If there is no advertisement heard for last hour Clear the neigbour.
|
||||
*/
|
||||
|
||||
// Discovery state processing
|
||||
//tr_info("neighbour: addr:%s panid:%x signal:%d", trace_array(data->SrcAddr, 8), data->SrcPANId, data->signal_dbm);
|
||||
|
||||
// Clean old entries
|
||||
ws_bootstrap_candidate_list_clean(cur, WS_PARENT_LIST_MAX_PAN_IN_DISCOVERY, protocol_core_monotonic_time, data->SrcPANId);
|
||||
|
||||
new_entry = ws_bootstrap_candidate_parent_get(cur, data->SrcAddr, true);
|
||||
if (!new_entry) {
|
||||
tr_warn("neighbour creation fail");
|
||||
return;
|
||||
}
|
||||
// Safe the information
|
||||
ws_bootstrap_candidate_parent_store(new_entry, data, ws_utt, ws_us, pan_information);
|
||||
// set to the correct place in list
|
||||
ws_bootstrap_candidate_parent_sort(cur, new_entry);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, ws_utt_ie_t *ws_utt, ws_us_ie_t *ws_us)
|
||||
|
@ -899,99 +1109,39 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf
|
|||
return;
|
||||
}
|
||||
|
||||
// if in active scan state
|
||||
if (!ws_bootstrap_state_discovery(cur)) {
|
||||
if (data->SrcPANId != cur->ws_info->network_pan_id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check pan flags so that it is valid
|
||||
if (!pan_information.rpl_routing_method) {
|
||||
// NOT RPL routing
|
||||
tr_warn("Not supported routing");
|
||||
//tr_warn("Not supported routing");
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO smart neighbour process
|
||||
*
|
||||
* Unsecure packet we cant trust the device?
|
||||
*
|
||||
* This message is received from tens of devices and we must select the best parent
|
||||
*
|
||||
* We save the best parent and create entry when we have selected the EAPOL target
|
||||
*
|
||||
*/
|
||||
// Store heard pans and possible candidate parents
|
||||
ws_bootstrap_pan_information_store(cur, data, ws_utt, ws_us, &pan_information);
|
||||
|
||||
// Save route cost for all neighbours
|
||||
if (!(ws_bootstrap_state_active(cur) ||
|
||||
ws_bootstrap_state_wait_rpl(cur))) {
|
||||
// During discovery/eapol/config learn we dont do further processing for advertisements
|
||||
return;
|
||||
}
|
||||
// Active state processing
|
||||
//tr_debug("Advertisement active");
|
||||
|
||||
// In active operation less neighbours per pan is allowed
|
||||
ws_bootstrap_candidate_list_clean(cur, WS_PARENT_LIST_MAX_PAN_IN_ACTIVE, protocol_core_monotonic_time, data->SrcPANId);
|
||||
|
||||
// Check if valid PAN
|
||||
if (data->SrcPANId != cur->ws_info->network_pan_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save route cost for all known neighbors
|
||||
llc_neighbour_req_t neighbor_info;
|
||||
neighbor_info.neighbor = NULL;
|
||||
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
|
||||
neighbor_info.ws_neighbor->routing_cost = pan_information.routing_cost;
|
||||
}
|
||||
|
||||
// Save the best network parent
|
||||
|
||||
if (ws_bootstrap_state_discovery(cur)) {
|
||||
// Discovery state processing
|
||||
tr_info("potential parent addr:%s panid:%x signal:%d", trace_array(data->SrcAddr, 8), data->SrcPANId, data->signal_dbm);
|
||||
|
||||
// This parent is selected and used for authentication.
|
||||
if (memcmp(cur->ws_info->parent_info.addr, ADDR_UNSPECIFIED, 8) != 0) {
|
||||
|
||||
// if we dont have higher than threshold signal only signal level decides parent
|
||||
if (ws_neighbor_class_rsl_from_dbm_calculate(cur->ws_info->parent_info.signal_dbm) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) &&
|
||||
ws_neighbor_class_rsl_from_dbm_calculate(data->signal_dbm) > ws_neighbor_class_rsl_from_dbm_calculate(cur->ws_info->parent_info.signal_dbm)) {
|
||||
// automatically select the best quality link from the below threshold
|
||||
goto parent_selected;
|
||||
}
|
||||
// Drop if signal quality is not good enough
|
||||
if (ws_neighbor_class_rsl_from_dbm_calculate(data->signal_dbm) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) {
|
||||
tr_info("EAPOL target dropped Link quality too low");
|
||||
return;
|
||||
}
|
||||
|
||||
// Select the lowest PAN cost
|
||||
uint16_t pan_cost = (pan_information.routing_cost / PRC_WEIGHT_FACTOR) + (pan_information.pan_size / PS_WEIGHT_FACTOR);
|
||||
uint16_t current_pan_cost = (cur->ws_info->parent_info.pan_information.routing_cost / PRC_WEIGHT_FACTOR) + (cur->ws_info->parent_info.pan_information.pan_size / PS_WEIGHT_FACTOR);
|
||||
if (current_pan_cost < pan_cost) {
|
||||
tr_info("EAPOL target dropped Higher Pan cost %u > %u current", pan_cost, current_pan_cost);
|
||||
return;
|
||||
}
|
||||
|
||||
// If pan cost is the same then we select the one we hear highest
|
||||
if (current_pan_cost == pan_cost &&
|
||||
cur->ws_info->parent_info.signal_dbm > data->signal_dbm) {
|
||||
tr_info("EAPOL target dropped Lower link quality %d < %d current", data->signal_dbm, cur->ws_info->parent_info.signal_dbm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
parent_selected:
|
||||
// Parent valid store information
|
||||
cur->ws_info->parent_info.ws_utt = *ws_utt;
|
||||
// Saved from unicast IE
|
||||
cur->ws_info->parent_info.ws_us = *ws_us;
|
||||
|
||||
// Saved from Pan information, do not overwrite pan_version as it is not valid here
|
||||
cur->ws_info->parent_info.pan_information.pan_size = pan_information.pan_size;
|
||||
cur->ws_info->parent_info.pan_information.routing_cost = pan_information.routing_cost;
|
||||
cur->ws_info->parent_info.pan_information.use_parent_bs = pan_information.use_parent_bs;
|
||||
cur->ws_info->parent_info.pan_information.rpl_routing_method = pan_information.rpl_routing_method;
|
||||
cur->ws_info->parent_info.pan_information.version = pan_information.version;
|
||||
|
||||
// Saved from message
|
||||
cur->ws_info->parent_info.timestamp = data->timestamp;
|
||||
cur->ws_info->parent_info.pan_id = data->SrcPANId;
|
||||
cur->ws_info->parent_info.link_quality = data->mpduLinkQuality;
|
||||
cur->ws_info->parent_info.signal_dbm = data->signal_dbm;
|
||||
memcpy(cur->ws_info->parent_info.addr, data->SrcAddr, 8);
|
||||
|
||||
tr_info("New parent addr:%s panid:%x signal:%d", trace_array(cur->ws_info->parent_info.addr, 8), cur->ws_info->parent_info.pan_id, cur->ws_info->parent_info.signal_dbm);
|
||||
return;
|
||||
}
|
||||
// Active state processing
|
||||
ws_bootstrap_pan_advertisement_analyse_active(cur, &pan_information);
|
||||
|
||||
// Learn latest network information
|
||||
|
@ -1000,13 +1150,18 @@ parent_selected:
|
|||
ws_bootsrap_create_ll_address(ll_address, neighbor_info.neighbor->mac64);
|
||||
|
||||
if (rpl_control_is_dodag_parent(cur, ll_address)) {
|
||||
// automatic network size adjustment learned
|
||||
if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC &&
|
||||
cur->ws_info->pan_information.pan_size != pan_information.pan_size) {
|
||||
ws_common_network_size_configure(cur, pan_information.pan_size);
|
||||
}
|
||||
|
||||
cur->ws_info->pan_information.pan_size = pan_information.pan_size;
|
||||
cur->ws_info->pan_information.routing_cost = pan_information.routing_cost;
|
||||
cur->ws_info->pan_information.rpl_routing_method = pan_information.rpl_routing_method;
|
||||
cur->ws_info->pan_information.use_parent_bs = pan_information.use_parent_bs;
|
||||
cur->ws_info->pan_information.version = pan_information.version;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1026,6 +1181,16 @@ static void ws_bootstrap_pan_advertisement_solicit_analyse(struct protocol_inter
|
|||
* a PAN Advertisement Solicit with NETNAME-IE / Network Name matching that configured on the receiving node.
|
||||
*/
|
||||
trickle_consistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit);
|
||||
|
||||
/*
|
||||
* Optimized PAN discovery to select faster the parent if we hear solicit from someone else
|
||||
*/
|
||||
|
||||
if (ws_bootstrap_state_discovery(cur) &&
|
||||
cur->bootsrap_state_machine_cnt > cur->ws_info->trickle_params_pan_discovery.Imin + 50) {
|
||||
cur->bootsrap_state_machine_cnt = cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50;
|
||||
tr_info("Making parent selection in %d s", (uint32_t)(cur->bootsrap_state_machine_cnt / 10));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1192,18 +1357,6 @@ static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_in
|
|||
*/
|
||||
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery);
|
||||
}
|
||||
static bool ws_bootstrap_network_found(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
tr_debug("analyze network discovery result");
|
||||
|
||||
// This parent is used for authentication to the network
|
||||
if (memcmp(cur->ws_info->parent_info.addr, ADDR_UNSPECIFIED, 8) == 0) {
|
||||
// No parent found yet
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ws_channel_plan_zero_compare(ws_channel_plan_zero_t *rx_plan, ws_hopping_schedule_t *hopping_schdule)
|
||||
{
|
||||
if (rx_plan->operation_class != hopping_schdule->operating_class) {
|
||||
|
@ -1286,7 +1439,7 @@ static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, c
|
|||
switch (message_type) {
|
||||
case WS_FT_PAN_ADVERT:
|
||||
// Analyse Advertisement
|
||||
tr_info("received ADVERT Src:%s rssi:%d", trace_array(data->SrcAddr, 8), data->signal_dbm);
|
||||
tr_info("received ADVERT Src:%s panid:%x rssi:%d", trace_array(data->SrcAddr, 8), data->SrcPANId, data->signal_dbm);
|
||||
ws_bootstrap_pan_advertisement_analyse(cur, data, ie_ext, &ws_utt, &ws_us);
|
||||
break;
|
||||
case WS_FT_PAN_ADVERT_SOL:
|
||||
|
@ -1370,8 +1523,13 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent
|
|||
|
||||
//Read current timestamp
|
||||
uint32_t time_from_last_unicast_shedule = ws_time_from_last_unicast_traffic(current_time_stamp, ws_neighbor);
|
||||
|
||||
if (time_from_last_unicast_shedule > WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT) {
|
||||
uint32_t min_timeout;
|
||||
if (interface->ws_info->network_size_config == NETWORK_SIZE_LARGE) {
|
||||
min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE;
|
||||
} else {
|
||||
min_timeout = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL;
|
||||
}
|
||||
if (time_from_last_unicast_shedule > min_timeout) {
|
||||
//Accept only Enough Old Device
|
||||
if (!neighbor_entry_ptr) {
|
||||
//Accept first compare
|
||||
|
@ -1436,13 +1594,13 @@ static bool ws_rpl_dio_new_parent_accept(struct protocol_interface_info_entry *i
|
|||
uint16_t parent_candidate_size = rpl_control_parent_candidate_list_size(interface, false);
|
||||
//TODO check bootstarap state for review
|
||||
//if we have enough candidates at list do not accept new multicast neighbours
|
||||
if (parent_candidate_size > WS_NEIGHBOUR_MAX_CANDIDATE_PROBE) {
|
||||
if (parent_candidate_size > interface->ws_info->rpl_parent_candidate_max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
parent_candidate_size = rpl_control_parent_candidate_list_size(interface, true);
|
||||
//If we have already enough parent selected Candidates count is bigger tahn 4
|
||||
if (parent_candidate_size >= 2) {
|
||||
//If we have already enough parent selected Candidates count is bigger than configured
|
||||
if (parent_candidate_size >= interface->ws_info->rpl_selected_parent_max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1771,7 +1929,6 @@ int ws_bootstrap_neighbor_remove(protocol_interface_info_entry_t *cur, const uin
|
|||
|
||||
int ws_bootstrap_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
|
||||
{
|
||||
blacklist_update(ll_address, false);
|
||||
rpl_control_neighbor_delete(cur, ll_address);
|
||||
ws_bootstrap_neighbor_remove(cur, ll_address);
|
||||
return 0;
|
||||
|
@ -1811,23 +1968,6 @@ static void ws_bootstrap_fhss_activate(protocol_interface_info_entry_t *cur)
|
|||
return;
|
||||
}
|
||||
|
||||
static void ws_bootstrap_network_information_learn(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
tr_debug("learn network information from parent");
|
||||
|
||||
// Start following network broadcast timing schedules
|
||||
|
||||
// Regulatory domain saving? cant change?
|
||||
|
||||
// Save network information
|
||||
cur->ws_info->network_pan_id = cur->ws_info->parent_info.pan_id;
|
||||
cur->ws_info->pan_information = cur->ws_info->parent_info.pan_information;
|
||||
cur->ws_info->pan_information.pan_version = 0; // This is learned from actual configuration
|
||||
|
||||
// TODO create parent neighbour table entry for unicast schedule to enable authentication
|
||||
|
||||
return;
|
||||
}
|
||||
static void ws_bootstrap_network_configuration_learn(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
tr_debug("Start using PAN configuration");
|
||||
|
@ -1926,7 +2066,7 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle)
|
|||
*
|
||||
*/
|
||||
|
||||
} else if (event == RPL_EVENT_DAO_PARENT_SWITCH) {
|
||||
} else if (event == RPL_EVENT_DAO_PARENT_ADD) {
|
||||
ws_address_registration_update(cur);
|
||||
}
|
||||
cur->ws_info->rpl_state = event;
|
||||
|
@ -1953,7 +2093,7 @@ static void ws_dhcp_client_global_adress_cb(int8_t interface, uint8_t dhcp_addr[
|
|||
|
||||
void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_t *prefix, uint8_t *parent_link_local)
|
||||
{
|
||||
if (dhcp_client_get_global_address(cur->id, parent_link_local, prefix, cur->mac, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE, ws_dhcp_client_global_adress_cb) != 0) {
|
||||
if (dhcp_client_get_global_address(cur->id, parent_link_local, prefix, ws_dhcp_client_global_adress_cb) != 0) {
|
||||
tr_error("DHCPp client request fail");
|
||||
}
|
||||
}
|
||||
|
@ -2106,16 +2246,19 @@ static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *
|
|||
static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
tr_debug("router discovery start");
|
||||
// Remove network keys from MAC
|
||||
ws_pae_controller_nw_keys_remove(cur);
|
||||
ws_bootstrap_state_change(cur, ER_ACTIVE_SCAN);
|
||||
cur->nwk_nd_re_scan_count = 0;
|
||||
cur->ws_info->configuration_learned = false;
|
||||
cur->ws_info->pan_version_timeout_timer = 0;
|
||||
// Clear parent info
|
||||
memset(cur->ws_info->parent_info.addr, 0, 8);
|
||||
|
||||
// Clear learned neighbours
|
||||
ws_bootstrap_neighbor_list_clean(cur);
|
||||
|
||||
// Clear learned candidate parents
|
||||
ws_bootstrap_candidate_table_reset(cur);
|
||||
|
||||
// Clear RPL information
|
||||
rpl_control_free_domain_instances_from_interface(cur);
|
||||
// Clear EAPOL relay address
|
||||
|
@ -2151,6 +2294,7 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
|
|||
cur->ws_info->trickle_pan_advertisement_solicit.I, cur->ws_info->trickle_pan_advertisement_solicit.t, cur->ws_info->trickle_pan_advertisement_solicit.now, cur->ws_info->trickle_pan_advertisement_solicit.c);
|
||||
|
||||
cur->bootsrap_state_machine_cnt = time_to_solicit + cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50;
|
||||
tr_info("Making parent selection in %d s", (uint32_t)(cur->bootsrap_state_machine_cnt / 10));
|
||||
}
|
||||
|
||||
// Start authentication
|
||||
|
@ -2184,23 +2328,34 @@ static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur,
|
|||
mac_helper_security_auto_request_key_index_set(cur, index, index + 1);
|
||||
}
|
||||
|
||||
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter)
|
||||
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter, uint8_t slot)
|
||||
{
|
||||
// Set frame counter
|
||||
mac_helper_link_frame_counter_set(cur->id, counter);
|
||||
mac_helper_key_link_frame_counter_set(cur->id, counter, slot);
|
||||
}
|
||||
|
||||
static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter)
|
||||
static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter, uint8_t slot)
|
||||
{
|
||||
// Read frame counter
|
||||
mac_helper_link_frame_counter_read(cur->id, counter);
|
||||
mac_helper_key_link_frame_counter_read(cur->id, counter, slot);
|
||||
}
|
||||
|
||||
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, bool success)
|
||||
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64)
|
||||
{
|
||||
if (success) {
|
||||
(void) target_eui_64;
|
||||
|
||||
if (result == AUTH_RESULT_OK) {
|
||||
tr_debug("authentication success");
|
||||
ws_bootstrap_event_configuration_start(cur);
|
||||
} else if (result == AUTH_RESULT_ERR_TX_NO_ACK) {
|
||||
// eapol parent selected is not working
|
||||
tr_debug("authentication TX failed");
|
||||
|
||||
ws_bootstrap_candidate_parent_free(cur, target_eui_64);
|
||||
// Go back for network scanning
|
||||
ws_bootstrap_state_change(cur, ER_ACTIVE_SCAN);
|
||||
cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(10, cur->ws_info->trickle_params_pan_discovery.Imin >> 1);
|
||||
tr_info("Making parent selection in %d s", (uint32_t)(cur->bootsrap_state_machine_cnt / 10));
|
||||
} else {
|
||||
tr_debug("authentication failed");
|
||||
// What else to do to start over again...
|
||||
|
@ -2217,9 +2372,6 @@ static void ws_bootstrap_start_configuration_learn(protocol_interface_info_entry
|
|||
ws_bootstrap_state_change(cur, ER_SCAN);
|
||||
|
||||
cur->ws_info->configuration_learned = false;
|
||||
// Clear parent info
|
||||
|
||||
memset(cur->ws_info->parent_info.addr, 0, 8);
|
||||
|
||||
// Clear all temporary information
|
||||
ws_bootstrap_ip_stack_reset(cur);
|
||||
|
@ -2268,6 +2420,19 @@ void ws_bootstrap_configuration_trickle_reset(protocol_interface_info_entry_t *c
|
|||
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_config, &cur->ws_info->trickle_params_pan_discovery);
|
||||
}
|
||||
|
||||
static void ws_set_asynch_channel_list(protocol_interface_info_entry_t *cur, asynch_request_t *async_req)
|
||||
{
|
||||
memset(&async_req->channel_list, 0, sizeof(channel_list_s));
|
||||
if (cur->ws_info->fhss_uc_channel_function == WS_FIXED_CHANNEL) {
|
||||
//SET 1 Channel only
|
||||
uint16_t channel_number = cur->ws_info->fhss_uc_fixed_channel;
|
||||
async_req->channel_list.channel_mask[0 + (channel_number / 32)] = (1 << (channel_number % 32));
|
||||
} else {
|
||||
ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain);
|
||||
}
|
||||
|
||||
async_req->channel_list.channel_page = CHANNEL_PAGE_10;
|
||||
}
|
||||
|
||||
static void ws_bootstrap_pan_advert_solicit(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
@ -2279,9 +2444,9 @@ static void ws_bootstrap_pan_advert_solicit(protocol_interface_info_entry_t *cur
|
|||
async_req.wp_requested_nested_ie_list.us_ie = true;
|
||||
async_req.wp_requested_nested_ie_list.net_name_ie = true;
|
||||
|
||||
ws_generate_channel_list(async_req.channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain);
|
||||
ws_set_asynch_channel_list(cur, &async_req);
|
||||
|
||||
|
||||
async_req.channel_list.channel_page = CHANNEL_PAGE_10;
|
||||
async_req.security.SecurityLevel = 0;
|
||||
|
||||
ws_llc_asynch_request(cur, &async_req);
|
||||
|
@ -2297,9 +2462,7 @@ static void ws_bootstrap_pan_config_solicit(protocol_interface_info_entry_t *cur
|
|||
async_req.wp_requested_nested_ie_list.us_ie = true;
|
||||
async_req.wp_requested_nested_ie_list.net_name_ie = true;
|
||||
|
||||
ws_generate_channel_list(async_req.channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain);
|
||||
|
||||
async_req.channel_list.channel_page = CHANNEL_PAGE_10;
|
||||
ws_set_asynch_channel_list(cur, &async_req);
|
||||
async_req.security.SecurityLevel = 0;
|
||||
|
||||
ws_llc_asynch_request(cur, &async_req);
|
||||
|
@ -2376,9 +2539,7 @@ static void ws_bootstrap_pan_advert(protocol_interface_info_entry_t *cur)
|
|||
async_req.wp_requested_nested_ie_list.pan_ie = true;
|
||||
async_req.wp_requested_nested_ie_list.net_name_ie = true;
|
||||
|
||||
ws_generate_channel_list(async_req.channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain);
|
||||
|
||||
async_req.channel_list.channel_page = CHANNEL_PAGE_10;
|
||||
ws_set_asynch_channel_list(cur, &async_req);
|
||||
async_req.security.SecurityLevel = 0;
|
||||
|
||||
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
||||
|
@ -2409,9 +2570,8 @@ static void ws_bootstrap_pan_config(protocol_interface_info_entry_t *cur)
|
|||
async_req.wp_requested_nested_ie_list.gtkhash_ie = true;
|
||||
async_req.wp_requested_nested_ie_list.vp_ie = true;
|
||||
|
||||
ws_generate_channel_list(async_req.channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain);
|
||||
ws_set_asynch_channel_list(cur, &async_req);
|
||||
|
||||
async_req.channel_list.channel_page = CHANNEL_PAGE_10;
|
||||
async_req.security.SecurityLevel = mac_helper_default_security_level_get(cur);
|
||||
async_req.security.KeyIdMode = mac_helper_default_security_key_id_mode_get(cur);
|
||||
async_req.security.KeyIndex = mac_helper_default_key_index_get(cur);
|
||||
|
@ -2551,7 +2711,6 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* State machine
|
||||
*
|
||||
|
@ -2559,27 +2718,35 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
|
|||
void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
||||
if (!ws_bootstrap_network_found(cur)) {
|
||||
parent_info_t *selected_parent_ptr;
|
||||
|
||||
tr_debug("analyze network discovery result");
|
||||
|
||||
selected_parent_ptr = ws_bootstrap_candidate_parent_get_best(cur);
|
||||
|
||||
if (!selected_parent_ptr) {
|
||||
// Next check will be after one trickle
|
||||
cur->bootsrap_state_machine_cnt += cur->ws_info->trickle_params_pan_discovery.Imin + randLIB_get_8bit() % 50;
|
||||
tr_info("Making parent selection in %d s", (uint32_t)(cur->bootsrap_state_machine_cnt / 10));
|
||||
return;
|
||||
}
|
||||
tr_info("select network");
|
||||
tr_info("selected parent:%s panid %u", trace_array(selected_parent_ptr->addr, 8), selected_parent_ptr->pan_id);
|
||||
|
||||
// Add EAPOL neighbour
|
||||
cur->ws_info->network_pan_id = selected_parent_ptr->pan_id;
|
||||
cur->ws_info->pan_information = selected_parent_ptr->pan_information;
|
||||
cur->ws_info->pan_information.pan_version = 0; // This is learned from actual configuration
|
||||
|
||||
ws_bootstrap_fhss_activate(cur);
|
||||
llc_neighbour_req_t neighbor_info;
|
||||
if (!ws_bootstrap_neighbor_info_request(cur, cur->ws_info->parent_info.addr, &neighbor_info, true)) {
|
||||
if (!ws_bootstrap_neighbor_info_request(cur, selected_parent_ptr->addr, &neighbor_info, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &cur->ws_info->parent_info.ws_utt, cur->ws_info->parent_info.timestamp);
|
||||
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &cur->ws_info->parent_info.ws_us);
|
||||
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &selected_parent_ptr->ws_utt, selected_parent_ptr->timestamp);
|
||||
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &selected_parent_ptr->ws_us);
|
||||
|
||||
|
||||
ws_bootstrap_network_information_learn(cur);
|
||||
ws_bootstrap_fhss_activate(cur);
|
||||
|
||||
ws_pae_controller_set_target(cur, cur->ws_info->parent_info.pan_id, cur->ws_info->parent_info.addr); // temporary!!! store since auth
|
||||
ws_pae_controller_set_target(cur, selected_parent_ptr->pan_id, selected_parent_ptr->addr); // temporary!!! store since auth
|
||||
ws_bootstrap_event_authentication_start(cur);
|
||||
return;
|
||||
}
|
||||
|
@ -2618,31 +2785,15 @@ void ws_bootstrap_rpl_wait_process(protocol_interface_info_entry_t *cur)
|
|||
|
||||
/*
|
||||
|
||||
static bool ws_bootstrap_state_active(struct protocol_interface_info_entry *cur)
|
||||
{
|
||||
if(cur->nwk_bootstrap_state == ER_BOOTSRAP_DONE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ws_bootstrap_state_configure(struct protocol_interface_info_entry *cur)
|
||||
{
|
||||
// Think about the state value
|
||||
if(cur->nwk_bootstrap_state == ER_SCAN) {
|
||||
if (cur->nwk_bootstrap_state == ER_SCAN) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ws_bootstrap_state_wait_rpl(struct protocol_interface_info_entry *cur)
|
||||
{
|
||||
// Think about the state value
|
||||
if(cur->nwk_bootstrap_state == ER_RPL_SCAN) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur)
|
||||
{
|
||||
|
@ -2652,6 +2803,22 @@ static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *c
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool ws_bootstrap_state_active(struct protocol_interface_info_entry *cur)
|
||||
{
|
||||
if (cur->nwk_bootstrap_state == ER_BOOTSRAP_DONE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static bool ws_bootstrap_state_wait_rpl(struct protocol_interface_info_entry *cur)
|
||||
{
|
||||
// Think about the state value
|
||||
if (cur->nwk_bootstrap_state == ER_RPL_SCAN) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state)
|
||||
{
|
||||
cur->bootsrap_state_machine_cnt = 1;
|
||||
|
@ -2712,9 +2879,6 @@ void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t t
|
|||
if (cur->ws_info->pas_requests >= PCS_MAX) {
|
||||
// if MAX PCS sent restart discovery
|
||||
|
||||
// Remove network keys from MAC
|
||||
ws_pae_controller_nw_keys_remove(cur);
|
||||
|
||||
// Trickle is reseted when entering to discovery from state 3
|
||||
trickle_inconsistent_heard(&cur->ws_info->trickle_pan_advertisement_solicit, &cur->ws_info->trickle_params_pan_discovery);
|
||||
ws_bootstrap_event_discovery_start(cur);
|
||||
|
@ -2796,7 +2960,6 @@ void ws_bootstrap_etx_accelerate(protocol_interface_info_entry_t *interface, mac
|
|||
neigh->nud_active = true;
|
||||
//Push NS to send
|
||||
ws_nud_active_timer(interface, 0);
|
||||
|
||||
}
|
||||
|
||||
#endif //HAVE_WS
|
||||
|
|
|
@ -288,6 +288,9 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur)
|
|||
ns_list_init(&cur->ws_info->active_nud_process);
|
||||
ns_list_init(&cur->ws_info->free_nud_entries);
|
||||
|
||||
ns_list_init(&cur->ws_info->parent_list_free);
|
||||
ns_list_init(&cur->ws_info->parent_list_reserved);
|
||||
|
||||
cur->ws_info->pan_information.use_parent_bs = true;
|
||||
cur->ws_info->pan_information.rpl_routing_method = true;
|
||||
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0;
|
||||
|
@ -295,8 +298,14 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur)
|
|||
cur->ws_info->hopping_schdule.regulatory_domain = REG_DOMAIN_EU;
|
||||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_3;
|
||||
cur->ws_info->hopping_schdule.operating_class = 2;
|
||||
// Clock drift value 255 indicates that information is not provided
|
||||
cur->ws_info->hopping_schdule.clock_drift = 255;
|
||||
// Timing accuracy is given from 0 to 2.55msec with 10usec resolution
|
||||
cur->ws_info->hopping_schdule.timing_accurancy = 100;
|
||||
ws_common_regulatory_domain_config(cur);
|
||||
cur->ws_info->network_size_config = NETWORK_SIZE_MEDIUM;
|
||||
cur->ws_info->rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
|
||||
cur->ws_info->rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
|
||||
ws_common_network_size_configure(cur, 200); // defaults to medium network size
|
||||
|
||||
// Set defaults for the device. user can modify these.
|
||||
|
@ -326,9 +335,11 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint
|
|||
// doublings:3 (128s)
|
||||
// redundancy; 0 Disabled
|
||||
if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC) {
|
||||
ws_bbr_rpl_config(14, 3, 0);
|
||||
ws_bbr_rpl_config(14, 3, 0, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE);
|
||||
} else if (cur->ws_info->network_size_config == NETWORK_SIZE_CERTIFICATE) {
|
||||
ws_bbr_rpl_config(0, 0, 0, WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE, WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE);
|
||||
} else {
|
||||
ws_bbr_rpl_config(0, 0, 0);
|
||||
ws_bbr_rpl_config(0, 0, 0, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE);
|
||||
}
|
||||
ws_pae_controller_timing_adjust(1); // Fast and reactive network
|
||||
} else if (network_size < 300) {
|
||||
|
@ -338,7 +349,7 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint
|
|||
// imin: 15 (32s)
|
||||
// doublings:5 (960s)
|
||||
// redundancy; 10
|
||||
ws_bbr_rpl_config(15, 5, 10);
|
||||
ws_bbr_rpl_config(15, 5, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE);
|
||||
ws_pae_controller_timing_adjust(9); // medium limited network
|
||||
} else {
|
||||
// Configure the Wi-SUN discovery trickle parameters
|
||||
|
@ -347,7 +358,7 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint
|
|||
// imin: 19 (524s, 9 min)
|
||||
// doublings:1 (1048s, 17 min)
|
||||
// redundancy; 10 May need some tuning still
|
||||
ws_bbr_rpl_config(19, 1, 10);
|
||||
ws_bbr_rpl_config(19, 1, 10, WS_RPL_MAX_HOP_RANK_INCREASE, WS_RPL_MIN_HOP_RANK_INCREASE);
|
||||
ws_pae_controller_timing_adjust(24); // Very slow and high latency network
|
||||
}
|
||||
return;
|
||||
|
@ -376,9 +387,12 @@ void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8
|
|||
}
|
||||
}
|
||||
|
||||
void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
|
||||
void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address, bool cache_full)
|
||||
{
|
||||
tr_warn("ARO registration Failure %s", trace_ipv6(ll_address));
|
||||
if (cache_full) {
|
||||
blacklist_update(ll_address, false);
|
||||
}
|
||||
ws_bootstrap_aro_failure(cur, ll_address);
|
||||
}
|
||||
|
||||
|
@ -435,7 +449,7 @@ bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, con
|
|||
}
|
||||
ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbour->index);
|
||||
ws_neighbor->negative_aro_send = true;
|
||||
neighbour->lifetime = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT; //Remove anyway if Packet is freed before MAC push
|
||||
neighbour->lifetime = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL; //Remove anyway if Packet is freed before MAC push
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -453,7 +467,7 @@ void ws_common_etx_validate(protocol_interface_info_entry_t *interface, mac_neig
|
|||
uint32_t ws_common_version_lifetime_get(uint8_t config)
|
||||
{
|
||||
uint32_t lifetime;
|
||||
if (config == NETWORK_SIZE_SMALL) {
|
||||
if (config == NETWORK_SIZE_SMALL || config == NETWORK_SIZE_CERTIFICATE) {
|
||||
lifetime = PAN_VERSION_SMALL_NETWORK_LIFETIME;
|
||||
} else if (config == NETWORK_SIZE_MEDIUM) {
|
||||
lifetime = PAN_VERSION_MEDIUM_NETWORK_LIFETIME;
|
||||
|
@ -468,7 +482,7 @@ uint32_t ws_common_version_lifetime_get(uint8_t config)
|
|||
uint32_t ws_common_version_timeout_get(uint8_t config)
|
||||
{
|
||||
uint32_t lifetime;
|
||||
if (config == NETWORK_SIZE_SMALL) {
|
||||
if (config == NETWORK_SIZE_SMALL || config == NETWORK_SIZE_CERTIFICATE) {
|
||||
lifetime = PAN_VERSION_SMALL_NETWORK_TIMEOUT;
|
||||
} else if (config == NETWORK_SIZE_MEDIUM) {
|
||||
lifetime = PAN_VERSION_MEDIUM_NETWORK_TIMEOUT;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "fhss_config.h"
|
||||
#include "net_fhss.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_common_defines.h"
|
||||
#include "6LoWPAN/ws/ws_neighbor_class.h"
|
||||
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
||||
|
@ -36,16 +37,20 @@ struct ws_pan_information_s;
|
|||
struct ws_neighbor_class_s;
|
||||
|
||||
typedef struct parent_info_s {
|
||||
uint16_t pan_id; /**< PAN ID */
|
||||
uint8_t addr[8]; /**< address */
|
||||
uint8_t link_quality; /**< LQI value measured during reception of the MPDU */
|
||||
int8_t signal_dbm; /**< This extension for normal IEEE 802.15.4 Data indication */
|
||||
uint16_t pan_id; /**< PAN ID */
|
||||
uint8_t addr[8]; /**< address */
|
||||
uint8_t link_quality; /**< LQI value measured during reception of the MPDU */
|
||||
int8_t signal_dbm; /**< This extension for normal IEEE 802.15.4 Data indication */
|
||||
ws_pan_information_t pan_information;
|
||||
ws_utt_ie_t ws_utt;
|
||||
ws_us_ie_t ws_us;
|
||||
uint32_t timestamp; /**< Timestamp when packet was received */
|
||||
ws_utt_ie_t ws_utt;
|
||||
ws_us_ie_t ws_us;
|
||||
uint32_t timestamp; /**< Timestamp when packet was received */
|
||||
uint32_t age; /**< Age of entry in 100ms ticks */
|
||||
ns_list_link_t link;
|
||||
} parent_info_t;
|
||||
|
||||
typedef NS_LIST_HEAD(parent_info_t, link) parent_info_list_t;
|
||||
|
||||
typedef struct ws_nud_table_entry {
|
||||
void *neighbor_info;
|
||||
uint16_t timer; /*!< Timer which resolution is 100ms*/
|
||||
|
@ -67,9 +72,13 @@ typedef struct ws_info_s {
|
|||
trickle_t trickle_pan_advertisement;
|
||||
trickle_params_t trickle_params_pan_discovery;
|
||||
uint8_t network_size_config; // configuration for network size selection of application.
|
||||
uint16_t rpl_parent_candidate_max;
|
||||
uint16_t rpl_selected_parent_max;
|
||||
uint8_t rpl_state; // state from rpl_event_t
|
||||
uint8_t pas_requests; // Amount of PAN solicits sent
|
||||
parent_info_t parent_info;
|
||||
parent_info_t parent_info[WS_PARENT_LIST_SIZE];
|
||||
parent_info_list_t parent_list_free;
|
||||
parent_info_list_t parent_list_reserved;
|
||||
uint32_t pan_version_timer; /**< border router version udate timeout */
|
||||
uint32_t pan_version_timeout_timer; /**< routers will fallback to previous state after this */
|
||||
uint8_t gtkhash[32];
|
||||
|
@ -78,6 +87,7 @@ typedef struct ws_info_s {
|
|||
bool trickle_pa_running: 1;
|
||||
bool trickle_pcs_running: 1;
|
||||
bool trickle_pc_running: 1;
|
||||
bool fhss_owner: 1;
|
||||
// default fhss parameters for this device
|
||||
uint8_t fhss_uc_dwell_interval;
|
||||
uint8_t fhss_bc_dwell_interval;
|
||||
|
@ -116,7 +126,7 @@ void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks);
|
|||
|
||||
void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address, bool cache_full);
|
||||
|
||||
void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
|
@ -136,7 +146,7 @@ uint32_t ws_common_version_timeout_get(uint8_t config);
|
|||
#define ws_info(cur) ((ws_info_t *) NULL)
|
||||
#define ws_common_seconds_timer(cur, seconds)
|
||||
#define ws_common_neighbor_update(cur, ll_address) ((void) 0)
|
||||
#define ws_common_aro_failure(cur, ll_address)
|
||||
#define ws_common_aro_failure(cur, ll_address, cache_full)
|
||||
#define ws_common_neighbor_remove(cur, ll_address)
|
||||
#define ws_common_fast_timer(cur, ticks) ((void) 0)
|
||||
#define ws_common_allow_child_registration(cur, eui64) (false)
|
||||
|
|
|
@ -186,7 +186,8 @@ typedef struct ws_bs_ie {
|
|||
#define WS_FAN_VERSION_1_0 1
|
||||
|
||||
#define WS_NEIGHBOR_LINK_TIMEOUT 2200
|
||||
#define WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT 120
|
||||
#define WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE 520
|
||||
#define WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL 260
|
||||
#define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2
|
||||
|
||||
#define WS_NEIGBOR_ETX_SAMPLE_MAX 3
|
||||
|
@ -206,6 +207,12 @@ typedef struct ws_bs_ie {
|
|||
|
||||
#define WS_ETX_MIN_WAIT_TIME 60
|
||||
|
||||
#define WS_RPL_PARENT_CANDIDATE_MAX 5
|
||||
#define WS_RPL_SELECTED_PARENT_MAX 2
|
||||
|
||||
#define WS_CERTIFICATE_RPL_PARENT_CANDIDATE_MAX 8
|
||||
#define WS_CERTIFICATE_RPL_SELECTED_PARENT_MAX 3
|
||||
|
||||
/**
|
||||
* Wi-sun spesific non-preferred prefix policy label
|
||||
*/
|
||||
|
|
|
@ -31,6 +31,11 @@
|
|||
#define WS_RPL_DIO_DOUBLING 2
|
||||
#define WS_RPL_DIO_REDUNDANCY 0
|
||||
|
||||
#define WS_RPL_MIN_HOP_RANK_INCREASE 196
|
||||
#define WS_RPL_MAX_HOP_RANK_INCREASE 2048
|
||||
|
||||
#define WS_CERTIFICATE_RPL_MIN_HOP_RANK_INCREASE 128
|
||||
#define WS_CERTIFICATE_RPL_MAX_HOP_RANK_INCREASE 0
|
||||
|
||||
/* Border router version change interval
|
||||
*
|
||||
|
@ -130,6 +135,7 @@ extern uint8_t DEVICE_MIN_SENS;
|
|||
* MAC frame counter NVM storing configuration
|
||||
*/
|
||||
#define FRAME_COUNTER_STORE_INTERVAL 60 // Time interval (on seconds) between frame counter store operations
|
||||
#define FRAME_COUNTER_STORE_TRIGGER 5 // Delay (on seconds) before storing, when storing of frame counters is triggered
|
||||
#define FRAME_COUNTER_INCREMENT 1000 // How much frame counter is incremented on start up
|
||||
#define FRAME_COUNTER_STORE_THRESHOLD 800 // How much frame counter must increment before it is stored
|
||||
|
||||
|
@ -141,4 +147,20 @@ extern uint8_t DEVICE_MIN_SENS;
|
|||
#define WS_MAX_DAO_INITIAL_TIMEOUT 400 // With 40s initial value exponentially increasing
|
||||
#define WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT 10 // Define 10 multicast advertisment when learn config or learn config update
|
||||
|
||||
/*
|
||||
* Candidate parent list parameters
|
||||
*/
|
||||
|
||||
#define WS_PARENT_LIST_SIZE 10
|
||||
#define WS_PARENT_LIST_MAX_AGE 3600*10 // 1 hour in 100ms ticks
|
||||
#define WS_PARENT_LIST_MAX_PAN_IN_DISCOVERY 5 // During discovery state how many neighbours per pan
|
||||
#define WS_PARENT_LIST_MAX_PAN_IN_ACTIVE 2 // During active state two nodes per pan is allowed
|
||||
|
||||
/*
|
||||
* Modifications for base specification.
|
||||
*
|
||||
* ERRATA changes after 1.0 specification release.
|
||||
*/
|
||||
#define WISUN_1_0_ERRATA_FIX
|
||||
|
||||
#endif /* WS_CONFIG_H_ */
|
||||
|
|
|
@ -37,9 +37,11 @@
|
|||
#define TRACE_GROUP "wsep"
|
||||
|
||||
typedef struct {
|
||||
uint8_t handle;
|
||||
void *data_ptr;
|
||||
void *buffer;
|
||||
ws_eapol_pdu_tx_status *tx_status;
|
||||
uint8_t tx_identifier;
|
||||
uint8_t handle;
|
||||
ns_list_link_t link;
|
||||
} eapol_pdu_msdu_t;
|
||||
|
||||
|
@ -180,7 +182,7 @@ int8_t ws_eapol_pdu_cb_unregister(protocol_interface_info_entry_t *interface_ptr
|
|||
return -1;
|
||||
}
|
||||
|
||||
int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *data, uint16_t size, void *buffer)
|
||||
int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *data, uint16_t size, void *buffer, ws_eapol_pdu_tx_status *tx_status, uint8_t tx_identifier)
|
||||
{
|
||||
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
||||
|
||||
|
@ -198,6 +200,8 @@ int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr,
|
|||
msdu_entry->data_ptr = data;
|
||||
msdu_entry->buffer = buffer;
|
||||
msdu_entry->handle = eapol_pdu_data->msdu_handle;
|
||||
msdu_entry->tx_status = tx_status;
|
||||
msdu_entry->tx_identifier = tx_identifier;
|
||||
ns_list_add_to_start(&eapol_pdu_data->msdu_list, msdu_entry);
|
||||
|
||||
memcpy(data_request.DstAddr, eui_64, 8);
|
||||
|
@ -265,6 +269,15 @@ static void ws_eapol_pdu_mpx_data_confirm(const mpx_api_t *api, const struct mcp
|
|||
|
||||
ns_list_foreach(eapol_pdu_msdu_t, msdu, &eapol_pdu_data->msdu_list) {
|
||||
if (msdu->handle == data->msduHandle) {
|
||||
if (msdu->tx_status) {
|
||||
eapol_pdu_tx_status_e status = EAPOL_PDU_TX_ERR_UNSPEC;
|
||||
if (data->status == MLME_SUCCESS) {
|
||||
status = EAPOL_PDU_TX_OK;
|
||||
} else if (data->status == MLME_TX_NO_ACK) {
|
||||
status = EAPOL_PDU_TX_ERR_TX_NO_ACK;
|
||||
}
|
||||
msdu->tx_status(eapol_pdu_data->interface_ptr, status, msdu->tx_identifier);
|
||||
}
|
||||
ns_dyn_mem_free(msdu->buffer);
|
||||
ns_list_remove(&eapol_pdu_data->msdu_list, msdu);
|
||||
ns_dyn_mem_free(msdu);
|
||||
|
|
|
@ -127,6 +127,22 @@ int8_t ws_eapol_pdu_cb_register(protocol_interface_info_entry_t *interface_ptr,
|
|||
*/
|
||||
int8_t ws_eapol_pdu_cb_unregister(protocol_interface_info_entry_t *interface_ptr, const eapol_pdu_recv_cb_data_t *cb_data);
|
||||
|
||||
typedef enum {
|
||||
EAPOL_PDU_TX_OK = 0, // Successful
|
||||
EAPOL_PDU_TX_ERR_TX_NO_ACK = -1, // No acknowledge was received
|
||||
EAPOL_PDU_TX_ERR_UNSPEC = -2, // Other reason
|
||||
} eapol_pdu_tx_status_e;
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_tx_status will be called when TX status is known
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param tx_status tx status
|
||||
* \param tx_identifier tx identifier
|
||||
*
|
||||
*/
|
||||
typedef int8_t ws_eapol_pdu_tx_status(protocol_interface_info_entry_t *interface_ptr, eapol_pdu_tx_status_e tx_status, uint8_t tx_identifier);
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_send_to_mpx send EAPOL PDU to MPX
|
||||
*
|
||||
|
@ -135,11 +151,13 @@ int8_t ws_eapol_pdu_cb_unregister(protocol_interface_info_entry_t *interface_ptr
|
|||
* \param data EAPOL PDU
|
||||
* \param size PDU size
|
||||
* \param buffer pointer to allocated buffer
|
||||
* \param tx_status tx status callback
|
||||
* \param tx_identifier tx identifier
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *data, uint16_t size, void *buffer);
|
||||
int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *data, uint16_t size, void *buffer, ws_eapol_pdu_tx_status tx_status, uint8_t tx_identifier);
|
||||
|
||||
#endif /* WS_EAPOL_PDU_H_ */
|
||||
|
|
|
@ -183,7 +183,7 @@ static void ws_eapol_relay_socket_cb(void *cb)
|
|||
}
|
||||
|
||||
//First 8 byte is EUID64 and rsr payload
|
||||
if (ws_eapol_pdu_send_to_mpx(eapol_relay->interface_ptr, socket_pdu, socket_pdu + 8, cb_data->d_len - 8, socket_pdu) < 0) {
|
||||
if (ws_eapol_pdu_send_to_mpx(eapol_relay->interface_ptr, socket_pdu, socket_pdu + 8, cb_data->d_len - 8, socket_pdu, NULL, 0) < 0) {
|
||||
ns_dyn_mem_free(socket_pdu);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -514,6 +514,11 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t
|
|||
return;
|
||||
}
|
||||
|
||||
if (interface->mac_parameters->pan_id != 0xffff && data->SrcPANId != interface->mac_parameters->pan_id) {
|
||||
//Drop wrong PAN-id messages in this phase.
|
||||
return;
|
||||
}
|
||||
|
||||
mpx_user_t *user_cb;
|
||||
mac_payload_IE_t mpx_ie;
|
||||
mpx_ie.id = MAC_PAYLOAD_MPX_IE_GROUP_ID;
|
||||
|
|
|
@ -136,18 +136,35 @@ int ws_management_network_size_set(
|
|||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
if (network_size > NETWORK_SIZE_LARGE) {
|
||||
return -2;
|
||||
}
|
||||
//Store old setup if new is not accepted
|
||||
uint8_t old_setup = ws_info(cur)->network_size_config;
|
||||
ws_info(cur)->network_size_config = network_size;
|
||||
|
||||
uint16_t rpl_parent_candidate_max;
|
||||
uint16_t rpl_selected_parent_max;
|
||||
|
||||
if (network_size == NETWORK_SIZE_CERTIFICATE) {
|
||||
rpl_parent_candidate_max = WS_CERTIFICATE_RPL_PARENT_CANDIDATE_MAX;
|
||||
rpl_selected_parent_max = WS_CERTIFICATE_RPL_SELECTED_PARENT_MAX;
|
||||
} else {
|
||||
rpl_parent_candidate_max = WS_RPL_PARENT_CANDIDATE_MAX;
|
||||
rpl_selected_parent_max = WS_RPL_SELECTED_PARENT_MAX;
|
||||
}
|
||||
|
||||
if (network_size == NETWORK_SIZE_LARGE) {
|
||||
ws_common_network_size_configure(cur, 5000);
|
||||
} else if (network_size == NETWORK_SIZE_MEDIUM) {
|
||||
ws_common_network_size_configure(cur, 200);
|
||||
} else {
|
||||
} else if (network_size == NETWORK_SIZE_SMALL) {
|
||||
ws_common_network_size_configure(cur, 10);
|
||||
} else if (network_size == NETWORK_SIZE_CERTIFICATE) {
|
||||
ws_common_network_size_configure(cur, 0);
|
||||
} else {
|
||||
ws_info(cur)->network_size_config = old_setup;
|
||||
return -2;
|
||||
}
|
||||
cur->ws_info->rpl_parent_candidate_max = rpl_parent_candidate_max;
|
||||
cur->ws_info->rpl_selected_parent_max = rpl_selected_parent_max;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -241,8 +258,20 @@ int ws_management_fhss_unicast_channel_function_configure(
|
|||
channel_function != WS_TR51CF) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (channel_function == WS_FIXED_CHANNEL && fixed_channel == 0xffff) {
|
||||
fixed_channel = 0;
|
||||
tr_warn("Fixed channel not configured. Set to 0");
|
||||
}
|
||||
|
||||
|
||||
cur->ws_info->fhss_uc_channel_function = channel_function;
|
||||
cur->ws_info->fhss_uc_fixed_channel = fixed_channel;
|
||||
if (cur->ws_info->fhss_uc_channel_function == WS_FIXED_CHANNEL) {
|
||||
cur->ws_info->fhss_uc_fixed_channel = fixed_channel;
|
||||
} else {
|
||||
cur->ws_info->fhss_uc_fixed_channel = 0xffff;
|
||||
}
|
||||
|
||||
cur->ws_info->fhss_uc_dwell_interval = dwell_interval;
|
||||
|
||||
// if settings change reset_restart for the settings needed
|
||||
|
@ -273,8 +302,19 @@ int ws_management_fhss_broadcast_channel_function_configure(
|
|||
channel_function != WS_TR51CF) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (channel_function == WS_FIXED_CHANNEL && fixed_channel == 0xffff) {
|
||||
fixed_channel = 0;
|
||||
tr_warn("Fixed channel not configured. Set to 0");
|
||||
}
|
||||
|
||||
cur->ws_info->fhss_bc_channel_function = channel_function;
|
||||
cur->ws_info->fhss_bc_fixed_channel = fixed_channel;
|
||||
if (cur->ws_info->fhss_bc_channel_function == WS_FIXED_CHANNEL) {
|
||||
cur->ws_info->fhss_bc_fixed_channel = fixed_channel;
|
||||
} else {
|
||||
cur->ws_info->fhss_bc_fixed_channel = 0xffff;
|
||||
}
|
||||
|
||||
cur->ws_info->fhss_bc_dwell_interval = dwell_interval;
|
||||
cur->ws_info->fhss_bc_interval = broadcast_interval;
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (kmp_service_cb_register(pae_auth->kmp_service, ws_pae_auth_kmp_incoming_ind, ws_pae_auth_kmp_service_addr_get, ws_pae_auth_kmp_service_api_get)) {
|
||||
if (kmp_service_cb_register(pae_auth->kmp_service, ws_pae_auth_kmp_incoming_ind, NULL, ws_pae_auth_kmp_service_addr_get, ws_pae_auth_kmp_service_api_get)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (key_sec_prot_register(pae_auth->kmp_service) < 0) {
|
||||
if (auth_key_sec_prot_register(pae_auth->kmp_service) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,18 +48,11 @@ typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface
|
|||
typedef int8_t ws_pae_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
|
||||
typedef struct {
|
||||
uint8_t hash[8]; /**< GTK hash for the key */
|
||||
uint8_t gtk[GTK_LEN]; /**< GTK key */
|
||||
bool set : 1; /**< Key has been set */
|
||||
bool installed : 1; /**< Key has been installed on MAC */
|
||||
bool fresh : 1; /**< Key is fresh i.e. not used on sending */
|
||||
} nw_key_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t hash[8]; /**< GTK hash for the frame counter */
|
||||
uint32_t frame_counter; /**< Frame counter */
|
||||
uint8_t index; /**< Index */
|
||||
bool set : 1; /**< Value has been set */
|
||||
} stored_frame_counter_t;
|
||||
|
||||
typedef struct {
|
||||
ns_list_link_t link; /**< Link */
|
||||
uint8_t target_eui_64[8]; /**< EAPOL target */
|
||||
|
@ -70,10 +63,10 @@ typedef struct {
|
|||
int8_t gtk_index; /**< GTK index */
|
||||
uint8_t gtkhash[32]; /**< GTK hashes */
|
||||
sec_prot_certs_t certs; /**< Certificates */
|
||||
nw_key_t nw_key[4]; /**< Currently active network keys (on MAC) */
|
||||
nw_key_t nw_key[GTK_NUM]; /**< Currently active network keys (on MAC) */
|
||||
char *network_name; /**< Network name for GAK generation */
|
||||
uint16_t frame_cnt_store_timer; /**< Timer for storing frame counter value */
|
||||
stored_frame_counter_t stored_frame_counter; /**< Stored frame counter */
|
||||
frame_counters_t frame_counters; /**< Frame counters */
|
||||
timer_settings_t timer_settings; /**< Timer settings */
|
||||
protocol_interface_info_entry_t *interface_ptr; /**< List link entry */
|
||||
ws_pae_controller_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */
|
||||
|
@ -105,9 +98,10 @@ typedef struct {
|
|||
|
||||
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
|
||||
static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry);
|
||||
static void ws_pae_controller_frame_counter_store(pae_controller_t *entry);
|
||||
static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry);
|
||||
static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool use_threshold);
|
||||
static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_entry_t *tlv_entry);
|
||||
static int8_t ws_pae_controller_nvm_frame_counter_read(uint8_t *index, uint8_t *hash, uint32_t *frame_counter);
|
||||
static int8_t ws_pae_controller_nvm_frame_counter_read(frame_counters_t *counters);
|
||||
static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id);
|
||||
static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
|
||||
static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
|
||||
|
@ -117,9 +111,7 @@ static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *n
|
|||
static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
static void ws_pae_controller_data_init(pae_controller_t *controller);
|
||||
static void ws_pae_controller_frame_counter_read(pae_controller_t *controller);
|
||||
static void ws_pae_controller_frame_counter_reset(stored_frame_counter_t *counter);
|
||||
static uint32_t ws_pae_controller_frame_counter_get(stored_frame_counter_t *counter, uint8_t index, uint8_t *key_hash);
|
||||
static void ws_pae_controller_frame_counter_write(pae_controller_t *controller, uint8_t index, uint8_t *key_hash, uint32_t curr_counter);
|
||||
static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters);
|
||||
|
||||
static const char *FRAME_COUNTER_FILE = FRAME_COUNTER_FILE_NAME;
|
||||
|
||||
|
@ -164,13 +156,14 @@ int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface
|
|||
if (sec_prot_keys_gtks_are_updated(&controller->gtks)) {
|
||||
ws_pae_controller_nw_key_check_and_insert(controller->interface_ptr, &controller->gtks);
|
||||
sec_prot_keys_gtks_updated_reset(&controller->gtks);
|
||||
ws_pae_supp_gtks_set(controller->interface_ptr, &controller->gtks);
|
||||
}
|
||||
controller->auth_completed(interface_ptr, true);
|
||||
controller->auth_completed(interface_ptr, AUTH_RESULT_OK, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ws_pae_supp_authenticate(controller->interface_ptr, controller->target_pan_id, controller->target_eui_64) < 0) {
|
||||
controller->auth_completed(interface_ptr, false);
|
||||
controller->auth_completed(interface_ptr, AUTH_RESULT_ERR_UNSPEC, controller->target_eui_64);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -178,7 +171,7 @@ int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface
|
|||
ws_pae_controller_nw_key_check_and_insert(interface_ptr, &controller->gtks);
|
||||
ws_pae_controller_nw_key_index_check_and_set(interface_ptr, 0);
|
||||
|
||||
controller->auth_completed(interface_ptr, true);
|
||||
controller->auth_completed(interface_ptr, AUTH_RESULT_OK);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -320,63 +313,86 @@ int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface
|
|||
|
||||
static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
int8_t ret = -1;
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t gtkhash[GTK_ALL_HASHES_LEN];
|
||||
sec_prot_keys_gtks_hash_generate(gtks, gtkhash);
|
||||
int8_t ret = -1;
|
||||
|
||||
// Adds, removes and updates network keys to MAC based on new GTKs
|
||||
nw_key_t *nw_key = controller->nw_key;
|
||||
|
||||
// Delete old keys
|
||||
uint8_t *gtk_hash_ptr = gtkhash;
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
// If hash is not set for a key
|
||||
if (sec_prot_keys_gtk_hash_empty(gtk_hash_ptr)) {
|
||||
// Deletes the key if it is set
|
||||
if (!sec_prot_keys_gtk_hash_empty(nw_key[i].hash)) {
|
||||
tr_info("NW key remove: %i", i);
|
||||
// Gets GTK for the index (new, modified or none)
|
||||
uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
|
||||
|
||||
// If network key is set and GTK key is not set or not the same, removes network key
|
||||
if (nw_key[i].set && (!gtk || memcmp(nw_key[i].gtk, gtk, GTK_LEN) != 0)) {
|
||||
// Removes key from MAC if installed
|
||||
if (nw_key[i].installed) {
|
||||
controller->nw_key_clear(interface_ptr, i);
|
||||
nw_key[i].installed = false;
|
||||
}
|
||||
nw_key[i].installed = false;
|
||||
nw_key[i].set = false;
|
||||
tr_info("NW key remove: %i", i);
|
||||
}
|
||||
gtk_hash_ptr += GTK_HASH_LEN;
|
||||
}
|
||||
|
||||
// Insert new keys
|
||||
gtk_hash_ptr = gtkhash;
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
// If hash is set for a key
|
||||
if (!sec_prot_keys_gtk_hash_empty(gtk_hash_ptr)) {
|
||||
int hash_matches = memcmp(gtk_hash_ptr, nw_key[i].hash, GTK_HASH_LEN);
|
||||
// If the hash does not match (not set or modified) or not installed
|
||||
if (hash_matches != 0 || !nw_key[i].installed) {
|
||||
// If GTK key is not set, continues to next GTK
|
||||
if (!gtk) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(nw_key[i].hash, gtk_hash_ptr, GTK_HASH_LEN);
|
||||
// Network key is set and installed, all done
|
||||
if (nw_key[i].set && nw_key[i].installed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If network key is not set, stores the new GTK key to network key
|
||||
if (!nw_key[i].set) {
|
||||
nw_key[i].set = true;
|
||||
nw_key[i].installed = false;
|
||||
memcpy(nw_key[i].gtk, gtk, GTK_LEN);
|
||||
}
|
||||
|
||||
// If network key has not been installed, installs it and updates frame counter as needed
|
||||
if (!nw_key[i].installed) {
|
||||
uint8_t gtkhash[GTK_HASH_LEN];
|
||||
sec_prot_keys_gtk_hash_generate(gtk, gtkhash);
|
||||
tr_info("NW key set: %i, hash: %s", i, trace_array(gtkhash, 8));
|
||||
uint8_t gak[GTK_LEN];
|
||||
if (ws_pae_controller_gak_from_gtk(gak, gtk, controller->network_name) >= 0) {
|
||||
// Install the new network key derived from GTK and network name (GAK) to MAC
|
||||
controller->nw_key_set(interface_ptr, i, i, gak);
|
||||
tr_info("NW: %s", controller->network_name);
|
||||
tr_info("NW: %s", trace_array((uint8_t *)controller->network_name, 20));
|
||||
tr_info("GTK: %s", trace_array(gtk, 16));
|
||||
tr_info("GAK: %s", trace_array(gak, 16));
|
||||
nw_key[i].installed = true;
|
||||
if (hash_matches != 0) {
|
||||
nw_key[i].fresh = true;
|
||||
}
|
||||
ret = 0;
|
||||
} else {
|
||||
tr_error("GAK generation failed network name: %s", controller->network_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
|
||||
tr_info("NW key set: %i, hash: %s", i, trace_array(nw_key[i].hash, 8));
|
||||
uint8_t gak[GTK_LEN];
|
||||
if (ws_pae_controller_gak_from_gtk(gak, gtk, controller->network_name) >= 0) {
|
||||
controller->nw_key_set(interface_ptr, i, i, gak);
|
||||
ret = 0;
|
||||
} else {
|
||||
tr_error("GAK generation failed network name: %s", controller->network_name);
|
||||
ret = -1;
|
||||
// If frame counter value has been stored for the network key, updates the frame counter if needed
|
||||
if (controller->frame_counters.counter[i].set &&
|
||||
memcmp(gtk, controller->frame_counters.counter[i].gtk, GTK_LEN) == 0) {
|
||||
// Read current counter from MAC
|
||||
uint32_t curr_frame_counter;
|
||||
controller->nw_frame_counter_read(controller->interface_ptr, &curr_frame_counter, i);
|
||||
// If stored frame counter is greater than MAC counter
|
||||
if (controller->frame_counters.counter[i].frame_counter > curr_frame_counter) {
|
||||
tr_debug("Frame counter set: %i, stored %"PRIu32" current: %"PRIu32"", i, controller->frame_counters.counter[i].frame_counter, curr_frame_counter);
|
||||
curr_frame_counter = controller->frame_counters.counter[i].frame_counter;
|
||||
// Updates MAC frame counter
|
||||
controller->nw_frame_counter_set(controller->interface_ptr, curr_frame_counter, i);
|
||||
}
|
||||
}
|
||||
/* Trigger storing of frame counters; there is 5 seconds delay to give time for the
|
||||
other keys to be inserted, so that frame counters for several keys are updated on
|
||||
a same time. */
|
||||
ws_pae_controller_frame_counter_timer_trigger(FRAME_COUNTER_STORE_TRIGGER, controller);
|
||||
}
|
||||
|
||||
gtk_hash_ptr += GTK_HASH_LEN;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -385,8 +401,8 @@ static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_
|
|||
static void ws_pae_controller_active_nw_key_clear(nw_key_t *nw_key)
|
||||
{
|
||||
memset(nw_key, 0, sizeof(nw_key_t));
|
||||
nw_key->set = false;
|
||||
nw_key->installed = false;
|
||||
nw_key->fresh = false;
|
||||
}
|
||||
|
||||
static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name)
|
||||
|
@ -463,9 +479,12 @@ void ws_pae_controller_nw_keys_remove(protocol_interface_info_entry_t *interface
|
|||
nw_key_t *nw_key = controller->nw_key;
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
// Deletes the key if it is set
|
||||
if (!sec_prot_keys_gtk_hash_empty(nw_key[i].hash)) {
|
||||
if (nw_key[i].set) {
|
||||
tr_info("NW key remove: %i", i);
|
||||
controller->nw_key_clear(interface_ptr, i);
|
||||
if (nw_key[i].installed) {
|
||||
controller->nw_key_clear(interface_ptr, i);
|
||||
}
|
||||
nw_key[i].set = false;
|
||||
nw_key[i].installed = false;
|
||||
}
|
||||
}
|
||||
|
@ -482,14 +501,6 @@ static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info
|
|||
tr_info("NW send key index set: %i", index + 1);
|
||||
controller->nw_send_key_index_set(interface_ptr, index);
|
||||
controller->gtk_index = index;
|
||||
|
||||
uint32_t frame_counter = ws_pae_controller_frame_counter_get(&controller->stored_frame_counter, index, controller->nw_key[index].hash);
|
||||
if (frame_counter) {
|
||||
controller->nw_frame_counter_set(interface_ptr, frame_counter);
|
||||
}
|
||||
tr_info("NW frame counter set: %"PRIu32"", frame_counter);
|
||||
ws_pae_controller_frame_counter_write(controller, index, controller->nw_key[index].hash, frame_counter);
|
||||
|
||||
}
|
||||
|
||||
// Do not update PAN version for initial key index set
|
||||
|
@ -510,22 +521,13 @@ static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t
|
|||
}
|
||||
|
||||
if (controller->nw_send_key_index_set) {
|
||||
/* Checks if frame counters needs to be stored for the new GTK that is taken into
|
||||
use; this is the last check that stored counters are in sync before activating key */
|
||||
ws_pae_controller_frame_counter_store(controller, true);
|
||||
// Activates key on MAC
|
||||
controller->nw_send_key_index_set(controller->interface_ptr, index);
|
||||
tr_info("NW send key index set: %i", index + 1);
|
||||
|
||||
// If index has changed and the key for the index is fresh get frame counter
|
||||
if (controller->gtk_index != index && controller->nw_key[index].fresh) {
|
||||
uint32_t frame_counter = ws_pae_controller_frame_counter_get(&controller->stored_frame_counter, index, controller->nw_key[index].hash);
|
||||
if (frame_counter) {
|
||||
controller->nw_frame_counter_set(cur, frame_counter);
|
||||
}
|
||||
tr_info("NW frame counter set: %"PRIu32"", frame_counter);
|
||||
ws_pae_controller_frame_counter_write(controller, index, controller->nw_key[index].hash, frame_counter);
|
||||
|
||||
}
|
||||
|
||||
controller->gtk_index = index;
|
||||
controller->nw_key[index].fresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -590,7 +592,7 @@ static void ws_pae_controller_data_init(pae_controller_t *controller)
|
|||
controller->gtk_index = -1;
|
||||
controller->network_name = NULL;
|
||||
controller->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL;
|
||||
ws_pae_controller_frame_counter_reset(&controller->stored_frame_counter);
|
||||
ws_pae_controller_frame_counter_reset(&controller->frame_counters);
|
||||
sec_prot_keys_gtks_init(&controller->gtks);
|
||||
sec_prot_keys_gtks_init(&controller->next_gtks);
|
||||
sec_prot_certs_init(&controller->certs);
|
||||
|
@ -600,49 +602,35 @@ static void ws_pae_controller_data_init(pae_controller_t *controller)
|
|||
|
||||
static void ws_pae_controller_frame_counter_read(pae_controller_t *controller)
|
||||
{
|
||||
stored_frame_counter_t *counter = &controller->stored_frame_counter;
|
||||
// If not already, read frame counter and check if index and hash matches
|
||||
if (!counter->set && ws_pae_controller_nvm_frame_counter_read(&counter->index, counter->hash, &counter->frame_counter) >= 0) {
|
||||
counter->frame_counter += FRAME_COUNTER_INCREMENT;
|
||||
counter->set = true;
|
||||
tr_debug("Read frame counter: %"PRIu32", index %i, hash %s, system time: %"PRIu32"", counter->frame_counter, counter->index, trace_array(counter->hash, 8), protocol_core_monotonic_time / 10);
|
||||
// Write incremented frame counter
|
||||
ws_pae_nvm_store_frame_counter_tlv_create(controller->pae_nvm_buffer, counter->index, counter->hash, counter->frame_counter);
|
||||
ws_pae_controller_nvm_frame_counter_write(controller->pae_nvm_buffer);
|
||||
// Read frame counters
|
||||
if (ws_pae_controller_nvm_frame_counter_read(&controller->frame_counters) >= 0) {
|
||||
bool updated = false;
|
||||
// Checks frame counters
|
||||
for (uint8_t index = 0; index < GTK_NUM; index++) {
|
||||
if (controller->frame_counters.counter[index].set) {
|
||||
// Increments frame counters
|
||||
controller->frame_counters.counter[index].frame_counter += FRAME_COUNTER_INCREMENT;
|
||||
|
||||
tr_info("Read frame counter: index %i value %"PRIu32"", index, controller->frame_counters.counter[index].frame_counter);
|
||||
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
if (updated) {
|
||||
// Writes incremented frame counters
|
||||
ws_pae_nvm_store_frame_counter_tlv_create(controller->pae_nvm_buffer, &controller->frame_counters);
|
||||
ws_pae_controller_nvm_frame_counter_write(controller->pae_nvm_buffer);
|
||||
//ws_pae_controller_frame_counter_write(controller, &controller->frame_counters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_pae_controller_frame_counter_reset(stored_frame_counter_t *counter)
|
||||
static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters)
|
||||
{
|
||||
memset(counter->hash, 0, GTK_HASH_LEN);
|
||||
counter->frame_counter = 0;
|
||||
counter->index = -1;
|
||||
counter->set = false;
|
||||
}
|
||||
|
||||
static uint32_t ws_pae_controller_frame_counter_get(stored_frame_counter_t *counter, uint8_t index, uint8_t *key_hash)
|
||||
{
|
||||
uint32_t frame_counter = 0;
|
||||
// If both index and hash matches uses the stored frame counter
|
||||
if (counter->set && counter->index == index && memcmp(counter->hash, key_hash, GTK_HASH_LEN) == 0) {
|
||||
frame_counter = counter->frame_counter;
|
||||
}
|
||||
|
||||
return frame_counter;
|
||||
}
|
||||
|
||||
static void ws_pae_controller_frame_counter_write(pae_controller_t *controller, uint8_t index, uint8_t *key_hash, uint32_t curr_frame_counter)
|
||||
{
|
||||
stored_frame_counter_t *counter = &controller->stored_frame_counter;
|
||||
// If index or hash changes, or frame counter has been incremented by the threshold updates frame counter
|
||||
if (!counter->set || counter->index != index || memcmp(key_hash, counter->hash, 8) != 0 || curr_frame_counter > counter->frame_counter + FRAME_COUNTER_STORE_THRESHOLD) {
|
||||
ws_pae_nvm_store_frame_counter_tlv_create(controller->pae_nvm_buffer, index, key_hash, curr_frame_counter);
|
||||
ws_pae_controller_nvm_frame_counter_write(controller->pae_nvm_buffer);
|
||||
counter->index = index;
|
||||
counter->frame_counter = curr_frame_counter;
|
||||
memcpy(counter->hash, key_hash, GTK_HASH_LEN);
|
||||
counter->set = true;
|
||||
tr_debug("Stored frame counter: %"PRIu32", index %i, hash %s, system time: %"PRIu32"", curr_frame_counter, index, trace_array(key_hash, 8), protocol_core_monotonic_time / 10);
|
||||
for (uint8_t index = 0; index < GTK_NUM; index++) {
|
||||
memset(frame_counters->counter[index].gtk, 0, GTK_LEN);
|
||||
frame_counters->counter[index].frame_counter = 0;
|
||||
frame_counters->counter[index].set = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -702,7 +690,7 @@ int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr)
|
|||
}
|
||||
|
||||
// Stores frame counter
|
||||
ws_pae_controller_frame_counter_store(controller);
|
||||
ws_pae_controller_frame_counter_store(controller, false);
|
||||
|
||||
// Removes network keys from PAE controller and MAC
|
||||
ws_pae_controller_nw_keys_remove(interface_ptr);
|
||||
|
@ -965,7 +953,7 @@ int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[4])
|
||||
int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[GTK_NUM])
|
||||
{
|
||||
if (!gtk) {
|
||||
return -1;
|
||||
|
@ -989,6 +977,7 @@ int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[4])
|
|||
uint32_t lifetime = sec_prot_keys_gtk_install_order_last_lifetime_get(&controller->gtks);
|
||||
lifetime += controller->timer_settings.gtk_expire_offset;
|
||||
if (sec_prot_keys_gtk_set(&controller->gtks, i, gtk[i], lifetime) >= 0) {
|
||||
controller->gtks_set = true;
|
||||
tr_info("GTK set index: %i, lifetime %"PRIu32", system time: %"PRIu32"", i, lifetime, protocol_core_monotonic_time / 10);
|
||||
}
|
||||
}
|
||||
|
@ -1002,7 +991,7 @@ int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[4])
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_next_gtk_update(int8_t interface_id, uint8_t *gtk[4])
|
||||
int8_t ws_pae_controller_next_gtk_update(int8_t interface_id, uint8_t *gtk[GTK_NUM])
|
||||
{
|
||||
if (!gtk) {
|
||||
return -1;
|
||||
|
@ -1212,7 +1201,6 @@ void ws_pae_controller_slow_timer(uint16_t seconds)
|
|||
if (entry->pae_slow_timer) {
|
||||
entry->pae_slow_timer(seconds);
|
||||
}
|
||||
|
||||
ws_pae_controller_frame_counter_timer(seconds, entry);
|
||||
}
|
||||
}
|
||||
|
@ -1223,26 +1211,63 @@ static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controll
|
|||
entry->frame_cnt_store_timer -= seconds;
|
||||
} else {
|
||||
entry->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL;
|
||||
ws_pae_controller_frame_counter_store(entry);
|
||||
ws_pae_controller_frame_counter_store(entry, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_pae_controller_frame_counter_store(pae_controller_t *entry)
|
||||
static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry)
|
||||
{
|
||||
// Gets index of active GTK
|
||||
int8_t active_index = entry->gtk_index;
|
||||
|
||||
if (active_index >= 0) {
|
||||
// Gets hash of the key
|
||||
uint8_t *hash = entry->nw_key[active_index].hash;
|
||||
|
||||
uint32_t curr_frame_counter;
|
||||
entry->nw_frame_counter_read(entry->interface_ptr, &curr_frame_counter);
|
||||
ws_pae_controller_frame_counter_write(entry, active_index, hash, curr_frame_counter);
|
||||
if (entry->frame_cnt_store_timer > seconds) {
|
||||
entry->frame_cnt_store_timer = seconds;
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t ws_pae_controller_nvm_frame_counter_read(uint8_t *index, uint8_t *hash, uint32_t *frame_counter)
|
||||
static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool use_threshold)
|
||||
{
|
||||
bool update_needed = false;
|
||||
|
||||
for (int i = 0; i < GTK_NUM; i++) {
|
||||
/* If network key is set, checks if frame counter needs to be updated to NVM
|
||||
* Note! The frame counters for non-installed keys (previous frame counters) are not changed.
|
||||
* This is because GTKs are removed e.g. if PAN configuration is not heard/cannot be
|
||||
* de-crypted during a bootstrap. If BR later installs previous keys using 4WH/GKH, the
|
||||
* frame counters will be still valid.
|
||||
*/
|
||||
if (entry->nw_key[i].installed) {
|
||||
// Reads frame counter for the key
|
||||
uint32_t curr_frame_counter;
|
||||
entry->nw_frame_counter_read(entry->interface_ptr, &curr_frame_counter, i);
|
||||
|
||||
// If frame counter for the network key has already been stored
|
||||
if (entry->frame_counters.counter[i].set &&
|
||||
memcmp(entry->nw_key[i].gtk, entry->frame_counters.counter[i].gtk, GTK_LEN) == 0) {
|
||||
// If threshold check is disabled or frame counter has advanced for the threshold value, stores the new value
|
||||
if (!use_threshold ||
|
||||
curr_frame_counter > entry->frame_counters.counter[i].frame_counter + FRAME_COUNTER_STORE_THRESHOLD) {
|
||||
entry->frame_counters.counter[i].frame_counter = curr_frame_counter;
|
||||
update_needed = true;
|
||||
tr_debug("Stored updated frame counter: index %i value %"PRIu32"", i, curr_frame_counter);
|
||||
}
|
||||
} else {
|
||||
// For new or modified network keys, stores the frame counter value
|
||||
entry->frame_counters.counter[i].set = true;
|
||||
memcpy(entry->frame_counters.counter[i].gtk, entry->nw_key[i].gtk, GTK_LEN);
|
||||
entry->frame_counters.counter[i].frame_counter = curr_frame_counter;
|
||||
update_needed = true;
|
||||
tr_debug("Stored new frame counter: index %i value %"PRIu32"", i, curr_frame_counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (update_needed) {
|
||||
tr_debug("Write frame counters: system time %"PRIu32"", protocol_core_monotonic_time / 10);
|
||||
// Writes modified frame counters
|
||||
ws_pae_nvm_store_frame_counter_tlv_create(entry->pae_nvm_buffer, &entry->frame_counters);
|
||||
ws_pae_controller_nvm_frame_counter_write(entry->pae_nvm_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t ws_pae_controller_nvm_frame_counter_read(frame_counters_t *counters)
|
||||
{
|
||||
nvm_tlv_list_t tlv_list;
|
||||
ns_list_init(&tlv_list);
|
||||
|
@ -1253,7 +1278,7 @@ static int8_t ws_pae_controller_nvm_frame_counter_read(uint8_t *index, uint8_t *
|
|||
|
||||
int8_t result = -1;
|
||||
ns_list_foreach_safe(nvm_tlv_entry_t, entry, &tlv_list) {
|
||||
if (ws_pae_nvm_store_frame_counter_tlv_read(entry, index, hash, frame_counter) >= 0) {
|
||||
if (ws_pae_nvm_store_frame_counter_tlv_read(entry, counters) >= 0) {
|
||||
result = 0;
|
||||
}
|
||||
ns_list_remove(&tlv_list, entry);
|
||||
|
|
|
@ -20,7 +20,15 @@
|
|||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
typedef enum {
|
||||
AUTH_RESULT_OK = 0, // Successful
|
||||
AUTH_RESULT_ERR_NO_MEM = -1, // No memory
|
||||
AUTH_RESULT_ERR_TX_NO_ACK = -2, // No acknowledge was received
|
||||
AUTH_RESULT_ERR_UNSPEC = -3 // Other reason
|
||||
} auth_result_e;
|
||||
|
||||
struct nvm_tlv_entry;
|
||||
|
||||
/**
|
||||
* ws_pae_controller_set_target sets EAPOL target for PAE supplicant
|
||||
*
|
||||
|
@ -467,9 +475,10 @@ typedef void ws_pae_controller_nw_send_key_index_set(protocol_interface_info_ent
|
|||
*
|
||||
* \param interface_ptr interface
|
||||
* \param counter frame counter
|
||||
* \param slot key slot (MAC key descriptor), from 0 to 4
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_nw_frame_counter_set(protocol_interface_info_entry_t *interface_ptr, uint32_t counter);
|
||||
typedef void ws_pae_controller_nw_frame_counter_set(protocol_interface_info_entry_t *interface_ptr, uint32_t counter, uint8_t slot);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_nw_frame_counter_read network frame counter read callback
|
||||
|
@ -478,16 +487,17 @@ typedef void ws_pae_controller_nw_frame_counter_set(protocol_interface_info_entr
|
|||
* \param counter frame counter
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_nw_frame_counter_read(protocol_interface_info_entry_t *interface_ptr, uint32_t *counter);
|
||||
typedef void ws_pae_controller_nw_frame_counter_read(protocol_interface_info_entry_t *interface_ptr, uint32_t *counter, uint8_t slot);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_auth_completed authentication completed callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param success true if authentication was successful
|
||||
* \param result result, either ok or failure reason
|
||||
* \param target_eui_64 EAPOL target in case of failure or NULL
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_auth_completed(protocol_interface_info_entry_t *interface_ptr, bool success);
|
||||
typedef void ws_pae_controller_auth_completed(protocol_interface_info_entry_t *interface_ptr, auth_result_e result, uint8_t *target_eui_64);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_pan_ver_increment PAN version increment callback
|
||||
|
|
|
@ -93,6 +93,17 @@ kmp_api_t *ws_pae_lib_kmp_list_type_get(kmp_list_t *kmp_list, kmp_type_e type)
|
|||
return kmp;
|
||||
}
|
||||
|
||||
kmp_api_t *ws_pae_lib_kmp_list_instance_id_get(kmp_list_t *kmp_list, uint8_t instance_id)
|
||||
{
|
||||
ns_list_foreach(kmp_entry_t, cur, kmp_list) {
|
||||
if (kmp_api_instance_id_get(cur->kmp) == instance_id) {
|
||||
return cur->kmp;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ws_pae_lib_kmp_list_free(kmp_list_t *kmp_list)
|
||||
{
|
||||
ns_list_foreach_safe(kmp_entry_t, cur, kmp_list) {
|
||||
|
|
|
@ -88,7 +88,7 @@ int8_t ws_pae_lib_kmp_list_delete(kmp_list_t *kmp_list, kmp_api_t *kmp);
|
|||
void ws_pae_lib_kmp_list_free(kmp_list_t *kmp_list);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_kmp_list_type_get gets KMP entry from KMP list based on KMP type
|
||||
* ws_pae_lib_kmp_list_type_get gets KMP from KMP list based on KMP type
|
||||
*
|
||||
* \param kmp_list KMP list
|
||||
* \param type type
|
||||
|
@ -99,6 +99,18 @@ void ws_pae_lib_kmp_list_free(kmp_list_t *kmp_list);
|
|||
*/
|
||||
kmp_api_t *ws_pae_lib_kmp_list_type_get(kmp_list_t *kmp_list, kmp_type_e type);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_kmp_list_instance_id_get gets KMP from KMP list based on instance identifier
|
||||
*
|
||||
* \param kmp_list KMP list
|
||||
* \param instance_id instance identifier
|
||||
*
|
||||
* \return KMP on success
|
||||
* \return NULL on failure
|
||||
*
|
||||
*/
|
||||
kmp_api_t *ws_pae_lib_kmp_list_instance_id_get(kmp_list_t *kmp_list, uint8_t instance_id);
|
||||
|
||||
/**
|
||||
* ws_pae_lib_kmp_list_entry_get gets KMP entry from KMP list based on KMP
|
||||
*
|
||||
|
|
|
@ -43,8 +43,11 @@
|
|||
// PTK EUI-64 set (1) + PTK EUI-64 (8) + PMK set (1) + PMK (32) + PMK replay counter (8) + PTK set (1) + PTK (48)
|
||||
#define PAE_NVM_KEYS_LEN 1 + 8 + 1 + PMK_LEN + 8 + 1 + PTK_LEN
|
||||
|
||||
// GTK hash (8), frame counter (4), index (1)
|
||||
#define PAE_NVM_FRAME_COUNTER_LEN 8 + 4 + 1
|
||||
// (frame counter set (1) + GTK (16) + frame counter (4)) * 4
|
||||
#define PAE_NVM_FRAME_COUNTER_LEN (1 + GTK_LEN + 4) * GTK_NUM
|
||||
|
||||
#define PAE_NVM_FIELD_NOT_SET 0 // Field is not present
|
||||
#define PAE_NVM_FIELD_SET 1 // Field is present
|
||||
|
||||
nvm_tlv_entry_t *ws_pae_buffer_allocate(void)
|
||||
{
|
||||
|
@ -68,7 +71,7 @@ void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pa
|
|||
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (sec_prot_keys_gtk_is_set(gtks, i)) {
|
||||
*tlv++ = 1; // GTK is set
|
||||
*tlv++ = PAE_NVM_FIELD_SET; // GTK is set
|
||||
uint32_t lifetime = sec_prot_keys_gtk_lifetime_get(gtks, i);
|
||||
tlv = common_write_32_bit(lifetime, tlv);
|
||||
|
||||
|
@ -76,7 +79,7 @@ void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pa
|
|||
memcpy(tlv, gtk, GTK_LEN);
|
||||
tlv += GTK_LEN;
|
||||
} else {
|
||||
*tlv++ = 0; // GTK is not set
|
||||
*tlv++ = PAE_NVM_FIELD_NOT_SET; // GTK is not set
|
||||
memset(tlv, 0, 4 + GTK_LEN);
|
||||
tlv += 4 + GTK_LEN;
|
||||
}
|
||||
|
@ -106,7 +109,7 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_entry_t *tlv_entry, uint16_t *p
|
|||
tlv += 33;
|
||||
|
||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||
if (*tlv++ == 1) { /* GTK is set */
|
||||
if (*tlv++ == PAE_NVM_FIELD_SET) { /* GTK is set */
|
||||
uint32_t lifetime = common_read_32_bit(tlv);
|
||||
tlv += 4;
|
||||
sec_prot_keys_gtk_set(gtks, i, tlv, lifetime);
|
||||
|
@ -131,20 +134,20 @@ void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
|
|||
|
||||
uint8_t *eui_64 = sec_prot_keys_ptk_eui_64_get(sec_keys);
|
||||
if (eui_64) {
|
||||
*tlv++ = 1;
|
||||
*tlv++ = PAE_NVM_FIELD_SET;
|
||||
memcpy(tlv, eui_64, 8);
|
||||
} else {
|
||||
*tlv++ = 0;
|
||||
*tlv++ = PAE_NVM_FIELD_NOT_SET;
|
||||
memset(tlv, 0, 8);
|
||||
}
|
||||
tlv += 8;
|
||||
|
||||
uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys);
|
||||
if (pmk) {
|
||||
*tlv++ = 1;
|
||||
*tlv++ = PAE_NVM_FIELD_SET;
|
||||
memcpy(tlv, pmk, PMK_LEN);
|
||||
} else {
|
||||
*tlv++ = 0;
|
||||
*tlv++ = PAE_NVM_FIELD_NOT_SET;
|
||||
memset(tlv, 0, PMK_LEN);
|
||||
}
|
||||
tlv += PMK_LEN;
|
||||
|
@ -154,10 +157,10 @@ void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
|
|||
|
||||
uint8_t *ptk = sec_prot_keys_ptk_get(sec_keys);
|
||||
if (ptk) {
|
||||
*tlv++ = 1;
|
||||
*tlv++ = PAE_NVM_FIELD_SET;
|
||||
memcpy(tlv, ptk, PTK_LEN);
|
||||
} else {
|
||||
*tlv++ = 0;
|
||||
*tlv++ = PAE_NVM_FIELD_NOT_SET;
|
||||
memset(tlv, 0, PTK_LEN);
|
||||
}
|
||||
tlv += PTK_LEN;
|
||||
|
@ -179,13 +182,13 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
|
|||
uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
|
||||
|
||||
// EUI-64 set */
|
||||
if (*tlv++ == 1) {
|
||||
if (*tlv++ == PAE_NVM_FIELD_SET) {
|
||||
sec_prot_keys_ptk_eui_64_write(sec_keys, tlv);
|
||||
}
|
||||
tlv += 8;
|
||||
|
||||
// PMK set
|
||||
if (*tlv++ == 1) {
|
||||
if (*tlv++ == PAE_NVM_FIELD_SET) {
|
||||
sec_prot_keys_pmk_write(sec_keys, tlv);
|
||||
}
|
||||
tlv += PMK_LEN;
|
||||
|
@ -195,7 +198,7 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
|
|||
sec_prot_keys_pmk_replay_cnt_set(sec_keys, counter);
|
||||
|
||||
// PTK set
|
||||
if (*tlv++ == 1) {
|
||||
if (*tlv++ == PAE_NVM_FIELD_SET) {
|
||||
sec_prot_keys_ptk_write(sec_keys, tlv);
|
||||
}
|
||||
|
||||
|
@ -208,25 +211,32 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_entry_t *tlv_entry, uint8_t index, uint8_t *hash, uint32_t frame_counter)
|
||||
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_entry_t *tlv_entry, frame_counters_t *counters)
|
||||
{
|
||||
|
||||
tlv_entry->tag = PAE_NVM_FRAME_COUNTER_TAG;
|
||||
tlv_entry->len = PAE_NVM_FRAME_COUNTER_LEN;
|
||||
|
||||
uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
|
||||
|
||||
memcpy(tlv, hash, GTK_HASH_LEN);
|
||||
tlv += GTK_HASH_LEN;
|
||||
tlv = common_write_32_bit(frame_counter, tlv);
|
||||
*tlv = index;
|
||||
for (uint8_t index = 0; index < GTK_NUM; index++) {
|
||||
if (!counters->counter[index].set) {
|
||||
*tlv++ = PAE_NVM_FIELD_NOT_SET;
|
||||
memset(tlv, 0, GTK_LEN + 4);
|
||||
tlv += GTK_LEN + 4;
|
||||
continue;
|
||||
}
|
||||
*tlv++ = PAE_NVM_FIELD_SET;
|
||||
memcpy(tlv, counters->counter[index].gtk, GTK_LEN);
|
||||
tlv += GTK_LEN;
|
||||
tlv = common_write_32_bit(counters->counter[index].frame_counter, tlv);
|
||||
}
|
||||
|
||||
tr_debug("NVM FRAME COUNTER write");
|
||||
}
|
||||
|
||||
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, uint8_t *index, uint8_t *hash, uint32_t *frame_counter)
|
||||
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, frame_counters_t *counters)
|
||||
{
|
||||
if (!tlv_entry || !frame_counter) {
|
||||
if (!tlv_entry || !counters) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -236,11 +246,20 @@ int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, uint8
|
|||
|
||||
uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
|
||||
|
||||
memcpy(hash, tlv, GTK_HASH_LEN);
|
||||
tlv += GTK_HASH_LEN;
|
||||
*frame_counter = common_read_32_bit(tlv);
|
||||
tlv += 4;
|
||||
*index = *tlv;
|
||||
for (uint8_t index = 0; index < GTK_NUM; index++) {
|
||||
// Frame counter not set
|
||||
if (*tlv++ == PAE_NVM_FIELD_NOT_SET) {
|
||||
counters->counter[index].set = false;
|
||||
tlv += GTK_LEN + 4;
|
||||
continue;
|
||||
}
|
||||
// Frame counter is set, read GTK key and counter values
|
||||
counters->counter[index].set = true;
|
||||
memcpy(counters->counter[index].gtk, tlv, GTK_LEN);
|
||||
tlv += GTK_LEN;
|
||||
counters->counter[index].frame_counter = common_read_32_bit(tlv);
|
||||
tlv += 4;
|
||||
}
|
||||
|
||||
tr_debug("NVM FRAME COUNTER read");
|
||||
|
||||
|
|
|
@ -76,27 +76,22 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_
|
|||
* ws_pae_nvm_store_frame_counter_tlv_create create NVM frame counter TLV
|
||||
*
|
||||
* \param tlv_entry TLV entry buffer pointer
|
||||
* \param index index
|
||||
* \param hash hash
|
||||
* \param frame_counter frame counter
|
||||
*
|
||||
* \param counters frame counters
|
||||
*
|
||||
*/
|
||||
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_entry_t *tlv_entry, uint8_t index, uint8_t *hash, uint32_t frame_counter);
|
||||
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_entry_t *tlv_entry, frame_counters_t *counters);
|
||||
|
||||
/**
|
||||
* ws_pae_nvm_store_frame_counter_tlv_read read from NVM frame counter TLV
|
||||
*
|
||||
* \param tlv_entry TLV entry
|
||||
* \param index index
|
||||
* \param hash hash
|
||||
* \param frame_counter frame counter
|
||||
* \param counters frame counters
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, uint8_t *index, uint8_t *hash, uint32_t *frame_counter);
|
||||
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, frame_counters_t *counters);
|
||||
|
||||
nvm_tlv_entry_t *ws_pae_buffer_allocate(void);
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ typedef struct {
|
|||
timer_settings_t *timer_settings; /**< Timer settings */
|
||||
uint8_t nw_keys_used_cnt; /**< How many times bootstrap has been tried with current keys */
|
||||
bool auth_trickle_running : 1; /**< Initial EAPOL-Key Trickle timer running */
|
||||
bool auth_requested : 1; /**< Authentication has been requested */
|
||||
bool auth_requested : 1; /**< Authentication has been requested by the bootstrap */
|
||||
bool timer_running : 1; /**< Timer is running */
|
||||
bool new_br_eui_64_set : 1; /**< Border router address has been set */
|
||||
bool new_br_eui_64_fresh : 1; /**< Border router address is fresh (set during this authentication attempt) */
|
||||
|
@ -117,7 +117,7 @@ static trickle_params_t initial_eapol_key_trickle_params = {
|
|||
};
|
||||
|
||||
static void ws_pae_supp_free(pae_supp_t *pae_supp);
|
||||
static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, bool success);
|
||||
static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, auth_result_e result);
|
||||
static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp);
|
||||
static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp);
|
||||
static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id);
|
||||
|
@ -134,6 +134,7 @@ static bool ws_pae_supp_timer_running(pae_supp_t *pae_supp);
|
|||
static void ws_pae_supp_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr);
|
||||
static kmp_api_t *ws_pae_supp_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type);
|
||||
static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr);
|
||||
static kmp_api_t *ws_pae_supp_kmp_tx_status_ind(kmp_service_t *service, uint8_t instance_id);
|
||||
static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp);
|
||||
static int8_t ws_pae_supp_eapol_pdu_address_check(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
|
||||
static int8_t ws_pae_supp_parent_eui_64_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64);
|
||||
|
@ -143,6 +144,7 @@ static void ws_pae_supp_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e typ
|
|||
static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
|
||||
static void ws_pae_supp_kmp_api_finished(kmp_api_t *kmp);
|
||||
|
||||
|
||||
static const eapol_pdu_recv_cb_data_t eapol_pdu_recv_cb_data = {
|
||||
.priority = EAPOL_PDU_RECV_HIGH_PRIORITY,
|
||||
.addr_check = ws_pae_supp_eapol_pdu_address_check,
|
||||
|
@ -179,7 +181,7 @@ int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr,
|
|||
}
|
||||
|
||||
if (ws_pae_supp_nw_keys_valid_check(pae_supp, dest_pan_id) >= 0) {
|
||||
pae_supp->auth_completed(interface_ptr, true);
|
||||
pae_supp->auth_completed(interface_ptr, AUTH_RESULT_OK, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -354,6 +356,18 @@ int8_t ws_pae_supp_nw_key_index_update(protocol_interface_info_entry_t *interfac
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_supp_gtks_set(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
|
||||
if (!pae_supp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_supp->gtks = *gtks;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_supp_eapol_target_remove(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
|
||||
|
@ -381,8 +395,6 @@ static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp)
|
|||
ws_pae_supp_nvm_keys_write(pae_supp);
|
||||
sec_prot_keys_updated_reset(&pae_supp->entry.sec_keys);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int8_t ws_pae_supp_nvm_nw_info_write(pae_supp_t *pae_supp)
|
||||
|
@ -457,12 +469,16 @@ static int8_t ws_pae_supp_nvm_keys_read(pae_supp_t *pae_supp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, bool success)
|
||||
static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, auth_result_e result)
|
||||
{
|
||||
pae_supp->auth_trickle_running = false;
|
||||
if (pae_supp->auth_requested && pae_supp->auth_completed) {
|
||||
pae_supp->auth_requested = false;
|
||||
pae_supp->auth_completed(pae_supp->interface_ptr, success);
|
||||
uint8_t *target_eui_64 = NULL;
|
||||
if (result != AUTH_RESULT_OK) {
|
||||
target_eui_64 = pae_supp->target_addr.eui_64;
|
||||
}
|
||||
pae_supp->auth_completed(pae_supp->interface_ptr, result, target_eui_64);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,7 +621,7 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (kmp_service_cb_register(pae_supp->kmp_service, ws_pae_supp_kmp_incoming_ind, ws_pae_supp_kmp_service_addr_get, ws_pae_supp_kmp_service_api_get) < 0) {
|
||||
if (kmp_service_cb_register(pae_supp->kmp_service, ws_pae_supp_kmp_incoming_ind, ws_pae_supp_kmp_tx_status_ind, ws_pae_supp_kmp_service_addr_get, ws_pae_supp_kmp_service_api_get) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -625,7 +641,7 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (key_sec_prot_register(pae_supp->kmp_service) < 0) {
|
||||
if (supp_key_sec_prot_register(pae_supp->kmp_service) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -788,7 +804,7 @@ void ws_pae_supp_fast_timer(uint16_t ticks)
|
|||
if (!pae_supp->initial_key_timer && !pae_supp->auth_trickle_running && !running) {
|
||||
tr_debug("PAE idle");
|
||||
// If not already completed, restart bootstrap
|
||||
ws_pae_supp_authenticate_response(pae_supp, false);
|
||||
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
|
||||
|
||||
ws_pae_supp_timer_stop(pae_supp);
|
||||
}
|
||||
|
@ -808,7 +824,7 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
|
|||
}
|
||||
// Maximum number of trickle expires, authentication fails
|
||||
if (!trickle_running(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params)) {
|
||||
ws_pae_supp_authenticate_response(pae_supp, false);
|
||||
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1087,7 +1103,7 @@ static void ws_pae_supp_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e resu
|
|||
|
||||
// KMP-CREATE.request has failed, authentication error
|
||||
if (result != KMP_RESULT_OK) {
|
||||
ws_pae_supp_authenticate_response(pae_supp, false);
|
||||
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1115,14 +1131,24 @@ static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
|
|||
ws_pae_lib_supp_timer_ticks_set(&pae_supp->entry, WAIT_FOR_AUTHENTICATION_TICKS);
|
||||
}
|
||||
|
||||
/* When 4WH or GKH completes inserts keys and indicates authentication completed
|
||||
(if not alredy indicated) */
|
||||
if ((type == IEEE_802_11_4WH || type == IEEE_802_11_GKH) && result == KMP_RESULT_OK) {
|
||||
if (sec_keys) {
|
||||
sec_prot_keys_t *keys = sec_keys;
|
||||
pae_supp->nw_key_insert(pae_supp->interface_ptr, keys->gtks);
|
||||
}
|
||||
|
||||
ws_pae_supp_authenticate_response(pae_supp, true);
|
||||
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_OK);
|
||||
}
|
||||
|
||||
/* If initial EAPOL-key message sending fails to tx no acknowledge, indicates failure so
|
||||
that bootstrap can decide if EAPOL target should be changed */
|
||||
else if (type > IEEE_802_1X_INITIAL_KEY && result == KMP_RESULT_ERR_TX_NO_ACK) {
|
||||
tr_info("Initial EAPOL-Key TX failure, target: %s", trace_array(kmp_address_eui_64_get(&pae_supp->entry.addr), 8));
|
||||
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_TX_NO_ACK);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void ws_pae_supp_kmp_api_finished(kmp_api_t *kmp)
|
||||
|
@ -1137,6 +1163,21 @@ static void ws_pae_supp_kmp_api_finished(kmp_api_t *kmp)
|
|||
ws_pae_lib_kmp_list_delete(&pae_supp->entry.kmp_list, kmp);
|
||||
}
|
||||
|
||||
static kmp_api_t *ws_pae_supp_kmp_tx_status_ind(kmp_service_t *service, uint8_t instance_id)
|
||||
{
|
||||
pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
|
||||
if (!pae_supp) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kmp_api_t *kmp = ws_pae_lib_kmp_list_instance_id_get(&pae_supp->entry.kmp_list, instance_id);
|
||||
if (!kmp) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return kmp;
|
||||
}
|
||||
|
||||
#endif /* HAVE_PAE_SUPP */
|
||||
#endif /* HAVE_WS */
|
||||
|
||||
|
|
|
@ -182,6 +182,18 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt
|
|||
*/
|
||||
int8_t ws_pae_supp_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_gtks_set set supplicant GTKs
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param gtks GTKs
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_supp_gtks_set(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_eapol_target_remove remove EAPOL target set using authentication start
|
||||
*
|
||||
|
@ -206,10 +218,11 @@ typedef void ws_pae_supp_nw_key_index_set(protocol_interface_info_entry_t *inter
|
|||
* ws_pae_supp_auth_completed authentication completed callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param success true if authentication was successful
|
||||
* \param result result, either ok or failure reason
|
||||
* \param target_eui_64 EAPOL target in case of failure or NULL
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_supp_auth_completed(protocol_interface_info_entry_t *interface_ptr, bool success);
|
||||
typedef void ws_pae_supp_auth_completed(protocol_interface_info_entry_t *interface_ptr, auth_result_e result, uint8_t *target_eui_64);
|
||||
|
||||
/**
|
||||
* ws_pae_supp_nw_key_insert network key insert callback
|
||||
|
@ -249,6 +262,7 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
|
|||
#define ws_pae_supp_border_router_addr_read NULL
|
||||
#define ws_pae_supp_gtk_hash_update NULL
|
||||
#define ws_pae_supp_nw_key_index_update NULL
|
||||
#define ws_pae_supp_gtks_set(interface_ptr, gtks)
|
||||
#define ws_pae_supp_eapol_target_remove(interface_ptr)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -356,7 +356,7 @@ static void icmpv6_na_wisun_aro_handler(protocol_interface_info_entry_t *cur_int
|
|||
|
||||
(void)life_time;
|
||||
if (nd_status != ARO_SUCCESS) {
|
||||
ws_common_aro_failure(cur_interface, src_addr);
|
||||
ws_common_aro_failure(cur_interface, src_addr, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1389,7 +1389,7 @@ static void icmpv6_aro_cb(buffer_t *buf, uint8_t status)
|
|||
}
|
||||
rpl_control_address_register_done(buf->interface, ll_address, status);
|
||||
if (status != SOCKET_TX_DONE) {
|
||||
ws_common_aro_failure(buf->interface, ll_address);
|
||||
ws_common_aro_failure(buf->interface, ll_address, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,11 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r
|
|||
dhcpv6_alloacted_address_entry_t *dhcp_allocated_address;
|
||||
dhcpv6_ia_non_temporal_address_s nonTemporalAddress;
|
||||
bool address_allocated = false;
|
||||
dhcp_allocated_address = libdhcpv6_address_allocated_list_scan(serverBase, replyPacket->clientDUID.linkID, replyPacket->clientDUID.linkType, dhcp_ia_non_temporal_params->iaId, dhcp_ia_non_temporal_params->T0, dhcp_ia_non_temporal_params->T1, allocateNew);
|
||||
//Validate Client DUID
|
||||
dhcp_link_options_params_t clientDUID;
|
||||
if (libdhcpv6_get_link_address_from_duid(replyPacket->clientDUID.duid, replyPacket->clientDUID.duid_length, replyPacket->clientDUID.type, &clientDUID) == 0) {
|
||||
dhcp_allocated_address = libdhcpv6_address_allocated_list_scan(serverBase, clientDUID.link_id, clientDUID.link_type, dhcp_ia_non_temporal_params->iaId, dhcp_ia_non_temporal_params->T0, dhcp_ia_non_temporal_params->T1, allocateNew);
|
||||
}
|
||||
if (dhcp_allocated_address) {
|
||||
address_allocated = true;
|
||||
nonTemporalAddress.requestedAddress = dhcp_allocated_address->nonTemporalAddress;
|
||||
|
@ -110,7 +114,7 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r
|
|||
}
|
||||
}
|
||||
|
||||
response->responseLength = libdhcpv6_address_reply_message_len(replyPacket->clientDUID.linkType, replyPacket->serverDUID.linkType, 0, replyPacket->rapidCommit, address_allocated);
|
||||
response->responseLength = libdhcpv6_address_reply_message_len(replyPacket->clientDUID.duid_length, replyPacket->serverDUID.duid_length, 0, replyPacket->rapidCommit, address_allocated);
|
||||
response->responsePtr = ns_dyn_mem_temporary_alloc(response->responseLength);
|
||||
if (response->responsePtr) {
|
||||
if (address_allocated) {
|
||||
|
@ -141,16 +145,13 @@ int DHCPV6_server_service_request_handler(uint16_t instance_id, uint32_t msg_tr_
|
|||
if (serverBase) {
|
||||
//Here Allocate address
|
||||
replyPacket.rapidCommit = libdhcpv6_rapid_commit_option_at_packet(msg_ptr, msg_len);
|
||||
replyPacket.serverDUID.linkID = serverBase->serverDUID;
|
||||
replyPacket.serverDUID.linkType = serverBase->serverLinkType;
|
||||
replyPacket.serverDUID = serverBase->serverDUID;
|
||||
replyPacket.T0 = dhcp_ia_non_temporal_params.T0;
|
||||
replyPacket.T1 = dhcp_ia_non_temporal_params.T1;
|
||||
replyPacket.iaId = dhcp_ia_non_temporal_params.iaId;
|
||||
replyPacket.transaction_ID = msg_tr_id;
|
||||
|
||||
uint16_t duid_length = libdhcpv6_duid_option_size(replyPacket.clientDUID.linkType);
|
||||
duid_length -= 8;
|
||||
tr_debug("Response dhcp sol %s clientDUID", trace_array(replyPacket.clientDUID.linkID, duid_length));
|
||||
tr_debug("Response dhcp sol %s clientDUID", trace_array(replyPacket.clientDUID.duid, replyPacket.clientDUID.duid_length));
|
||||
|
||||
//Check First Current list
|
||||
if (DHCPv6_server_respond_client(serverBase, &replyPacket, &dhcp_ia_non_temporal_params, &responseBuf, true) == 0) {
|
||||
|
@ -173,10 +174,7 @@ int DHCPV6_server_service_request_handler(uint16_t instance_id, uint32_t msg_tr_
|
|||
// Discover SERVER
|
||||
serverBase = libdhcpv6_server_data_get_by_prefix_and_socketinstance(instance_id, dhcp_ia_non_temporal_params.nonTemporalAddress);
|
||||
if (serverBase) {
|
||||
dhcp_link_options_params_t serverInfoDui;
|
||||
serverInfoDui.linkID = serverBase->serverDUID;
|
||||
serverInfoDui.linkType = serverBase->serverLinkType;
|
||||
if (libdhcpv6_compare_DUID(&serverInfoDui, &replyPacket.serverDUID) == 0) {
|
||||
if (libdhcpv6_compare_DUID(&serverBase->serverDUID, &replyPacket.serverDUID) == 0) {
|
||||
replyPacket.rapidCommit = libdhcpv6_rapid_commit_option_at_packet(msg_ptr, msg_len);
|
||||
replyPacket.T0 = dhcp_ia_non_temporal_params.T0;
|
||||
replyPacket.T1 = dhcp_ia_non_temporal_params.T1;
|
||||
|
@ -339,6 +337,25 @@ void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[stat
|
|||
serverInfo->removeCb = remove_cb;
|
||||
}
|
||||
|
||||
|
||||
int DHCPv6_server_service_duid_update(int8_t interface, uint8_t guaPrefix[static 16], uint8_t *duid_ptr, uint16_t duid_type, uint8_t duid_length)
|
||||
{
|
||||
|
||||
//Validate length and type
|
||||
if (!libdhcpv6_duid_length_validate(duid_type, duid_length)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
|
||||
if (!serverInfo) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return libdhcpv6_server_duid_set(serverInfo, duid_ptr, duid_type, duid_length);
|
||||
}
|
||||
|
||||
|
||||
/* SET max accepted clients to server, Default is 200
|
||||
*
|
||||
*
|
||||
|
|
|
@ -45,6 +45,7 @@ int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], u
|
|||
|
||||
void DHCPv6_server_service_callback_set(int8_t interface, uint8_t guaPrefix[static 16], dhcp_address_prefer_remove_cb *remove_cb, dhcp_address_add_notify_cb *add_cb);
|
||||
|
||||
int DHCPv6_server_service_duid_update(int8_t interface, uint8_t guaPrefix[static 16], uint8_t *duid_ptr, uint16_t duid_type, uint8_t duid_length);
|
||||
|
||||
/* Delete dhcp thread dhcp router ID server.
|
||||
*
|
||||
|
|
|
@ -32,9 +32,10 @@
|
|||
* 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);
|
||||
void dhcp_client_init(int8_t interface, uint16_t link_type);
|
||||
|
||||
/* Set configurations for DHCP client
|
||||
*
|
||||
|
@ -72,15 +73,13 @@ void dhcp_client_delete(int8_t interface);
|
|||
* /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 mac64 64 bit mac address for identifieng client.
|
||||
* /param link_type Link hardware type.
|
||||
* /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], uint8_t mac64[static 8], uint16_t link_type, dhcp_client_global_adress_cb *error_cb);
|
||||
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
|
||||
*
|
||||
|
|
|
@ -39,57 +39,128 @@ typedef struct {
|
|||
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 dhcp_client_class_t dhcp_client;
|
||||
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);
|
||||
|
||||
|
||||
void dhcp_client_init(int8_t interface)
|
||||
{
|
||||
// No support for multible instances yet.
|
||||
dhcp_client.service_instance = dhcp_service_init(interface, DHCP_INSTANCE_CLIENT, NULL);
|
||||
dhcp_client.interface = interface;
|
||||
dhcp_client.libDhcp_instance = libdhcpv6_nonTemporal_entry_get_unique_instance_id();
|
||||
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;
|
||||
|
||||
return;
|
||||
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.
|
||||
(void)interface;
|
||||
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;
|
||||
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.
|
||||
(void)interface;
|
||||
dhcp_client.sol_timeout = timeout;
|
||||
dhcp_client.sol_max_rt = max_rt;
|
||||
dhcp_client.sol_max_rc = max_rc;
|
||||
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.relay_instance = dhcp_service_init(interface, DHCP_INTANCE_RELAY_AGENT, NULL);
|
||||
dhcp_service_relay_instance_enable(dhcp_client.relay_instance, border_router_address);
|
||||
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)
|
||||
|
@ -97,7 +168,13 @@ 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_service_delete(dhcp_client.service_instance);
|
||||
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);
|
||||
|
@ -107,7 +184,7 @@ void dhcp_client_delete(int8_t interface)
|
|||
}
|
||||
|
||||
do {
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client.libDhcp_instance);
|
||||
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);
|
||||
|
@ -117,7 +194,7 @@ void dhcp_client_delete(int8_t interface)
|
|||
|
||||
}
|
||||
} while (srv_data_ptr != NULL);
|
||||
dhcp_client.service_instance = 0;
|
||||
dhcp_client->service_instance = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -125,10 +202,14 @@ void dhcp_client_delete(int8_t interface)
|
|||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,9 +219,8 @@ void dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr)
|
|||
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_link_options_params_t clientId;
|
||||
dhcp_link_options_params_t serverId;
|
||||
dhcp_link_options_params_t interfaceId;
|
||||
dhcp_duid_options_params_t clientId;
|
||||
dhcp_duid_options_params_t serverId;
|
||||
dhcpv6_client_server_data_t *srv_data_ptr = NULL;
|
||||
(void)instance_id;
|
||||
|
||||
|
@ -153,6 +233,13 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
|
|||
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;
|
||||
|
||||
|
@ -178,16 +265,33 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
|
|||
goto error_exit;
|
||||
}
|
||||
|
||||
interfaceId.linkID = srv_data_ptr->clientId;
|
||||
interfaceId.linkType = srv_data_ptr->clientLinkIdType;
|
||||
if (libdhcpv6_compare_DUID(&interfaceId, &clientId) != 0) {
|
||||
if (libdhcpv6_compare_DUID(&srv_data_ptr->clientDUID, &clientId) != 0) {
|
||||
tr_error("Not Valid Client Id");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (dhcp_client.one_instance_interface && memcmp(srv_data_ptr->iaNontemporalAddress.addressPrefix, dhcp_ia_non_temporal_params.nonTemporalAddress, 16)) {
|
||||
//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;
|
||||
}
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(dhcp_client.interface);
|
||||
//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);
|
||||
}
|
||||
|
@ -196,17 +300,15 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
|
|||
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;
|
||||
memcpy(srv_data_ptr->serverLinkId, serverId.linkID, 8);
|
||||
srv_data_ptr->serverLinkType = serverId.linkType;
|
||||
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);
|
||||
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);
|
||||
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:
|
||||
|
@ -214,7 +316,7 @@ error_exit:
|
|||
return RET_MSG_ACCEPTED;
|
||||
}
|
||||
|
||||
int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], uint8_t mac64[static 8], uint16_t link_type, dhcp_client_global_adress_cb *error_cb)
|
||||
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};
|
||||
|
||||
|
@ -222,53 +324,67 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
|
|||
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 (mac64 == NULL || dhcp_addr == NULL) {
|
||||
if (dhcp_addr == NULL || !dhcp_client) {
|
||||
tr_error("Invalid parameters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!prefix || dhcp_client.one_instance_interface) {
|
||||
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);
|
||||
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 (dhcp_client->one_instance_interface && prefix) {
|
||||
if (srv_data_ptr->iaNonTemporalStructValid) {
|
||||
if (memcmp(srv_data_ptr->iaNontemporalAddress.addressPrefix, prefix, 8)) {
|
||||
//Request new address direct from Server if prefix is new
|
||||
srv_data_ptr->iaNonTemporalStructValid = false;
|
||||
dhcpv6_renew(protocol_stack_interface_info_get_by_id(interface), NULL, ADDR_CALLBACK_TIMER);
|
||||
if (memcmp(srv_data_ptr->iaNontemporalAddress.addressPrefix, prefix, 8) == 0) {
|
||||
return 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, mac64, link_type, prefix, dhcp_addr);
|
||||
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) {
|
||||
if (!prefix || dhcp_client->no_address_hint) {
|
||||
add_prefix = false;
|
||||
} else {
|
||||
add_prefix = prefix != NULL;
|
||||
}
|
||||
|
||||
payload_len = libdhcpv6_solication_message_length(link_type, add_prefix, 0);
|
||||
payload_len = libdhcpv6_solication_message_length(srv_data_ptr->clientDUID.duid_length, add_prefix, 0);
|
||||
|
||||
|
||||
payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
|
||||
|
@ -278,17 +394,16 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
|
|||
return -1;
|
||||
}
|
||||
|
||||
dhcp_client.global_address_cb = error_cb; //TODO Only supporting one instance globaly if we need more for different instances needs code.
|
||||
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.linkID = mac64;
|
||||
solPacket.clientDUID.linkType = link_type;
|
||||
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) {
|
||||
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);
|
||||
|
@ -297,16 +412,16 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
|
|||
}
|
||||
|
||||
// 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);
|
||||
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) {
|
||||
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);
|
||||
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;
|
||||
|
@ -314,17 +429,18 @@ int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16
|
|||
|
||||
int dhcp_client_server_address_update(int8_t interface, uint8_t *prefix, uint8_t server_address[static 16])
|
||||
{
|
||||
dhcpv6_client_server_data_t *srv_data_ptr = NULL;
|
||||
|
||||
if (dhcp_client.interface != interface) {
|
||||
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);
|
||||
} 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;
|
||||
|
@ -353,17 +469,19 @@ void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uin
|
|||
{
|
||||
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) {
|
||||
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) {
|
||||
if (dhcp_client->one_instance_interface) {
|
||||
addr_deprecate(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
} else {
|
||||
addr_delete(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
|
||||
|
@ -375,14 +493,18 @@ void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uin
|
|||
void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t *addr, if_address_callback_t reason)
|
||||
{
|
||||
|
||||
dhcp_link_options_params_t serverLink;
|
||||
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);
|
||||
srv_data_ptr = libdhcpv6_nonTemporal_entry_get_by_instance(dhcp_client->libDhcp_instance);
|
||||
}
|
||||
|
||||
if (srv_data_ptr == NULL) {
|
||||
|
@ -405,7 +527,7 @@ void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t
|
|||
return;
|
||||
}
|
||||
|
||||
payload_len = libdhcpv6_address_request_message_len(srv_data_ptr->clientLinkIdType, srv_data_ptr->serverLinkType, 0, !dhcp_client.no_address_hint);
|
||||
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) {
|
||||
|
@ -416,8 +538,7 @@ void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t
|
|||
}
|
||||
dhcpv6_solication_base_packet_s packetReq = {
|
||||
.messageType = DHCPV6_RENEW_TYPE,
|
||||
.clientDUID.linkID = srv_data_ptr->clientId,
|
||||
.clientDUID.linkType = srv_data_ptr->clientLinkIdType,
|
||||
.clientDUID = srv_data_ptr->clientDUID,
|
||||
.requestedOptionCnt = 0,
|
||||
.iaID = srv_data_ptr->IAID,
|
||||
.timerT0 = srv_data_ptr->T0,
|
||||
|
@ -425,32 +546,31 @@ void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t
|
|||
.requestedOptionList = NULL,
|
||||
};
|
||||
|
||||
if (dhcp_client.renew_uses_solicit) {
|
||||
if (dhcp_client->renew_uses_solicit) {
|
||||
packetReq.messageType = DHCPV6_SOLICATION_TYPE;
|
||||
}
|
||||
|
||||
|
||||
serverLink.linkID = srv_data_ptr->serverLinkId;
|
||||
serverLink.linkType = srv_data_ptr->serverLinkType;
|
||||
if (dhcp_client.no_address_hint && dhcp_client.renew_uses_solicit) {
|
||||
|
||||
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, &serverLink);
|
||||
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, &serverLink);
|
||||
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);
|
||||
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);
|
||||
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) {
|
||||
|
@ -458,9 +578,9 @@ void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t
|
|||
}
|
||||
tr_error("DHCP renew send failed");
|
||||
}
|
||||
if (packetReq.messageType == DHCPV6_SOLICATION_TYPE && dhcp_client.sol_timeout != 0) {
|
||||
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);
|
||||
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");
|
||||
}
|
||||
|
@ -470,7 +590,6 @@ static bool dhcpv6_client_set_address(int8_t interface_id, dhcpv6_client_server_
|
|||
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;
|
||||
|
|
|
@ -39,6 +39,7 @@ typedef enum mac_event_t {
|
|||
MAC_TIMER_CCA,
|
||||
MAC_TX_FAIL,
|
||||
MAC_TX_TIMEOUT,
|
||||
MAC_ACK_SECURITY_FAIL,
|
||||
MAC_UNKNOWN_DESTINATION,
|
||||
MAC_TX_PRECOND_FAIL
|
||||
} mac_event_t;
|
||||
|
|
|
@ -572,9 +572,9 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme
|
|||
} else {
|
||||
|
||||
if (!b->neigh_info) {
|
||||
if (rf_mac_setup->mac_security_bypass_unknow_device && (b->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_64_BIT
|
||||
&& security_params->SecurityLevel > AES_SECURITY_LEVEL_ENC)) {
|
||||
security_by_pass = true;
|
||||
if (SrcPANId == rf_mac_setup->pan_id && rf_mac_setup->mac_security_bypass_unknow_device &&
|
||||
(b->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_64_BIT && security_params->SecurityLevel > AES_SECURITY_LEVEL_ENC)) {
|
||||
security_by_pass = true;//Accept by pass only from same PAN-ID
|
||||
} else {
|
||||
return MLME_UNSUPPORTED_SECURITY;
|
||||
}
|
||||
|
@ -723,7 +723,7 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte
|
|||
/* Parse security part */
|
||||
mac_header_security_components_read(buf, &data_ind->Key);
|
||||
|
||||
buf->neigh_info = mac_sec_mib_device_description_get(rf_mac_setup, data_ind->SrcAddr, data_ind->SrcAddrMode);
|
||||
buf->neigh_info = mac_sec_mib_device_description_get(rf_mac_setup, data_ind->SrcAddr, data_ind->SrcAddrMode, data_ind->SrcPANId);
|
||||
if (buf->fcf_dsn.securityEnabled) {
|
||||
status = mac_data_interface_decrypt_packet(buf, &data_ind->Key);
|
||||
if (status != MLME_SUCCESS) {
|
||||
|
@ -846,7 +846,8 @@ static int8_t mac_command_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_i
|
|||
//Read address and pan-id
|
||||
mac_header_get_src_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), temp_src_address);
|
||||
uint8_t address_mode = buf->fcf_dsn.SrcAddrMode;
|
||||
buf->neigh_info = mac_sec_mib_device_description_get(rf_mac_setup, temp_src_address, address_mode);
|
||||
uint16_t pan_id = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id);
|
||||
buf->neigh_info = mac_sec_mib_device_description_get(rf_mac_setup, temp_src_address, address_mode, pan_id);
|
||||
//Decrypt Packet if secured
|
||||
if (buf->fcf_dsn.securityEnabled) {
|
||||
mac_header_security_components_read(buf, &security_params);
|
||||
|
@ -1082,18 +1083,21 @@ static int8_t mac_ack_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inter
|
|||
memset(SrcAddr, 0, 8);
|
||||
memset(&key, 0, sizeof(mlme_security_t));
|
||||
mac_header_get_src_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), SrcAddr);
|
||||
uint16_t pan_id = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id);
|
||||
/* Parse security part */
|
||||
mac_header_security_components_read(buf, &key);
|
||||
|
||||
buf->neigh_info = mac_sec_mib_device_description_get(rf_mac_setup, SrcAddr, buf->fcf_dsn.SrcAddrMode);
|
||||
buf->neigh_info = mac_sec_mib_device_description_get(rf_mac_setup, SrcAddr, buf->fcf_dsn.SrcAddrMode, pan_id);
|
||||
if (buf->fcf_dsn.securityEnabled) {
|
||||
uint8_t status = mac_data_interface_decrypt_packet(buf, &key);
|
||||
if (status != MLME_SUCCESS) {
|
||||
rf_mac_setup->mac_tx_result = MAC_ACK_SECURITY_FAIL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf->mac_payload_length && !mac_payload_information_elements_parse(buf)) {
|
||||
rf_mac_setup->mac_tx_result = MAC_ACK_SECURITY_FAIL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1144,6 +1148,7 @@ static void mac_pd_data_ack_handler(mac_pre_parsed_frame_t *buf)
|
|||
//Do not forward ACK payload but Accept ACK
|
||||
mcps_sap_pre_parsed_frame_buffer_free(buf);
|
||||
buf = NULL;
|
||||
|
||||
}
|
||||
|
||||
rf_mac_setup->active_pd_data_request = NULL;
|
||||
|
@ -1276,7 +1281,7 @@ static bool mac_frame_security_parameters_init(ccm_globals_t *ccm_ptr, protocol_
|
|||
} else {
|
||||
//Discover device descriptor only unicast packet which need ack
|
||||
if (buffer->fcf_dsn.DstAddrMode && buffer->fcf_dsn.ackRequested) {
|
||||
device_description = mac_sec_mib_device_description_get(rf_ptr, buffer->DstAddr, buffer->fcf_dsn.DstAddrMode);
|
||||
device_description = mac_sec_mib_device_description_get(rf_ptr, buffer->DstAddr, buffer->fcf_dsn.DstAddrMode, buffer->DstPANId);
|
||||
if (!device_description) {
|
||||
buffer->status = MLME_UNAVAILABLE_KEY;
|
||||
return false;
|
||||
|
@ -1348,6 +1353,8 @@ static void mac_common_data_confirmation_handle(protocol_interface_rf_mac_setup_
|
|||
buf->status = MLME_TRANSACTION_EXPIRED;
|
||||
} else if (m_event == MAC_UNKNOWN_DESTINATION) {
|
||||
buf->status = MLME_UNAVAILABLE_KEY;
|
||||
} else if (m_event == MAC_ACK_SECURITY_FAIL) {
|
||||
buf->status = MLME_TX_NO_ACK;
|
||||
}/** else if (m_event == MAC_TX_PRECOND_FAIL) {
|
||||
* Nothing to do, status already set to buf->status.
|
||||
}**/
|
||||
|
|
|
@ -542,6 +542,9 @@ static int8_t mac_mlme_16bit_set(protocol_interface_rf_mac_setup_s *rf_mac_setup
|
|||
case macTransactionPersistenceTime:
|
||||
//TODO: check this also
|
||||
break;
|
||||
case macDeviceDescriptionPanIDUpdate:
|
||||
mac_sec_mib_device_description_pan_update(rf_mac_setup, value);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
|
|
|
@ -429,7 +429,7 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
|||
|
||||
if (rf_ptr->mac_ack_tx_active) {
|
||||
//Accept direct non crypted acks and crypted only if neighbor is at list
|
||||
if (rf_ptr->ack_tx_possible || mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode)) {
|
||||
if (rf_ptr->ack_tx_possible || mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode, rf_ptr->enhanced_ack_buffer.DstPANId)) {
|
||||
return PHY_TX_ALLOWED;
|
||||
}
|
||||
|
||||
|
@ -772,7 +772,7 @@ static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (rf_ptr->enhanced_ack_buffer.aux_header.securityLevel == 0 || mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode)) {
|
||||
if (rf_ptr->enhanced_ack_buffer.aux_header.securityLevel == 0 || mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode, rf_ptr->enhanced_ack_buffer.DstPANId)) {
|
||||
rf_ptr->ack_tx_possible = true;
|
||||
} else {
|
||||
rf_ptr->ack_tx_possible = false;
|
||||
|
|
|
@ -115,7 +115,7 @@ static void mac_sec_mib_frame_counter_key_buffer_free(protocol_interface_rf_mac_
|
|||
rf_mac_setup->secFrameCounterPerKey = false;
|
||||
}
|
||||
|
||||
static mlme_device_descriptor_t *mac_sec_mib_device_description_get_by_mac16(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint16_t mac16)
|
||||
static mlme_device_descriptor_t *mac_sec_mib_device_description_get_by_mac16(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint16_t mac16, uint16_t pan_id)
|
||||
{
|
||||
|
||||
mlme_device_descriptor_t *device_table = rf_mac_setup->device_description_table;
|
||||
|
@ -124,7 +124,7 @@ static mlme_device_descriptor_t *mac_sec_mib_device_description_get_by_mac16(pro
|
|||
}
|
||||
|
||||
for (int i = 0; i < rf_mac_setup->device_description_table_size; i++) {
|
||||
if (device_table->ShortAddress == mac16) {
|
||||
if ((pan_id == 0xffff || device_table->PANId == pan_id) && device_table->ShortAddress == mac16) {
|
||||
return device_table;
|
||||
}
|
||||
device_table++;
|
||||
|
@ -133,7 +133,7 @@ static mlme_device_descriptor_t *mac_sec_mib_device_description_get_by_mac16(pro
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static mlme_device_descriptor_t *mac_sec_mib_device_description_get_by_mac64(protocol_interface_rf_mac_setup_s *rf_mac_setup, const uint8_t *mac64)
|
||||
static mlme_device_descriptor_t *mac_sec_mib_device_description_get_by_mac64(protocol_interface_rf_mac_setup_s *rf_mac_setup, const uint8_t *mac64, uint16_t pan_id)
|
||||
{
|
||||
|
||||
mlme_device_descriptor_t *device_table = rf_mac_setup->device_description_table;
|
||||
|
@ -142,8 +142,10 @@ static mlme_device_descriptor_t *mac_sec_mib_device_description_get_by_mac64(pro
|
|||
}
|
||||
|
||||
for (int i = 0; i < rf_mac_setup->device_description_table_size; i++) {
|
||||
if (memcmp(device_table->ExtAddress, mac64, 8) == 0) {
|
||||
return device_table;
|
||||
if ((pan_id == 0xffff || device_table->PANId == pan_id)) {
|
||||
if (memcmp(device_table->ExtAddress, mac64, 8) == 0) {
|
||||
return device_table;
|
||||
}
|
||||
}
|
||||
device_table++;
|
||||
}
|
||||
|
@ -365,14 +367,30 @@ mlme_device_descriptor_t *mac_sec_mib_device_description_get_attribute_index(pro
|
|||
return rf_mac_setup->device_description_table + attribute_index;
|
||||
}
|
||||
|
||||
mlme_device_descriptor_t *mac_sec_mib_device_description_get(protocol_interface_rf_mac_setup_s *rf_mac_setup, const uint8_t *address, uint8_t type)
|
||||
void mac_sec_mib_device_description_pan_update(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint16_t pan_id)
|
||||
{
|
||||
mlme_device_descriptor_t *device_table = rf_mac_setup->device_description_table;
|
||||
if (!device_table) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rf_mac_setup->device_description_table_size; i++) {
|
||||
|
||||
device_table->PANId = pan_id;
|
||||
device_table++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
mlme_device_descriptor_t *mac_sec_mib_device_description_get(protocol_interface_rf_mac_setup_s *rf_mac_setup, const uint8_t *address, uint8_t type, uint16_t pan_id)
|
||||
{
|
||||
if (rf_mac_setup) {
|
||||
if (type == MAC_ADDR_MODE_16_BIT) {
|
||||
uint16_t short_id = common_read_16_bit(address);
|
||||
return mac_sec_mib_device_description_get_by_mac16(rf_mac_setup, short_id);
|
||||
return mac_sec_mib_device_description_get_by_mac16(rf_mac_setup, short_id, pan_id);
|
||||
} else if (type == MAC_ADDR_MODE_64_BIT) {
|
||||
return mac_sec_mib_device_description_get_by_mac64(rf_mac_setup, address);
|
||||
return mac_sec_mib_device_description_get_by_mac64(rf_mac_setup, address, pan_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,9 @@ int8_t mac_sec_mib_key_description_set(uint8_t atribute_index, mlme_key_descript
|
|||
|
||||
mlme_device_descriptor_t *mac_sec_mib_device_description_get_attribute_index(struct protocol_interface_rf_mac_setup *rf_mac_setup, uint8_t attribute_index);
|
||||
|
||||
mlme_device_descriptor_t *mac_sec_mib_device_description_get(struct protocol_interface_rf_mac_setup *rf_mac_setup, const uint8_t *address, uint8_t type);
|
||||
mlme_device_descriptor_t *mac_sec_mib_device_description_get(struct protocol_interface_rf_mac_setup *rf_mac_setup, const uint8_t *address, uint8_t type, uint16_t pan_id);
|
||||
|
||||
void mac_sec_mib_device_description_pan_update(struct protocol_interface_rf_mac_setup *rf_mac_setup, uint16_t pan_id);
|
||||
|
||||
uint8_t mac_mib_device_descption_attribute_get_by_descriptor(struct protocol_interface_rf_mac_setup *rf_mac_setup, mlme_device_descriptor_t *descriptor);
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ typedef enum {
|
|||
STATS_BUFFER_HEADROOM_FAIL,
|
||||
STATS_ETX_1ST_PARENT,
|
||||
STATS_ETX_2ND_PARENT,
|
||||
STATS_AL_TX_QUEUE_SIZE
|
||||
|
||||
} nwk_stats_type_t;
|
||||
|
||||
|
|
|
@ -146,6 +146,12 @@ void protocol_stats_update(nwk_stats_type_t type, uint16_t update_val)
|
|||
case STATS_ETX_2ND_PARENT:
|
||||
nwk_stats_ptr->etx_2nd_parent = update_val;
|
||||
break;
|
||||
case STATS_AL_TX_QUEUE_SIZE:
|
||||
nwk_stats_ptr->adapt_layer_tx_queue_size = update_val;
|
||||
if (nwk_stats_ptr->adapt_layer_tx_queue_size > nwk_stats_ptr->adapt_layer_tx_queue_peak) {
|
||||
nwk_stats_ptr->adapt_layer_tx_queue_peak = nwk_stats_ptr->adapt_layer_tx_queue_size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef enum rpl_event {
|
|||
RPL_EVENT_DAO_DONE, /* Simplistic trigger for bootstrap advance - a DAO registration completed */
|
||||
RPL_EVENT_LOCAL_REPAIR_START, /* RPL start scanning new parent by multicast DIS user can disable beacon request responser here*/
|
||||
RPL_EVENT_LOCAL_REPAIR_NO_MORE_DIS, /* RPL not sending DIS anymore user can report bootstrap error */
|
||||
RPL_EVENT_DAO_PARENT_SWITCH, /* RPL indicate that DAO downward Parent state have been updated */
|
||||
RPL_EVENT_DAO_PARENT_ADD, /* RPL indicate that DAO downward Parent has been added */
|
||||
} rpl_event_t;
|
||||
|
||||
typedef void rpl_domain_callback_t(rpl_event_t event, void *handle);
|
||||
|
|
|
@ -192,20 +192,18 @@ static bool rpl_instance_parent_selection_ready(rpl_instance_t *instance)
|
|||
|
||||
void rpl_downward_neighbour_gone(rpl_instance_t *instance, rpl_neighbour_t *neighbour)
|
||||
{
|
||||
if (neighbour->dao_path_control == 0) {
|
||||
return;
|
||||
}
|
||||
neighbour->old_dao_path_control = neighbour->dao_path_control;
|
||||
neighbour->dao_path_control = 0;
|
||||
rpl_downward_process_dao_parent_changes(instance);
|
||||
|
||||
// Currently don't need to do anything - caller is expected to
|
||||
// trigger parent selection, which will do everything required.
|
||||
(void) instance;
|
||||
(void) neighbour;
|
||||
}
|
||||
|
||||
void rpl_downward_process_dao_parent_changes(rpl_instance_t *instance)
|
||||
{
|
||||
uint8_t mop = rpl_instance_mop(instance);
|
||||
bool storing;
|
||||
|
||||
switch (mop) {
|
||||
switch (rpl_instance_mop(instance)) {
|
||||
case RPL_MODE_NON_STORING:
|
||||
storing = false;
|
||||
break;
|
||||
|
@ -219,6 +217,7 @@ void rpl_downward_process_dao_parent_changes(rpl_instance_t *instance)
|
|||
|
||||
bool bits_removed = false;
|
||||
uint8_t bits_added = 0;
|
||||
|
||||
ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) {
|
||||
if (neighbour->old_dao_path_control != neighbour->dao_path_control) {
|
||||
if (neighbour->old_dao_path_control & ~ neighbour->dao_path_control) {
|
||||
|
@ -230,11 +229,21 @@ void rpl_downward_process_dao_parent_changes(rpl_instance_t *instance)
|
|||
}
|
||||
}
|
||||
}
|
||||
tr_debug("removed=%x, added=%x", bits_removed, bits_added);
|
||||
|
||||
if (!(bits_removed || bits_added)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tr_debug("removed=%x, added=%x", bits_removed, bits_added);
|
||||
|
||||
ns_list_foreach(rpl_neighbour_t, neighbour, &instance->candidate_neighbours) {
|
||||
if (neighbour->dao_path_control != 0 && neighbour->old_dao_path_control == 0) {
|
||||
//Candidate has become a DAO parent
|
||||
rpl_control_event(instance->domain, RPL_EVENT_DAO_PARENT_ADD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (storing) {
|
||||
/* XXX more complicated - No-Paths to people losing stuff, etc.
|
||||
* Need to think a bit about what each parent would have had.
|
||||
|
@ -253,8 +262,8 @@ void rpl_downward_process_dao_parent_changes(rpl_instance_t *instance)
|
|||
}
|
||||
}
|
||||
}
|
||||
//GENERATE PARENT Update event
|
||||
rpl_control_event(instance->domain, RPL_EVENT_DAO_PARENT_SWITCH);
|
||||
|
||||
//Trig DAO allways after change
|
||||
rpl_instance_dao_trigger(instance, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,6 +198,13 @@ static rpl_neighbour_t *rpl_mrhof_select_best_parent(rpl_instance_t *instance, c
|
|||
/* We can use this to simplify some logic */
|
||||
if (prev_preferred) {
|
||||
prev_preferred_path_cost = rpl_mrhof_path_cost_through_neighbour(prev_preferred);
|
||||
// Path cost might be not much worse than alternate parents, but it might push
|
||||
// us over our DAGMaxRankIncrease limit. In that case, makes sense to treat
|
||||
// the path cost as "infinite", allowing immediate switch to an alternative,
|
||||
// defeating hysteresis.
|
||||
if (prev_preferred_path_cost > prev_preferred->dodag_version->hard_rank_limit) {
|
||||
prev_preferred_path_cost = RPL_RANK_INFINITE;
|
||||
}
|
||||
}
|
||||
|
||||
ns_list_foreach(rpl_neighbour_t, c, &instance->candidate_neighbours) {
|
||||
|
|
|
@ -81,6 +81,12 @@ uint16_t nrpl_dag_rank(const rpl_dodag_t *dodag, uint16_t rank)
|
|||
return rank == RPL_RANK_INFINITE ? rank : rank / dodag->config.min_hop_rank_increase;
|
||||
}
|
||||
|
||||
uint16_t nrpl_rank(const rpl_dodag_t *dodag, uint16_t dag_rank)
|
||||
{
|
||||
uint32_t rank = (uint32_t) dag_rank * dodag->config.min_hop_rank_increase;
|
||||
return rank < RPL_RANK_INFINITE ? rank : RPL_RANK_INFINITE;
|
||||
}
|
||||
|
||||
/* Silly function needed because RPL HbH option includes dagrank directly */
|
||||
rpl_cmp_t rpl_rank_compare_dagrank_rank(const rpl_dodag_t *dodag, uint16_t dag_rank_a, uint16_t b)
|
||||
{
|
||||
|
@ -1566,7 +1572,27 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_
|
|||
/* When we advertise a new lowest rank, need to re-evaluate our rank limits */
|
||||
if (rank < dodag_version->lowest_advertised_rank) {
|
||||
dodag_version->lowest_advertised_rank = rank;
|
||||
#if 0
|
||||
// Standard RFC 6550 behaviour
|
||||
dodag_version->hard_rank_limit = rpl_rank_add(rank, dodag->config.dag_max_rank_increase);
|
||||
#else
|
||||
// Round up hard limit - DAGRank interpretation. Contrary to wording of RFC 6550 8.2.2.4.3,
|
||||
// but needed to cope reasonably with Wi-SUN insisting on DAGMaxRankIncrease of 0.
|
||||
// Interpret that as a request to not increase DAGRank, rather than Rank.
|
||||
//
|
||||
// Example, if DAGMaxRankIncrease is 0, MinHopRankIncrease is 0x80, and our advertised
|
||||
// 0xC0, then we permit up to 0xFF, which doesn't increase DAGRank. If DAGMaxRankIncrease
|
||||
// is 0x80, then we permit can go form 0xC0 to 0x17F, increasing DAGRank by 1, even though
|
||||
// it's a Rank increase of 0xBF. Fractional parts of DAGMaxRankIncrease are ignored.
|
||||
uint16_t dagrank = nrpl_dag_rank(dodag, rank);
|
||||
uint16_t dagmaxinc = nrpl_dag_rank(dodag, dodag->config.dag_max_rank_increase);
|
||||
uint16_t dagmax = rpl_rank_add(dagrank, dagmaxinc);
|
||||
if (dagmax == RPL_RANK_INFINITE) {
|
||||
dodag_version->hard_rank_limit = RPL_RANK_INFINITE;
|
||||
} else {
|
||||
dodag_version->hard_rank_limit = nrpl_rank(dodag, 1 + dagmax) - 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
rpl_dodag_version_limit_greediness(dodag_version, rank);
|
||||
|
||||
|
|
|
@ -108,8 +108,8 @@ static const uint8_t *kde_search(const uint8_t *ptr, uint16_t len, const uint8_t
|
|||
while (len >= KDE_MIN_LEN) {
|
||||
uint16_t kde_len = ptr[1] + KDE_FIXED_LEN;
|
||||
|
||||
// Type shall be 0xdd and length shall be at least 6 */
|
||||
if (ptr[KDE_TYPE_INDEX] != 0xdd || kde_len < KDE_MIN_LEN || kde_len > len) {
|
||||
// For the type 0xdd the length shall be at least 6 */
|
||||
if ((ptr[KDE_TYPE_INDEX] == 0xdd && kde_len < KDE_MIN_LEN) || kde_len > len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ struct kmp_api_s {
|
|||
kmp_type_e type; /**< KMP type */
|
||||
kmp_addr_t *addr; /**< Supplicant EUI-64, Relay IP address, Relay port */
|
||||
kmp_service_t *service; /**< KMP service */
|
||||
uint8_t instance_identifier; /**< KMP instance identifier, incremented when created, from 0 to 255 */
|
||||
bool timer_start_pending : 1; /**< Timer is pending to start */
|
||||
bool receive_disable : 1; /**< Receiving disabled, do not route messages anymore */
|
||||
sec_prot_t sec_prot; /**< Security protocol interface */
|
||||
|
@ -62,6 +63,7 @@ typedef NS_LIST_HEAD(kmp_sec_prot_entry_t, link) kmp_sec_prot_list_t;
|
|||
struct kmp_service_s {
|
||||
kmp_sec_prot_list_t sec_prot_list; /**< Security protocols list */
|
||||
kmp_service_incoming_ind *incoming_ind; /**< Callback to application to indicate incoming KMP frame */
|
||||
kmp_service_tx_status_ind *tx_status_ind; /**< Callback to application to indicate TX status */
|
||||
kmp_service_addr_get *addr_get; /**< Callback to get addresses related to KMP */
|
||||
kmp_service_api_get *api_get; /**< Callback to get KMP API from a service */
|
||||
kmp_service_msg_if_send *send; /**< Callback to send KMP frames */
|
||||
|
@ -79,6 +81,9 @@ typedef struct {
|
|||
|
||||
static NS_LIST_DEFINE(kmp_service_list, kmp_service_t, link);
|
||||
|
||||
// KMP instance identifier value
|
||||
static uint8_t kmp_instance_identifier = 0;
|
||||
|
||||
static void kmp_api_sec_prot_create_confirm(sec_prot_t *prot, sec_prot_result_e result);
|
||||
static void kmp_api_sec_prot_create_indication(sec_prot_t *prot);
|
||||
static void kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys);
|
||||
|
@ -125,6 +130,7 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type)
|
|||
kmp->create_ind = 0;
|
||||
kmp->finished_ind = 0;
|
||||
kmp->finished = 0;
|
||||
kmp->instance_identifier = kmp_instance_identifier++;
|
||||
kmp->addr = 0;
|
||||
kmp->service = service;
|
||||
kmp->timer_start_pending = false;
|
||||
|
@ -212,7 +218,7 @@ static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size)
|
|||
int8_t result = -1;
|
||||
|
||||
if (kmp->service->send) {
|
||||
result = kmp->service->send(kmp->service, kmp_id, kmp->addr, pdu, size);
|
||||
result = kmp->service->send(kmp->service, kmp_id, kmp->addr, pdu, size, kmp->instance_identifier);
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
|
@ -348,6 +354,11 @@ void *kmp_api_data_get(kmp_api_t *kmp)
|
|||
return kmp->app_data_ptr;
|
||||
}
|
||||
|
||||
uint8_t kmp_api_instance_id_get(kmp_api_t *kmp)
|
||||
{
|
||||
return kmp->instance_identifier;
|
||||
}
|
||||
|
||||
void kmp_api_addr_set(kmp_api_t *kmp, kmp_addr_t *addr)
|
||||
{
|
||||
kmp->addr = addr;
|
||||
|
@ -367,6 +378,7 @@ kmp_service_t *kmp_service_create(void)
|
|||
|
||||
ns_list_init(&service->sec_prot_list);
|
||||
service->incoming_ind = 0;
|
||||
service->tx_status_ind = 0;
|
||||
service->addr_get = 0;
|
||||
service->api_get = 0;
|
||||
service->send = 0;
|
||||
|
@ -405,13 +417,14 @@ static void kmp_sec_prot_state_machine_call(sec_prot_t *prot)
|
|||
kmp->service->event_send(kmp->service, prot);
|
||||
}
|
||||
|
||||
int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind *incoming_ind, kmp_service_addr_get *addr_get, kmp_service_api_get *api_get)
|
||||
int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind *incoming_ind, kmp_service_tx_status_ind *tx_status_ind, kmp_service_addr_get *addr_get, kmp_service_api_get *api_get)
|
||||
{
|
||||
if (!service) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
service->incoming_ind = incoming_ind;
|
||||
service->tx_status_ind = tx_status_ind;
|
||||
service->addr_get = addr_get;
|
||||
service->api_get = api_get;
|
||||
|
||||
|
@ -450,6 +463,36 @@ int8_t kmp_service_msg_if_receive(kmp_service_t *service, kmp_type_e type, const
|
|||
return ret;
|
||||
}
|
||||
|
||||
int8_t kmp_service_tx_status_indication(kmp_service_t *service, kmp_tx_status_e tx_status, uint8_t tx_identifier)
|
||||
{
|
||||
if (!service || !service->tx_status_ind) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Application can use the tx_identifier to match the TX status indication to kmp
|
||||
kmp_api_t *kmp = (kmp_api_t *) service->tx_status_ind(service, tx_identifier);
|
||||
if (!kmp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Security protocol has disabled message receiving or tx status indication is not set
|
||||
if (kmp->receive_disable || !kmp->sec_prot.tx_status_ind) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sec_prot_tx_status_e sec_prot_tx_status;
|
||||
if (tx_status == KMP_TX_OK) {
|
||||
sec_prot_tx_status = SEC_PROT_TX_OK;
|
||||
} else if (tx_status == KMP_TX_ERR_TX_NO_ACK) {
|
||||
sec_prot_tx_status = SEC_PROT_TX_ERR_TX_NO_ACK;
|
||||
} else {
|
||||
sec_prot_tx_status = SEC_PROT_TX_ERR_UNSPEC;
|
||||
}
|
||||
|
||||
int8_t ret = kmp->sec_prot.tx_status_ind(&kmp->sec_prot, sec_prot_tx_status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t kmp_service_sec_protocol_register(kmp_service_t *service, kmp_type_e type, kmp_sec_prot_size *size, kmp_sec_prot_init *init)
|
||||
{
|
||||
if (!service) {
|
||||
|
|
|
@ -43,12 +43,18 @@ typedef enum {
|
|||
IEEE_802_11_GKH_KEY = 17
|
||||
} kmp_type_e;
|
||||
|
||||
typedef enum {
|
||||
KMP_RESULT_OK = 0, // Successful
|
||||
KMP_RESULT_ERR_NO_MEM = -1, // No memory
|
||||
KMP_RESULT_ERR_TX_NO_ACK = -2, // No acknowledge was received
|
||||
KMP_RESULT_ERR_UNSPEC = -3 // Other reason
|
||||
} kmp_result_e;
|
||||
|
||||
typedef enum {
|
||||
KMP_RESULT_OK = 0,
|
||||
KMP_RESULT_ERR_NO_MEM = -1,
|
||||
KMP_RESULT_ERR_UNSPEC = -2
|
||||
} kmp_result_e;
|
||||
KMP_TX_OK = 0, // Successful
|
||||
KMP_TX_ERR_TX_NO_ACK = -1, // No acknowledge was received
|
||||
KMP_TX_ERR_UNSPEC = -2, // Other reason
|
||||
} kmp_tx_status_e;
|
||||
|
||||
typedef void kmp_sec_keys_t;
|
||||
typedef struct sec_prot_s sec_prot_t;
|
||||
|
@ -201,6 +207,16 @@ void kmp_api_data_set(kmp_api_t *kmp, void *data);
|
|||
*/
|
||||
void *kmp_api_data_get(kmp_api_t *kmp);
|
||||
|
||||
/**
|
||||
* kmp_api_id_get get KMP instance identifier
|
||||
*
|
||||
* \param kmp instance
|
||||
*
|
||||
* \return instance identifier
|
||||
*
|
||||
*/
|
||||
uint8_t kmp_api_instance_id_get(kmp_api_t *kmp);
|
||||
|
||||
/**
|
||||
* kmp_api_addr_set set address
|
||||
*
|
||||
|
@ -262,6 +278,17 @@ int8_t kmp_service_delete(kmp_service_t *service);
|
|||
*/
|
||||
typedef kmp_api_t *kmp_service_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr);
|
||||
|
||||
/**
|
||||
* kmp_service_tx_status_ind Notifies application about TX status
|
||||
*
|
||||
* \param service KMP service
|
||||
* \param instance_id KMP instance identifier
|
||||
*
|
||||
* \return KMP instance or NULL
|
||||
*
|
||||
*/
|
||||
typedef kmp_api_t *kmp_service_tx_status_ind(kmp_service_t *service, uint8_t instance_id);
|
||||
|
||||
/**
|
||||
* kmp_service_addr_get gets addressing information related to KMP
|
||||
*
|
||||
|
@ -290,13 +317,15 @@ typedef kmp_api_t *kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, k
|
|||
*
|
||||
* \param service KMP service
|
||||
* \param incoming_ind incoming message callback
|
||||
* \param tx_status tx status callback
|
||||
* \param addr_get gets addressing information callback
|
||||
* \param api_get gets KMP API from KMP service
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind *incoming_ind, kmp_service_addr_get *addr_get, kmp_service_api_get *api_get);
|
||||
int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind *incoming_ind, kmp_service_tx_status_ind *tx_status_ind, kmp_service_addr_get *addr_get, kmp_service_api_get *api_get);
|
||||
|
||||
/**
|
||||
* kmp_service_msg_if_receive receive a message
|
||||
|
@ -321,12 +350,13 @@ int8_t kmp_service_msg_if_receive(kmp_service_t *service, kmp_type_e kmp_id, con
|
|||
* \param addr address
|
||||
* \param pdu pdu
|
||||
* \param size pdu size
|
||||
* \param tx_identifier TX identifier
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size);
|
||||
typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
|
||||
|
||||
/**
|
||||
* kmp_service_msg_if_register registers message interface
|
||||
|
@ -341,6 +371,19 @@ typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, kmp_type_e type,
|
|||
*/
|
||||
int8_t kmp_service_msg_if_register(kmp_service_t *service, kmp_service_msg_if_send *send, uint8_t header_size);
|
||||
|
||||
/**
|
||||
* kmp_service_tx_status tx status indication
|
||||
*
|
||||
* \param service KMP service
|
||||
* \param tx_status tx status
|
||||
* \param tx_identifier tx identifier
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t kmp_service_tx_status_indication(kmp_service_t *service, kmp_tx_status_e tx_status, uint8_t tx_identifier);
|
||||
|
||||
/**
|
||||
* kmp_sec_prot_size security protocol data size
|
||||
*
|
||||
|
|
|
@ -48,7 +48,8 @@ typedef struct {
|
|||
|
||||
static NS_LIST_DEFINE(kmp_eapol_pdu_if_list, kmp_eapol_pdu_if_t, link);
|
||||
|
||||
static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size);
|
||||
static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
|
||||
static int8_t kmp_eapol_pdu_if_tx_status(protocol_interface_info_entry_t *interface_ptr, eapol_pdu_tx_status_e tx_status, uint8_t tx_identifier);
|
||||
|
||||
int8_t kmp_eapol_pdu_if_register(kmp_service_t *service, protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
|
@ -96,7 +97,7 @@ int8_t kmp_eapol_pdu_if_unregister(kmp_service_t *service)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size)
|
||||
static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier)
|
||||
{
|
||||
if (!service || !addr || !pdu) {
|
||||
return -1;
|
||||
|
@ -123,7 +124,7 @@ static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, kmp_type_e kmp_id, c
|
|||
uint8_t *ptr = pdu;
|
||||
*ptr = kmp_id;
|
||||
|
||||
int8_t ret = ws_eapol_pdu_send_to_mpx(interface_ptr, eui_64, pdu, size, pdu);
|
||||
int8_t ret = ws_eapol_pdu_send_to_mpx(interface_ptr, eui_64, pdu, size, pdu, kmp_eapol_pdu_if_tx_status, tx_identifier);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -160,5 +161,35 @@ int8_t kmp_eapol_pdu_if_receive(protocol_interface_info_entry_t *interface_ptr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int8_t kmp_eapol_pdu_if_tx_status(protocol_interface_info_entry_t *interface_ptr, eapol_pdu_tx_status_e tx_status, uint8_t tx_identifier)
|
||||
{
|
||||
kmp_service_t *service = NULL;
|
||||
|
||||
ns_list_foreach(kmp_eapol_pdu_if_t, entry, &kmp_eapol_pdu_if_list) {
|
||||
if (entry->interface_ptr == interface_ptr) {
|
||||
service = entry->kmp_service;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!service) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
kmp_tx_status_e kmp_tx_status;
|
||||
if (tx_status == EAPOL_PDU_TX_OK) {
|
||||
kmp_tx_status = KMP_TX_OK;
|
||||
} else if (tx_status == EAPOL_PDU_TX_ERR_TX_NO_ACK) {
|
||||
kmp_tx_status = KMP_TX_ERR_TX_NO_ACK;
|
||||
} else {
|
||||
kmp_tx_status = KMP_TX_ERR_UNSPEC;
|
||||
}
|
||||
|
||||
int8_t ret = kmp_service_tx_status_indication(service, kmp_tx_status, tx_identifier);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_WS */
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ typedef struct {
|
|||
ns_list_link_t link; /**< Link */
|
||||
} kmp_socket_if_t;
|
||||
|
||||
static int8_t kmp_socket_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size);
|
||||
static int8_t kmp_socket_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
|
||||
static void kmp_socket_if_socket_cb(void *ptr);
|
||||
|
||||
static NS_LIST_DEFINE(kmp_socket_if_list, kmp_socket_if_t, link);
|
||||
|
@ -108,8 +108,10 @@ int8_t kmp_socket_if_unregister(kmp_service_t *service)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int8_t kmp_socket_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size)
|
||||
static int8_t kmp_socket_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier)
|
||||
{
|
||||
(void) tx_identifier;
|
||||
|
||||
if (!service || !pdu || !addr) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -119,7 +119,16 @@ int8_t eap_tls_sec_prot_lib_message_handle(uint8_t *data, uint16_t length, bool
|
|||
data += 4;
|
||||
}
|
||||
result = EAP_TLS_MSG_MORE_FRAG;
|
||||
} else if (data[0] == 0) {
|
||||
} else if (data[0] == 0 || data[0] == EAP_TLS_FRAGMENT_LENGTH) {
|
||||
// Skip fragment length if present
|
||||
if (data[0] & EAP_TLS_FRAGMENT_LENGTH) {
|
||||
if (length < 5) {
|
||||
tr_error("EAP-TLS: decode error");
|
||||
return EAP_TLS_MSG_DECODE_ERROR;
|
||||
}
|
||||
length -= 4;
|
||||
data += 4;
|
||||
}
|
||||
// Last (or only) fragment or fragment acknowledge. If sending data
|
||||
// updates acknowledged fragments.
|
||||
if (new_seq_id && eap_tls_sec_prot_lib_ack_update(tls_send)) {
|
||||
|
@ -132,10 +141,15 @@ int8_t eap_tls_sec_prot_lib_message_handle(uint8_t *data, uint16_t length, bool
|
|||
length -= 1; // EAP-TLS flags
|
||||
data += 1;
|
||||
|
||||
// No further processing for EAP-TLS start
|
||||
if (result == EAP_TLS_MSG_START) {
|
||||
return EAP_TLS_MSG_START;
|
||||
}
|
||||
|
||||
// TLS data not included
|
||||
if (length == 0) {
|
||||
if (new_seq_id && result == EAP_TLS_MSG_CONTINUE) {
|
||||
// If received only EAP-TLS header fails, and is not start,
|
||||
// If received only EAP-TLS header fails, and is not
|
||||
// fragment acknowledge or last frame
|
||||
result = EAP_TLS_MSG_FAIL;
|
||||
}
|
||||
|
|
|
@ -415,8 +415,8 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
return;
|
||||
}
|
||||
|
||||
// Set default timeout for the total maximum length of the negotiation
|
||||
sec_prot_default_timeout_set(&data->common);
|
||||
// Set retry timeout based on network size
|
||||
data->common.ticks = retry_timeout;
|
||||
|
||||
// Store sequence ID
|
||||
supp_eap_tls_sec_prot_seq_id_update(prot);
|
||||
|
@ -466,6 +466,9 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
// Initialize TLS protocol
|
||||
if (supp_eap_tls_sec_prot_init_tls(prot) < 0) {
|
||||
tr_error("TLS init failed");
|
||||
// If fatal error terminates EAP-TLS
|
||||
sec_prot_result_set(&data->common, SEC_RESULT_ERROR);
|
||||
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_FINISH);
|
||||
return;
|
||||
}
|
||||
// Request TLS to start (send client hello)
|
||||
|
@ -508,7 +511,12 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
|||
}
|
||||
} else {
|
||||
data->wait_tls = false;
|
||||
if (!data->tls_send.data || data->tls_result == EAP_TLS_RESULT_HANDSHAKE_FATAL_ERROR) {
|
||||
if (data->tls_result == EAP_TLS_RESULT_HANDSHAKE_FATAL_ERROR) {
|
||||
// If fatal error terminates EAP-TLS (TLS init has failed)
|
||||
sec_prot_result_set(&data->common, SEC_RESULT_ERROR);
|
||||
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_FINISH);
|
||||
return;
|
||||
} else if (!data->tls_send.data) {
|
||||
// If no more data send response, TLS EAP (empty)
|
||||
eap_tls_sec_prot_lib_message_allocate(&data->tls_send, TLS_HEAD_LEN, 0);
|
||||
}
|
||||
|
|
|
@ -39,40 +39,67 @@
|
|||
|
||||
#define TRACE_GROUP "ksep"
|
||||
|
||||
#define KEY_SEC_FINISHED_TIMEOUT 1 // Finishes right away
|
||||
|
||||
typedef enum {
|
||||
KEY_INIT = 0,
|
||||
KEY_CREATE_REQ,
|
||||
KEY_CREATE_RESP,
|
||||
KEY_FINISH,
|
||||
KEY_STATE_INIT = SEC_STATE_INIT,
|
||||
KEY_STATE_CREATE_REQ = SEC_STATE_CREATE_REQ,
|
||||
KEY_STATE_CREATE_RESP = SEC_STATE_CREATE_RESP,
|
||||
KEY_STATE_TX_DONE = SEC_STATE_FIRST,
|
||||
KEY_STATE_INITIAL_KEY_RECEIVED,
|
||||
KEY_STATE_FINISH = SEC_STATE_FINISH,
|
||||
KEY_STATE_FINISHED = SEC_STATE_FINISHED
|
||||
} key_sec_prot_state_e;
|
||||
|
||||
typedef struct {
|
||||
key_sec_prot_state_e state; /**< Protocol state machine state */
|
||||
sec_prot_result_e result; /**< Result for ongoing negotiation */
|
||||
sec_prot_common_t common; /**< Common data */
|
||||
} key_sec_prot_int_t;
|
||||
|
||||
static uint16_t key_sec_prot_size(void);
|
||||
static int8_t key_sec_prot_init(sec_prot_t *prot);
|
||||
static int8_t supp_key_sec_prot_init(sec_prot_t *prot);
|
||||
static int8_t auth_key_sec_prot_init(sec_prot_t *prot);
|
||||
|
||||
static void key_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_keys);
|
||||
static void key_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result);
|
||||
static void key_sec_prot_delete(sec_prot_t *prot);
|
||||
static int8_t key_sec_prot_initial_key_send(sec_prot_t *prot, sec_prot_keys_t *sec_keys);
|
||||
static int8_t key_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size);
|
||||
static void key_sec_prot_state_machine(sec_prot_t *prot);
|
||||
static int8_t key_sec_prot_tx_status_ind(sec_prot_t *prot, sec_prot_tx_status_e tx_status);
|
||||
static void key_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
|
||||
|
||||
static void supp_key_sec_prot_state_machine(sec_prot_t *prot);
|
||||
static void auth_key_sec_prot_state_machine(sec_prot_t *prot);
|
||||
|
||||
#define key_sec_prot_get(prot) (key_sec_prot_int_t *) &prot->data
|
||||
|
||||
int8_t key_sec_prot_register(kmp_service_t *service)
|
||||
int8_t supp_key_sec_prot_register(kmp_service_t *service)
|
||||
{
|
||||
if (!service) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kmp_service_sec_protocol_register(service, IEEE_802_1X_MKA_KEY, key_sec_prot_size, key_sec_prot_init) < 0) {
|
||||
if (kmp_service_sec_protocol_register(service, IEEE_802_1X_MKA_KEY, key_sec_prot_size, supp_key_sec_prot_init) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kmp_service_sec_protocol_register(service, IEEE_802_11_GKH_KEY, key_sec_prot_size, key_sec_prot_init) < 0) {
|
||||
if (kmp_service_sec_protocol_register(service, IEEE_802_11_GKH_KEY, key_sec_prot_size, supp_key_sec_prot_init) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t auth_key_sec_prot_register(kmp_service_t *service)
|
||||
{
|
||||
if (!service) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kmp_service_sec_protocol_register(service, IEEE_802_1X_MKA_KEY, key_sec_prot_size, auth_key_sec_prot_init) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kmp_service_sec_protocol_register(service, IEEE_802_11_GKH_KEY, key_sec_prot_size, auth_key_sec_prot_init) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -84,32 +111,60 @@ static uint16_t key_sec_prot_size(void)
|
|||
return sizeof(key_sec_prot_int_t);
|
||||
}
|
||||
|
||||
static int8_t key_sec_prot_init(sec_prot_t *prot)
|
||||
static int8_t supp_key_sec_prot_init(sec_prot_t *prot)
|
||||
{
|
||||
prot->create_req = key_sec_prot_create_request;
|
||||
prot->create_resp = key_sec_prot_create_response;
|
||||
|
||||
prot->receive = key_sec_prot_receive;
|
||||
prot->tx_status_ind = key_sec_prot_tx_status_ind;
|
||||
prot->delete = key_sec_prot_delete;
|
||||
prot->state_machine = key_sec_prot_state_machine;
|
||||
prot->state_machine = supp_key_sec_prot_state_machine;
|
||||
prot->timer_timeout = key_sec_prot_timer_timeout;
|
||||
|
||||
key_sec_prot_int_t *data = key_sec_prot_get(prot);
|
||||
data->state = KEY_INIT;
|
||||
data->result = SEC_RESULT_OK;
|
||||
sec_prot_init(&data->common);
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_INIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t auth_key_sec_prot_init(sec_prot_t *prot)
|
||||
{
|
||||
prot->create_resp = key_sec_prot_create_response;
|
||||
prot->receive = key_sec_prot_receive;
|
||||
prot->delete = key_sec_prot_delete;
|
||||
prot->state_machine = auth_key_sec_prot_state_machine;
|
||||
prot->timer_timeout = key_sec_prot_timer_timeout;
|
||||
|
||||
key_sec_prot_int_t *data = key_sec_prot_get(prot);
|
||||
sec_prot_init(&data->common);
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_INIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void key_sec_prot_delete(sec_prot_t *prot)
|
||||
{
|
||||
// No op at the moment
|
||||
(void) prot;
|
||||
}
|
||||
|
||||
static void key_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
key_sec_prot_int_t *data = key_sec_prot_get(prot);
|
||||
(void) sec_keys;
|
||||
|
||||
prot->state_machine_call(prot);
|
||||
}
|
||||
|
||||
static void key_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result)
|
||||
{
|
||||
key_sec_prot_int_t *data = key_sec_prot_get(prot);
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_CREATE_RESP);
|
||||
|
||||
sec_prot_result_set(&data->common, result);
|
||||
prot->state_machine_call(prot);
|
||||
}
|
||||
|
||||
static int8_t key_sec_prot_initial_key_send(sec_prot_t *prot, sec_prot_keys_t *sec_keys)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
uint16_t kde_len = KDE_GTKL_LEN;
|
||||
|
||||
uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys);
|
||||
|
@ -134,7 +189,7 @@ static void key_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_k
|
|||
|
||||
uint8_t *kde_start = ns_dyn_mem_temporary_alloc(kde_len);
|
||||
if (!kde_start) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *kde_end = kde_start;
|
||||
|
@ -157,41 +212,35 @@ static void key_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_k
|
|||
uint16_t eapol_pdu_size = eapol_pdu_key_frame_init(&eapol_pdu, kde_len, kde_start);
|
||||
|
||||
uint8_t *eapol_decoded_data = ns_dyn_mem_temporary_alloc(eapol_pdu_size + prot->header_size); // In future fill with data that defines eapol message
|
||||
|
||||
if (!eapol_decoded_data) {
|
||||
data->result = SEC_RESULT_ERR_NO_MEM;
|
||||
} else {
|
||||
eapol_pdu.msg.key.key_information.install = false;
|
||||
eapol_pdu.msg.key.key_information.pairwise_key = false;
|
||||
eapol_pdu.msg.key.key_information.request = true;
|
||||
eapol_pdu.msg.key.replay_counter = 0;
|
||||
eapol_pdu.msg.key.key_length = 0;
|
||||
eapol_write_pdu_frame(eapol_decoded_data + prot->header_size, &eapol_pdu);
|
||||
|
||||
tr_info("Initial EAPOL-Key send, PMKID %s PTKID %s GTKL %x", pmk ? "set" : "not set", ptk ? "set" : "not set", gtkl);
|
||||
|
||||
if (prot->send(prot, eapol_decoded_data, eapol_pdu_size + prot->header_size) < 0) {
|
||||
data->result = SEC_RESULT_ERR_NO_MEM;
|
||||
}
|
||||
result = -1;
|
||||
goto initial_key_exit;
|
||||
}
|
||||
|
||||
eapol_pdu.msg.key.key_information.install = false;
|
||||
eapol_pdu.msg.key.key_information.pairwise_key = false;
|
||||
eapol_pdu.msg.key.key_information.request = true;
|
||||
eapol_pdu.msg.key.replay_counter = 0;
|
||||
eapol_pdu.msg.key.key_length = 0;
|
||||
eapol_write_pdu_frame(eapol_decoded_data + prot->header_size, &eapol_pdu);
|
||||
|
||||
tr_info("Initial EAPOL-Key send, PMKID %s PTKID %s GTKL %x", pmk ? "set" : "not set", ptk ? "set" : "not set", gtkl);
|
||||
|
||||
if (prot->send(prot, eapol_decoded_data, eapol_pdu_size + prot->header_size) < 0) {
|
||||
result = -1;
|
||||
}
|
||||
|
||||
initial_key_exit:
|
||||
ns_dyn_mem_free(kde_start);
|
||||
|
||||
data->state = KEY_CREATE_REQ;
|
||||
prot->state_machine_call(prot);
|
||||
}
|
||||
|
||||
static void key_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result)
|
||||
{
|
||||
key_sec_prot_int_t *data = key_sec_prot_get(prot);
|
||||
data->state = KEY_CREATE_RESP;
|
||||
data->result = result;
|
||||
prot->state_machine_call(prot);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int8_t key_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size)
|
||||
{
|
||||
eapol_pdu_t eapol_pdu;
|
||||
key_sec_prot_int_t *data = key_sec_prot_get(prot);
|
||||
sec_prot_result_e result = SEC_RESULT_OK;
|
||||
|
||||
tr_info("Initial EAPOL-Key recv, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
|
||||
|
@ -248,45 +297,131 @@ static int8_t key_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size)
|
|||
tr_info("PMK %s PTK %s GTKL %x", prot->sec_keys->pmk_mismatch ? "not live" : "live", prot->sec_keys->ptk_mismatch ? "not live" : "live", gtkl);
|
||||
|
||||
ns_dyn_mem_free(kde);
|
||||
|
||||
prot->create_ind(prot);
|
||||
return 0;
|
||||
} else {
|
||||
tr_error("Invalid");
|
||||
// No error handling yet, indicate just that ready to be deleted
|
||||
prot->finished(prot);
|
||||
result = SEC_RESULT_ERROR;
|
||||
}
|
||||
|
||||
sec_prot_result_set(&data->common, result);
|
||||
prot->state_machine(prot);
|
||||
|
||||
if (result != SEC_RESULT_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void key_sec_prot_state_machine(sec_prot_t *prot)
|
||||
static int8_t key_sec_prot_tx_status_ind(sec_prot_t *prot, sec_prot_tx_status_e tx_status)
|
||||
{
|
||||
key_sec_prot_int_t *data = key_sec_prot_get(prot);
|
||||
|
||||
// Mixes currently supplicant and authenticator states
|
||||
switch (data->state) {
|
||||
case KEY_INIT:
|
||||
// empty
|
||||
break;
|
||||
case KEY_CREATE_REQ:
|
||||
// KMP-CREATE.confirm
|
||||
prot->create_conf(prot, data->result);
|
||||
// Indicates TX failure
|
||||
if (tx_status == SEC_PROT_TX_ERR_TX_NO_ACK) {
|
||||
sec_prot_result_set(&data->common, KMP_RESULT_ERR_TX_NO_ACK);
|
||||
} else if (tx_status != SEC_PROT_TX_OK) {
|
||||
// Indicates other failure
|
||||
sec_prot_result_set(&data->common, KMP_RESULT_ERR_UNSPEC);
|
||||
}
|
||||
prot->state_machine_call(prot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data->result == SEC_RESULT_OK) {
|
||||
// KMP-FINISHED.indication, no meaning for eapol-key, just completes transfer
|
||||
prot->finished_ind(prot, SEC_RESULT_OK, 0);
|
||||
static void key_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
||||
{
|
||||
key_sec_prot_int_t *data = key_sec_prot_get(prot);
|
||||
sec_prot_timer_timeout_handle(prot, &data->common, NULL, ticks);
|
||||
}
|
||||
|
||||
static void supp_key_sec_prot_state_machine(sec_prot_t *prot)
|
||||
{
|
||||
key_sec_prot_int_t *data = key_sec_prot_get(prot);
|
||||
|
||||
switch (sec_prot_state_get(&data->common)) {
|
||||
case KEY_STATE_INIT:
|
||||
tr_info("Initial-key init");
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_CREATE_REQ);
|
||||
prot->timer_start(prot);
|
||||
break;
|
||||
|
||||
case KEY_STATE_CREATE_REQ:
|
||||
// KMP-CREATE.confirm
|
||||
prot->create_conf(prot, sec_prot_result_get(&data->common));
|
||||
|
||||
// Send initial-key message
|
||||
if (key_sec_prot_initial_key_send(prot, prot->sec_keys) < 0) {
|
||||
// Error on sending, ready to be deleted
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_FINISH);
|
||||
return;
|
||||
}
|
||||
// Ready to be deleted
|
||||
|
||||
// Waits for TX acknowledge
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_TX_DONE);
|
||||
break;
|
||||
|
||||
case KEY_STATE_TX_DONE:
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_FINISH);
|
||||
break;
|
||||
|
||||
case KEY_STATE_FINISH:
|
||||
// KMP-FINISHED.indication,
|
||||
prot->finished_ind(prot, sec_prot_result_get(&data->common), 0);
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_FINISHED);
|
||||
data->common.ticks = KEY_SEC_FINISHED_TIMEOUT;
|
||||
break;
|
||||
|
||||
case KEY_STATE_FINISHED:
|
||||
tr_info("Initial-key finished");
|
||||
prot->timer_stop(prot);
|
||||
prot->finished(prot);
|
||||
break;
|
||||
case KEY_CREATE_RESP:
|
||||
if (data->result == SEC_RESULT_OK) {
|
||||
// KMP-FINISHED.indication, no meaning for eapol-key, just completes transfer
|
||||
prot->finished_ind(prot, SEC_RESULT_OK, 0);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void auth_key_sec_prot_state_machine(sec_prot_t *prot)
|
||||
{
|
||||
key_sec_prot_int_t *data = key_sec_prot_get(prot);
|
||||
|
||||
switch (sec_prot_state_get(&data->common)) {
|
||||
case KEY_STATE_INIT:
|
||||
tr_info("Initial-key init");
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_INITIAL_KEY_RECEIVED);
|
||||
prot->timer_start(prot);
|
||||
break;
|
||||
|
||||
case KEY_STATE_INITIAL_KEY_RECEIVED:
|
||||
if (!sec_prot_result_ok_check(&data->common)) {
|
||||
// Goes right away to finished
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_FINISHED);
|
||||
return;
|
||||
}
|
||||
// Ready to be deleted
|
||||
|
||||
// Send KMP-CREATE.indication
|
||||
prot->create_ind(prot);
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_CREATE_RESP);
|
||||
break;
|
||||
|
||||
case KEY_STATE_CREATE_RESP:
|
||||
// Goes to finish state right away
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_FINISH);
|
||||
break;
|
||||
|
||||
case KEY_STATE_FINISH:
|
||||
// KMP-FINISHED.indication,
|
||||
prot->finished_ind(prot, sec_prot_result_get(&data->common), 0);
|
||||
sec_prot_state_set(prot, &data->common, KEY_STATE_FINISHED);
|
||||
data->common.ticks = KEY_SEC_FINISHED_TIMEOUT;
|
||||
break;
|
||||
|
||||
case KEY_STATE_FINISHED: {
|
||||
tr_info("Initial-key finished, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||
prot->finished(prot);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -26,13 +26,23 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* key_sec_prot_register register EAPOL-Key protocol to KMP service
|
||||
* supp_key_sec_prot_register register supplicant EAPOL-Key protocol to KMP service
|
||||
*
|
||||
* \param service KMP service
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*/
|
||||
int8_t key_sec_prot_register(kmp_service_t *service);
|
||||
int8_t supp_key_sec_prot_register(kmp_service_t *service);
|
||||
|
||||
/**
|
||||
* auth_key_sec_prot_register register authenticator EAPOL-Key protocol to KMP service
|
||||
*
|
||||
* \param service KMP service
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*/
|
||||
int8_t auth_key_sec_prot_register(kmp_service_t *service);
|
||||
|
||||
#endif /* KEY_SEC_PROT_H_ */
|
||||
|
|
|
@ -30,9 +30,11 @@
|
|||
typedef enum {
|
||||
SEC_RESULT_OK = 0,
|
||||
SEC_RESULT_ERR_NO_MEM = -1,
|
||||
SEC_RESULT_TIMEOUT = -2,
|
||||
SEC_RESULT_ERROR = -3,
|
||||
SEC_RESULT_CONF_ERROR = -4
|
||||
SEC_RESULT_ERR_TX_NO_ACK = -2,
|
||||
SEC_RESULT_ERR_UNSPEC = -3,
|
||||
SEC_RESULT_TIMEOUT = -4,
|
||||
SEC_RESULT_ERROR = -5,
|
||||
SEC_RESULT_CONF_ERROR = -6
|
||||
} sec_prot_result_e;
|
||||
|
||||
typedef enum {
|
||||
|
@ -50,6 +52,12 @@ typedef enum {
|
|||
SEC_PROT_TYPE_TLS
|
||||
} sec_prot_type_e;
|
||||
|
||||
typedef enum {
|
||||
SEC_PROT_TX_OK = 0, // Successful
|
||||
SEC_PROT_TX_ERR_TX_NO_ACK = -1, // No acknowledge was received
|
||||
SEC_PROT_TX_ERR_UNSPEC = -2, // Other reason
|
||||
} sec_prot_tx_status_e;
|
||||
|
||||
/**
|
||||
* sec_prot_create_request KMP-CREATE.request to security protocol
|
||||
*
|
||||
|
@ -137,6 +145,18 @@ typedef int8_t sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size);
|
|||
*/
|
||||
typedef int8_t sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size);
|
||||
|
||||
/**
|
||||
* sec_prot_tx_status_ind tx status indication
|
||||
*
|
||||
* \param prot protocol
|
||||
* \param tx_status tx status
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
typedef int8_t sec_prot_tx_status_ind(sec_prot_t *prot, sec_prot_tx_status_e tx_status);
|
||||
|
||||
/**
|
||||
* sec_prot_delete delete the protocol data
|
||||
*
|
||||
|
@ -232,6 +252,7 @@ struct sec_prot_s {
|
|||
|
||||
sec_prot_send *send; /**< Protocol send */
|
||||
sec_prot_receive *receive; /**< Protocol receive */
|
||||
sec_prot_tx_status_ind *tx_status_ind; /**< TX status indication */
|
||||
|
||||
sec_prot_delete *delete; /**< Protocol delete */
|
||||
|
||||
|
|
|
@ -581,6 +581,11 @@ void sec_prot_keys_gtks_hash_generate(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhas
|
|||
}
|
||||
}
|
||||
|
||||
void sec_prot_keys_gtk_hash_generate(uint8_t *gtk, uint8_t *gtk_hash)
|
||||
{
|
||||
sec_prot_lib_gtkhash_generate(gtk, gtk_hash);
|
||||
}
|
||||
|
||||
gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash)
|
||||
{
|
||||
uint8_t *gtk_hash_ptr = gtkhash;
|
||||
|
|
|
@ -92,6 +92,17 @@ typedef struct {
|
|||
bool ptk_mismatch: 1; /**< Remote PTK mismatch reported */
|
||||
} sec_prot_keys_t;
|
||||
|
||||
// Frame counter data
|
||||
typedef struct {
|
||||
uint8_t gtk[GTK_LEN]; /**< GTK of the frame counter */
|
||||
uint32_t frame_counter; /**< Frame counter */
|
||||
bool set : 1; /**< Value has been set */
|
||||
} frame_counter_t;
|
||||
|
||||
typedef struct {
|
||||
frame_counter_t counter[GTK_NUM]; /**< Frame counter for each GTK key */
|
||||
} frame_counters_t;
|
||||
|
||||
/*
|
||||
* GTK mismatch types, list is ordered according to priority of mismatch i.e. if there
|
||||
* are both hash and lifetime mismatch, hash has greater priority
|
||||
|
@ -632,6 +643,15 @@ bool sec_prot_keys_gtk_status_is_live(sec_prot_gtk_keys_t *gtks, uint8_t index);
|
|||
*/
|
||||
void sec_prot_keys_gtks_hash_generate(sec_prot_gtk_keys_t *gtks, uint8_t *gtk_hash);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtk_hash_generate generate GTK hash for a GTK
|
||||
*
|
||||
* \param gtk GTK key
|
||||
* \param gtk_hash GTK hash for a GTK
|
||||
*
|
||||
*/
|
||||
void sec_prot_keys_gtk_hash_generate(uint8_t *gtk, uint8_t *gtk_hash);
|
||||
|
||||
/**
|
||||
* sec_prot_keys_gtks_hash_update update GTKs based on GTK hash
|
||||
*
|
||||
|
|
|
@ -487,6 +487,10 @@ static int tls_sec_prot_lib_x509_crt_verify(void *ctx, mbedtls_x509_crt *crt, in
|
|||
if (crt->sig_pk != MBEDTLS_PK_ECDSA) {
|
||||
tr_error("Invalid signature pk algorithm");
|
||||
}
|
||||
if (*flags & MBEDTLS_X509_BADCERT_FUTURE) {
|
||||
tr_info("Certificate time future");
|
||||
*flags &= ~MBEDTLS_X509_BADCERT_FUTURE;
|
||||
}
|
||||
|
||||
// Verify client/server certificate of the chain
|
||||
if (certificate_depth == 0) {
|
||||
|
|
|
@ -38,16 +38,23 @@ static NS_LARGE NS_LIST_DEFINE(dhcpv6_client_nonTemporal_list, dhcpv6_client_ser
|
|||
static dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_entry_allocate(void)
|
||||
{
|
||||
dhcpv6_client_server_data_t *newEntry = ns_dyn_mem_alloc(sizeof(dhcpv6_client_server_data_t));
|
||||
if (newEntry) {
|
||||
newEntry->T0 = 0;
|
||||
newEntry->T1 = 0;
|
||||
newEntry->reNewTimer = 0;
|
||||
newEntry->iaNonTemporalStructValid = false;
|
||||
newEntry->GlobalAddress = false;
|
||||
newEntry->useServerAddress = false;
|
||||
newEntry->iaNontemporalAddress.preferredTime = 0;
|
||||
newEntry->iaNontemporalAddress.validLifetime = 0;
|
||||
uint8_t *temporary_duid = ns_dyn_mem_alloc(16); //Support DUID-LL, DUID-LLP and DUID-UUID by default
|
||||
if (!newEntry || !temporary_duid) {
|
||||
ns_dyn_mem_free(newEntry);
|
||||
ns_dyn_mem_free(temporary_duid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newEntry->T0 = 0;
|
||||
newEntry->T1 = 0;
|
||||
newEntry->reNewTimer = 0;
|
||||
newEntry->iaNonTemporalStructValid = false;
|
||||
newEntry->GlobalAddress = false;
|
||||
newEntry->useServerAddress = false;
|
||||
newEntry->iaNontemporalAddress.preferredTime = 0;
|
||||
newEntry->iaNontemporalAddress.validLifetime = 0;
|
||||
newEntry->dyn_server_duid_length = 16;
|
||||
newEntry->serverDynamic_DUID = temporary_duid;
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
|
@ -123,35 +130,34 @@ uint32_t libdhcpv6_renew_time_define(dhcpv6_client_server_data_t *addresInfo)
|
|||
return renewTimer;
|
||||
}
|
||||
|
||||
dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_server_data_allocate(int8_t interfaceId, uint8_t instanceId, uint8_t *duiId, uint16_t duiLinkType, uint8_t *nonTemporalPrefix, uint8_t *serverIPv6Address)
|
||||
dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_server_data_allocate(int8_t interfaceId, uint8_t instanceId, uint8_t *nonTemporalPrefix, uint8_t *serverIPv6Address)
|
||||
{
|
||||
uint32_t iaId;
|
||||
uint8_t *ptr;
|
||||
dhcpv6_client_server_data_t *new_entry = NULL;
|
||||
if (duiId) {
|
||||
//allocate new Entry
|
||||
iaId = libdhcpv6_IAID_generate();
|
||||
new_entry = libdhcvp6_nontemporalAddress_entry_allocate();
|
||||
if (new_entry) {
|
||||
new_entry->IAID = iaId;
|
||||
new_entry->interfaceId = interfaceId;
|
||||
new_entry->instanceId = instanceId;
|
||||
//save Cliet ID
|
||||
memcpy(new_entry->clientId, duiId, 8);
|
||||
new_entry->clientLinkIdType = duiLinkType;
|
||||
if (serverIPv6Address) {
|
||||
memcpy(new_entry->server_address, serverIPv6Address, 16);
|
||||
new_entry->useServerAddress = true;
|
||||
}
|
||||
if (nonTemporalPrefix) {
|
||||
uint8_t *ptr = new_entry->iaNontemporalAddress.addressPrefix;
|
||||
memcpy(ptr, nonTemporalPrefix, 8);
|
||||
memset((ptr + 8), 0, 8);
|
||||
new_entry->iaNonTemporalStructValid = true;
|
||||
new_entry->iaNontemporalAddress.preferredTime = 0;
|
||||
new_entry->iaNontemporalAddress.validLifetime = 0;
|
||||
}
|
||||
ns_list_add_to_end(&dhcpv6_client_nonTemporal_list, new_entry);
|
||||
//allocate new Entry
|
||||
iaId = libdhcpv6_IAID_generate();
|
||||
new_entry = libdhcvp6_nontemporalAddress_entry_allocate();
|
||||
if (new_entry) {
|
||||
new_entry->IAID = iaId;
|
||||
new_entry->interfaceId = interfaceId;
|
||||
new_entry->instanceId = instanceId;
|
||||
new_entry->serverDUID.duid = NULL;
|
||||
new_entry->serverDUID.duid_length = 0;
|
||||
|
||||
if (serverIPv6Address) {
|
||||
memcpy(new_entry->server_address, serverIPv6Address, 16);
|
||||
new_entry->useServerAddress = true;
|
||||
}
|
||||
if (nonTemporalPrefix) {
|
||||
ptr = new_entry->iaNontemporalAddress.addressPrefix;
|
||||
memcpy(ptr, nonTemporalPrefix, 8);
|
||||
memset((ptr + 8), 0, 8);
|
||||
new_entry->iaNonTemporalStructValid = true;
|
||||
new_entry->iaNontemporalAddress.preferredTime = 0;
|
||||
new_entry->iaNontemporalAddress.validLifetime = 0;
|
||||
}
|
||||
ns_list_add_to_end(&dhcpv6_client_nonTemporal_list, new_entry);
|
||||
}
|
||||
return new_entry;
|
||||
}
|
||||
|
@ -160,6 +166,7 @@ void libdhcvp6_nontemporalAddress_server_data_free(dhcpv6_client_server_data_t *
|
|||
{
|
||||
if (removedEntry) {
|
||||
ns_list_remove(&dhcpv6_client_nonTemporal_list, removedEntry);
|
||||
ns_dyn_mem_free(removedEntry->serverDynamic_DUID);
|
||||
ns_dyn_mem_free(removedEntry);
|
||||
}
|
||||
}
|
||||
|
@ -228,26 +235,19 @@ dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_validate_class_pointer(void *
|
|||
}
|
||||
|
||||
|
||||
uint16_t libdhcpv6_duid_option_size(uint16_t linkType)
|
||||
uint16_t libdhcpv6_duid_option_size(uint16_t duidLength)
|
||||
{
|
||||
uint16_t length = 8; // Type & Length header part *2
|
||||
if (linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE ||
|
||||
linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) {
|
||||
length += 8;
|
||||
} else {
|
||||
length += 6;
|
||||
}
|
||||
|
||||
return length;
|
||||
return duidLength + 6; //ID Type 2, length 2 ,Duid Type 2 + duid data
|
||||
}
|
||||
|
||||
uint16_t libdhcpv6_client_data_option_size(uint16_t linkType)
|
||||
uint8_t libdhcpv6_duid_linktype_size(uint16_t linkType)
|
||||
{
|
||||
uint16_t optionLength = 4;
|
||||
optionLength += libdhcpv6_duid_option_size(linkType);
|
||||
optionLength += libdhcpv6_ia_address_option_size();
|
||||
optionLength += libdhcpv6_client_last_transaction_time_option_size();
|
||||
return optionLength;
|
||||
if (linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE ||
|
||||
linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
return 6;
|
||||
}
|
||||
|
||||
uint16_t libdhcvp6_request_option_size(uint8_t optionCnt)
|
||||
|
@ -345,18 +345,14 @@ uint8_t *libdhcvp6_request_option_write(uint8_t *ptr, uint8_t optionCnt, uint16_
|
|||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *libdhcpv6_duid_option_write(uint8_t *ptr, uint16_t duidRole, const dhcp_link_options_params_t *duid)
|
||||
uint8_t *libdhcpv6_duid_option_write(uint8_t *ptr, uint16_t duidRole, const dhcp_duid_options_params_t *duid)
|
||||
{
|
||||
uint16_t length = libdhcpv6_duid_option_size(duid->linkType);
|
||||
|
||||
length -= 4; //Cut normal option header out
|
||||
uint16_t length = duid->duid_length + 2;
|
||||
ptr = common_write_16_bit(duidRole, ptr);
|
||||
ptr = common_write_16_bit(length, ptr);
|
||||
ptr = common_write_16_bit(DHCPV6_DUID_LINK_LAYER_TYPE, ptr);
|
||||
ptr = common_write_16_bit(duid->linkType, ptr);
|
||||
length -= 4; //Cut normal option header out
|
||||
memcpy(ptr, duid->linkID, length);
|
||||
ptr += length;
|
||||
ptr = common_write_16_bit(duid->type, ptr);
|
||||
memcpy(ptr, duid->duid, duid->duid_length);
|
||||
ptr += duid->duid_length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -460,25 +456,23 @@ int libdhcpv6_message_option_discover(uint8_t *ptr, uint16_t data_len, uint16_t
|
|||
return -1;
|
||||
}
|
||||
|
||||
int libdhcpv6_compare_DUID(dhcp_link_options_params_t *targetId, dhcp_link_options_params_t *parsedId)
|
||||
int libdhcpv6_compare_DUID(dhcp_duid_options_params_t *targetId, dhcp_duid_options_params_t *parsedId)
|
||||
{
|
||||
if (targetId->linkType == parsedId->linkType) {
|
||||
uint8_t cmpLen;
|
||||
if (targetId->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE ||
|
||||
targetId->linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) {
|
||||
//Compare Current Interface EUID64
|
||||
cmpLen = 8;
|
||||
} else {
|
||||
cmpLen = 6;
|
||||
}
|
||||
if (memcmp(targetId->linkID, parsedId->linkID, cmpLen) == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (targetId->type != parsedId->type) {
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
|
||||
if (targetId->duid_length != parsedId->duid_length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(targetId->duid, parsedId->duid, targetId->duid_length) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libdhcpv6_reply_message_option_validate(dhcp_link_options_params_t *clientId, dhcp_link_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length)
|
||||
int libdhcpv6_reply_message_option_validate(dhcp_duid_options_params_t *clientId, dhcp_duid_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length)
|
||||
{
|
||||
/**
|
||||
* Solication Message Should Include Next Options:
|
||||
|
@ -503,7 +497,7 @@ int libdhcpv6_reply_message_option_validate(dhcp_link_options_params_t *clientId
|
|||
return 0;
|
||||
}
|
||||
|
||||
int libdhcpv6_advertisment_message_option_validate(dhcp_link_options_params_t *clientId, dhcp_link_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length)
|
||||
int libdhcpv6_advertisment_message_option_validate(dhcp_duid_options_params_t *clientId, dhcp_duid_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length)
|
||||
{
|
||||
/**
|
||||
* Solication Message Should Include Next Options:
|
||||
|
@ -528,7 +522,7 @@ int libdhcpv6_advertisment_message_option_validate(dhcp_link_options_params_t *c
|
|||
return 0;
|
||||
}
|
||||
#ifdef HAVE_DHCPV6_SERVER
|
||||
int libdhcpv6_renew_message_options_validate(uint8_t *ptr, uint16_t data_length, dhcp_link_options_params_t *clientLinkData, dhcp_link_options_params_t *serverLinkData, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params)
|
||||
int libdhcpv6_renew_message_options_validate(uint8_t *ptr, uint16_t data_length, dhcp_duid_options_params_t *clientLinkData, dhcp_duid_options_params_t *serverLinkData, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params)
|
||||
{
|
||||
|
||||
/**
|
||||
|
@ -565,7 +559,7 @@ int libdhcpv6_renew_message_options_validate(uint8_t *ptr, uint16_t data_length,
|
|||
|
||||
|
||||
|
||||
int libdhcpv6_solication_message_options_validate(uint8_t *ptr, uint16_t data_length, dhcp_link_options_params_t *clientLink, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params)
|
||||
int libdhcpv6_solication_message_options_validate(uint8_t *ptr, uint16_t data_length, dhcp_duid_options_params_t *clientLink, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params)
|
||||
{
|
||||
/**
|
||||
* Solication Message Should Include Next Options:
|
||||
|
@ -620,34 +614,102 @@ bool libdhcpv6_rapid_commit_option_at_packet(uint8_t *ptr, uint16_t length)
|
|||
return retVal;
|
||||
}
|
||||
|
||||
int libdhcpv6_get_duid_by_selected_type_id_opt(uint8_t *ptr, uint16_t data_length, uint16_t type, dhcp_link_options_params_t *params)
|
||||
bool libdhcpv6_duid_length_validate(uint16_t duid_type, uint16_t duid_length)
|
||||
{
|
||||
uint16_t min_length;
|
||||
switch (duid_type) {
|
||||
case DHCPV6_DUID_LINK_LAYER_PLUS_TIME_TYPE:
|
||||
//hardware type (16 bits) + time (32 bits) +link layer address (variable length 1 min)
|
||||
min_length = 7; //Link Time Time
|
||||
break;
|
||||
case DHCPV6_DUID_EN_TYPE: //enterprise-number (32-bits) +identifier (variable length 1 min)
|
||||
min_length = 5;
|
||||
break;
|
||||
case DHCPV6_DUID_LINK_LAYER_TYPE:
|
||||
//hardware type (16 bits) + link layer address (variable length 1 min)
|
||||
min_length = 3; //Type 2 and MiN DUI-id 1
|
||||
break;
|
||||
|
||||
case DHCPV6_DUID_UUID_TYPE:
|
||||
//UUID (128-bits)
|
||||
if (duid_length != 16) {
|
||||
return false;
|
||||
}
|
||||
min_length = 16;
|
||||
break;
|
||||
|
||||
default://Unsupported type set length to inpossible
|
||||
min_length = 0xffff;
|
||||
break;
|
||||
}
|
||||
|
||||
//Validate min and MAX length
|
||||
if (min_length > duid_length || min_length == 0xffff) {
|
||||
//Too short
|
||||
return false;
|
||||
}
|
||||
|
||||
if (duid_length > 128 - min_length) {
|
||||
//Too Long
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int libdhcpv6_get_duid_by_selected_type_id_opt(uint8_t *ptr, uint16_t data_length, uint16_t type, dhcp_duid_options_params_t *params)
|
||||
{
|
||||
dhcp_options_msg_t option_msg;
|
||||
|
||||
/** Verify DHCPV6_CLIENT_ID_OPTION */
|
||||
if (libdhcpv6_message_option_discover(ptr, data_length, type, &option_msg) == 0) {
|
||||
if (option_msg.len >= DHCPV6_SERVER_ID_MAC48_OPTION_LEN) {
|
||||
uint8_t *t_ptr = option_msg.msg_ptr;
|
||||
type = common_read_16_bit(t_ptr);
|
||||
t_ptr += 2;
|
||||
params->linkType = common_read_16_bit(t_ptr);
|
||||
t_ptr += 2;
|
||||
if (type == DHCPV6_DUID_LINK_LAYER_TYPE) {
|
||||
params->linkID = t_ptr;
|
||||
if ((params->linkType == DHCPV6_DUID_HARDWARE_EUI48_TYPE) && (option_msg.len == DHCPV6_SERVER_ID_MAC48_OPTION_LEN)) {
|
||||
return 0;
|
||||
} else if ((params->linkType == DHCPV6_DUID_HARDWARE_EUI64_TYPE) && (option_msg.len == DHCPV6_SERVER_ID_MAC64_OPTION_LEN)) {
|
||||
return 0;
|
||||
} else if ((params->linkType == DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) && (option_msg.len == DHCPV6_SERVER_ID_MAC64_OPTION_LEN)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (libdhcpv6_message_option_discover(ptr, data_length, type, &option_msg) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
if (option_msg.len < 5) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *t_ptr = option_msg.msg_ptr;
|
||||
params->type = common_read_16_bit(t_ptr);
|
||||
t_ptr += 2;
|
||||
params->duid = t_ptr;
|
||||
params->duid_length = option_msg.len - 2;
|
||||
//Validate types and lengths
|
||||
if (!libdhcpv6_duid_length_validate(params->type, params->duid_length)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libdhcpv6_get_link_address_from_duid(uint8_t *ptr, uint16_t data_length, uint16_t type, dhcp_link_options_params_t *params)
|
||||
{
|
||||
|
||||
if ((type != DHCPV6_DUID_LINK_LAYER_TYPE && type != DHCPV6_DUID_LINK_LAYER_PLUS_TIME_TYPE) || data_length < 8) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
params->link_type = common_read_16_bit(ptr);
|
||||
ptr += 2;
|
||||
data_length -= 2;
|
||||
if (type == DHCPV6_DUID_LINK_LAYER_PLUS_TIME_TYPE) {
|
||||
params->link_time = common_read_32_bit(ptr);
|
||||
ptr += 4;
|
||||
data_length -= 4;
|
||||
} else {
|
||||
params->link_time = 0;
|
||||
}
|
||||
if (libdhcpv6_duid_linktype_size(params->link_type) > data_length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
params->link_id = ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int libdhcpv6_get_IA_address(uint8_t *ptr, uint16_t data_length, dhcp_ia_non_temporal_params_t *params)
|
||||
{
|
||||
dhcp_options_msg_t option_msg;
|
||||
|
@ -708,26 +770,26 @@ int libdhcpv6_get_IA_address(uint8_t *ptr, uint16_t data_length, dhcp_ia_non_tem
|
|||
return -1;
|
||||
}
|
||||
|
||||
uint16_t libdhcpv6_address_request_message_len(uint16_t clientLinkType, uint16_t serverLinkType, uint8_t requstOptionCnt, bool add_address)
|
||||
uint16_t libdhcpv6_address_request_message_len(uint16_t clientDUIDLength, uint16_t serverDUIDLength, uint8_t requstOptionCnt, bool add_address)
|
||||
{
|
||||
uint16_t length = 0;
|
||||
length += libdhcpv6_header_size();
|
||||
length += libdhcpv6_elapsed_time_option_size();
|
||||
length += libdhcpv6_duid_option_size(clientLinkType);
|
||||
length += libdhcpv6_duid_option_size(serverLinkType);
|
||||
length += libdhcpv6_duid_option_size(clientDUIDLength);
|
||||
length += libdhcpv6_duid_option_size(serverDUIDLength);
|
||||
length += libdhcvp6_request_option_size(requstOptionCnt);
|
||||
length += libdhcpv6_rapid_commit_option_size();
|
||||
length += libdhcpv6_non_temporal_address_size(add_address);
|
||||
return length;
|
||||
}
|
||||
#ifdef HAVE_DHCPV6_SERVER
|
||||
uint16_t libdhcpv6_address_reply_message_len(uint16_t clientLinkType, uint16_t serverLinkType, uint16_t vendorDataLen, bool rapidCommon, bool status)
|
||||
uint16_t libdhcpv6_address_reply_message_len(uint16_t clientDUIDLength, uint16_t serverDUIDLength, uint16_t vendorDataLen, bool rapidCommon, bool status)
|
||||
{
|
||||
uint16_t length = 0;
|
||||
|
||||
length += libdhcpv6_header_size();
|
||||
length += libdhcpv6_duid_option_size(clientLinkType);
|
||||
length += libdhcpv6_duid_option_size(serverLinkType);
|
||||
length += libdhcpv6_duid_option_size(clientDUIDLength);
|
||||
length += libdhcpv6_duid_option_size(serverDUIDLength);
|
||||
if (rapidCommon) {
|
||||
length += libdhcpv6_rapid_commit_option_size();
|
||||
}
|
||||
|
@ -747,7 +809,7 @@ uint16_t libdhcpv6_address_reply_message_len(uint16_t clientLinkType, uint16_t s
|
|||
}
|
||||
#endif
|
||||
|
||||
uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_link_options_params_t *serverLink)
|
||||
uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_duid_options_params_t *serverLink)
|
||||
{
|
||||
bool add_address = false;
|
||||
if (nonTemporalAddress) {
|
||||
|
@ -803,13 +865,13 @@ uint8_t *libdhcpv6_reply_message_write(uint8_t *ptr, dhcpv6_reply_packet_s *repl
|
|||
return ptr;
|
||||
}
|
||||
|
||||
uint16_t libdhcpv6_solication_message_length(uint16_t clientLinkType, bool addressDefined, uint8_t requestOptionCount)
|
||||
uint16_t libdhcpv6_solication_message_length(uint16_t clientDUIDLength, bool addressDefined, uint8_t requestOptionCount)
|
||||
{
|
||||
uint16_t length = 0;
|
||||
length += libdhcpv6_header_size();
|
||||
length += libdhcpv6_elapsed_time_option_size();
|
||||
length += libdhcpv6_rapid_commit_option_size();
|
||||
length += libdhcpv6_duid_option_size(clientLinkType);
|
||||
length += libdhcpv6_duid_option_size(clientDUIDLength);
|
||||
length += libdhcpv6_non_temporal_address_size(addressDefined);
|
||||
length += libdhcvp6_request_option_size(requestOptionCount);
|
||||
return length;
|
||||
|
|
|
@ -26,10 +26,18 @@
|
|||
|
||||
#include "ns_list.h"
|
||||
|
||||
typedef struct dhcp_duid_options_params {
|
||||
uint16_t type;
|
||||
uint16_t duid_length;
|
||||
uint8_t *duid;
|
||||
} dhcp_duid_options_params_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t linkType;
|
||||
uint8_t *linkID;
|
||||
uint16_t link_type;
|
||||
uint32_t link_time;
|
||||
uint8_t *link_id;
|
||||
} dhcp_link_options_params_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
|
@ -49,8 +57,8 @@ typedef struct {
|
|||
} dhcpv6_ia_non_temporal_address_s;
|
||||
|
||||
typedef struct {
|
||||
dhcp_link_options_params_t clientDUID;
|
||||
dhcp_link_options_params_t serverDUID;
|
||||
dhcp_duid_options_params_t clientDUID;
|
||||
dhcp_duid_options_params_t serverDUID;
|
||||
uint32_t transaction_ID;
|
||||
uint32_t iaId;
|
||||
uint32_t T0;
|
||||
|
@ -66,7 +74,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
uint8_t messageType;
|
||||
uint32_t transActionId;
|
||||
dhcp_link_options_params_t clientDUID;
|
||||
dhcp_duid_options_params_t clientDUID;
|
||||
uint32_t iaID;
|
||||
uint32_t timerT0;
|
||||
uint32_t timerT1;
|
||||
|
@ -93,19 +101,19 @@ typedef struct dhcpv6_ia_nontemp_addres_entry_t {
|
|||
typedef struct dhcpv6_client_server_entry_s {
|
||||
int8_t interfaceId;
|
||||
uint8_t instanceId; // instance identifying specific client
|
||||
uint8_t dyn_server_duid_length;
|
||||
bool useServerAddress; //This indicate
|
||||
bool iaNonTemporalStructValid;
|
||||
bool GlobalAddress;
|
||||
uint8_t server_address[16];
|
||||
uint8_t serverLinkId[8];
|
||||
uint16_t serverLinkType;
|
||||
uint8_t clientId[8];
|
||||
uint16_t clientLinkIdType;
|
||||
uint8_t *serverDynamic_DUID;
|
||||
uint32_t T0;
|
||||
uint32_t T1;
|
||||
uint32_t IAID; //Take random for that
|
||||
uint32_t transActionId; //Client save this and use for get
|
||||
uint32_t reNewTimer;
|
||||
dhcp_duid_options_params_t clientDUID;
|
||||
dhcp_duid_options_params_t serverDUID;
|
||||
dhcpv6_ia_nontemp_addres_entry_t iaNontemporalAddress; // Dynamical Part
|
||||
ns_list_link_t link; /*!< List link entry */
|
||||
} dhcpv6_client_server_data_t;
|
||||
|
@ -188,7 +196,10 @@ typedef struct dhcpv6_relay_msg {
|
|||
#define DHCPV6_SERVER_ID_MAC64_OPTION_LEN 0x000c
|
||||
/** Server Identifier END */
|
||||
/** Common for server and Client Identifier option */
|
||||
#define DHCPV6_DUID_LINK_LAYER_PLUS_TIME_TYPE 0x0001
|
||||
#define DHCPV6_DUID_EN_TYPE 0x0002
|
||||
#define DHCPV6_DUID_LINK_LAYER_TYPE 0x0003
|
||||
#define DHCPV6_DUID_UUID_TYPE 0x0004
|
||||
#define DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE 0x0006
|
||||
#define DHCPV6_DUID_HARDWARE_EUI64_TYPE 0x001b
|
||||
#define DHCPV6_DUID_HARDWARE_EUI48_TYPE 0x0001
|
||||
|
@ -226,7 +237,7 @@ typedef struct dhcpv6_relay_msg {
|
|||
|
||||
|
||||
/** DHCPv6 client Nontemporal address and server data allocate, free and search */
|
||||
dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_server_data_allocate(int8_t interfaceId, uint8_t instanceId, uint8_t *duiId, uint16_t duiLinkType, uint8_t *nonTemporalPrefix, uint8_t *serverIPv6Address);
|
||||
dhcpv6_client_server_data_t *libdhcvp6_nontemporalAddress_server_data_allocate(int8_t interfaceId, uint8_t instanceId, uint8_t *nonTemporalPrefix, uint8_t *serverIPv6Address);
|
||||
void libdhcvp6_nontemporalAddress_server_data_free(dhcpv6_client_server_data_t *removedEntry);
|
||||
|
||||
uint32_t libdhcpv6_renew_time_define(dhcpv6_client_server_data_t *addresInfo);
|
||||
|
@ -262,26 +273,29 @@ int libdhcpv6_message_option_discover(uint8_t *ptr, uint16_t data_len, uint16_t
|
|||
#define libdhcpv6_client_last_transaction_time_option_size() 8
|
||||
|
||||
/** Dynamic Option lengths */
|
||||
uint16_t libdhcpv6_duid_option_size(uint16_t linkType);
|
||||
uint16_t libdhcpv6_duid_option_size(uint16_t duidLength);
|
||||
uint8_t libdhcpv6_duid_linktype_size(uint16_t linkType);
|
||||
uint16_t libdhcvp6_request_option_size(uint8_t optionCnt);
|
||||
uint16_t libdhcpv6_non_temporal_address_size(bool addressDefined);
|
||||
|
||||
uint16_t libdhcpv6_solication_message_length(uint16_t clientLinkType, bool addressDefined, uint8_t requestOptionCount);
|
||||
uint16_t libdhcpv6_address_request_message_len(uint16_t clientLinkType, uint16_t serverLinkType, uint8_t requstOptionCnt, bool add_address);
|
||||
uint16_t libdhcpv6_solication_message_length(uint16_t clientDUIDLength, bool addressDefined, uint8_t requestOptionCount);
|
||||
uint16_t libdhcpv6_address_request_message_len(uint16_t clientDUIDLength, uint16_t serverDUIDLength, uint8_t requstOptionCnt, bool add_address);
|
||||
#ifdef HAVE_DHCPV6_SERVER
|
||||
uint16_t libdhcpv6_address_reply_message_len(uint16_t clientLinkType, uint16_t serverLinkType, uint16_t vendorDataLen, bool rapidCommon, bool status);
|
||||
uint16_t libdhcpv6_address_reply_message_len(uint16_t clientDUIDLength, uint16_t serverDUIDLength, uint16_t vendorDataLen, bool rapidCommon, bool status);
|
||||
#else
|
||||
#define libdhcpv6_address_reply_message_len(clientLinkType, serverLinkType, vendorDataLen, rapidCommon, status) 0
|
||||
#define libdhcpv6_address_reply_message_len(clientDUIDLength, serverDUIDLength, vendorDataLen, rapidCommon, status) 0
|
||||
#endif
|
||||
|
||||
uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_link_options_params_t *serverLink);
|
||||
uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_duid_options_params_t *serverLink);
|
||||
uint8_t *libdhcpv6_reply_message_write(uint8_t *ptr, dhcpv6_reply_packet_s *replyPacket, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcpv6_vendor_data_packet_s *vendorData);
|
||||
uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_limit, uint8_t *peer_addres, uint8_t *link_address);
|
||||
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length);
|
||||
|
||||
int libdhcpv6_get_IA_address(uint8_t *ptr, uint16_t data_length, dhcp_ia_non_temporal_params_t *params);
|
||||
int libdhcpv6_get_duid_by_selected_type_id_opt(uint8_t *ptr, uint16_t data_length, uint16_t type, dhcp_link_options_params_t *params);
|
||||
int libdhcpv6_compare_DUID(dhcp_link_options_params_t *targetId, dhcp_link_options_params_t *parsedId);
|
||||
int libdhcpv6_get_duid_by_selected_type_id_opt(uint8_t *ptr, uint16_t data_length, uint16_t type, dhcp_duid_options_params_t *params);
|
||||
bool libdhcpv6_duid_length_validate(uint16_t duid_type, uint16_t duid_length);
|
||||
int libdhcpv6_get_link_address_from_duid(uint8_t *ptr, uint16_t data_length, uint16_t type, dhcp_link_options_params_t *params);
|
||||
int libdhcpv6_compare_DUID(dhcp_duid_options_params_t *targetId, dhcp_duid_options_params_t *parsedId);
|
||||
|
||||
/**
|
||||
* This Function write dhcpv6 basic header
|
||||
|
@ -346,23 +360,23 @@ uint8_t *libdhcvp6_request_option_write(uint8_t *ptr, uint8_t optionCnt, uint16_
|
|||
*
|
||||
* return incremented pointer after write
|
||||
*/
|
||||
uint8_t *libdhcpv6_duid_option_write(uint8_t *ptr, uint16_t duidRole, const dhcp_link_options_params_t *duid);
|
||||
uint8_t *libdhcpv6_duid_option_write(uint8_t *ptr, uint16_t duidRole, const dhcp_duid_options_params_t *duid);
|
||||
uint8_t *libdhcpv6_ia_address_option_write(uint8_t *ptr, const uint8_t *addressPtr, uint32_t preferredValidLifeTime, uint32_t validLifeTime);
|
||||
uint8_t *libdhcpv6_identity_association_option_write(uint8_t *ptr, uint32_t iaID, uint32_t TimerT1, uint32_t TimerT2, bool withAddress);
|
||||
uint8_t *libdhcpv6_identity_association_option_write_with_status(uint8_t *ptr, uint32_t iaID, uint32_t TimerT1, uint32_t TimerT2, uint16_t status);
|
||||
uint8_t *libdhcpv6_status_code_write(uint8_t *ptr, uint16_t statusCode);
|
||||
uint8_t *libdhcpv6_prefix_delegation_info_option_write(uint8_t *ptr, uint32_t iaId);
|
||||
|
||||
int libdhcpv6_reply_message_option_validate(dhcp_link_options_params_t *clientId, dhcp_link_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length);
|
||||
int libdhcpv6_reply_message_option_validate(dhcp_duid_options_params_t *clientId, dhcp_duid_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length);
|
||||
|
||||
#ifdef HAVE_DHCPV6_SERVER
|
||||
int libdhcpv6_renew_message_options_validate(uint8_t *ptr, uint16_t data_length, dhcp_link_options_params_t *clientLinkData, dhcp_link_options_params_t *serverLinkData, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params);
|
||||
int libdhcpv6_solication_message_options_validate(uint8_t *ptr, uint16_t data_length, dhcp_link_options_params_t *clientLink, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params);
|
||||
int libdhcpv6_renew_message_options_validate(uint8_t *ptr, uint16_t data_length, dhcp_duid_options_params_t *clientLinkData, dhcp_duid_options_params_t *serverLinkData, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params);
|
||||
int libdhcpv6_solication_message_options_validate(uint8_t *ptr, uint16_t data_length, dhcp_duid_options_params_t *clientLink, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params);
|
||||
#else
|
||||
#define libdhcpv6_renew_message_options_validate(ptr, data_length, clientLinkData, serverLinkData, dhcp_ia_non_temporal_params) -1
|
||||
#define libdhcpv6_solication_message_options_validate(ptr, data_length, clientLink, dhcp_ia_non_temporal_params) -1
|
||||
#endif
|
||||
int libdhcpv6_advertisment_message_option_validate(dhcp_link_options_params_t *clientId, dhcp_link_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length);
|
||||
int libdhcpv6_advertisment_message_option_validate(dhcp_duid_options_params_t *clientId, dhcp_duid_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length);
|
||||
bool libdhcpv6_rapid_commit_option_at_packet(uint8_t *ptr, uint16_t length);
|
||||
bool libdhcpv6_time_elapsed_option_at_packet(uint8_t *ptr, uint16_t length);
|
||||
bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t *relay_msg);
|
||||
|
|
|
@ -41,16 +41,22 @@ bool libdhcpv6_gua_server_list_empty(void)
|
|||
static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void)
|
||||
{
|
||||
dhcpv6_gua_server_entry_s *entry = ns_dyn_mem_alloc(sizeof(dhcpv6_gua_server_entry_s));
|
||||
if (entry) {
|
||||
entry->clientIdSequence = 0;
|
||||
entry->enableAddressAutonous = true;
|
||||
entry->clientIdDefaultSuffics = 0x0000000;
|
||||
entry->maxSuppertedClients = 200;
|
||||
entry->validLifetime = 7200;
|
||||
entry->removeCb = NULL;
|
||||
entry->addCb = NULL;
|
||||
ns_list_init(&entry->allocatedAddressList);
|
||||
uint8_t *server_duid_ptr = ns_dyn_mem_alloc(16);// Allocate 128-bit DUID-UUID by default it cover DUID-LL and DUID-LLTP also
|
||||
if (!entry || !server_duid_ptr) {
|
||||
ns_dyn_mem_free(entry);
|
||||
ns_dyn_mem_free(server_duid_ptr);
|
||||
return NULL;
|
||||
}
|
||||
entry->serverDynamic_DUID = server_duid_ptr;
|
||||
entry->serverDynamic_DUID_length = 16;
|
||||
entry->clientIdSequence = 0;
|
||||
entry->enableAddressAutonous = true;
|
||||
entry->clientIdDefaultSuffics = 0x0000000;
|
||||
entry->maxSuppertedClients = 200;
|
||||
entry->validLifetime = 7200;
|
||||
entry->removeCb = NULL;
|
||||
entry->addCb = NULL;
|
||||
ns_list_init(&entry->allocatedAddressList);
|
||||
return entry;
|
||||
}
|
||||
static void libdhcpv6_address_generate(dhcpv6_gua_server_entry_s *serverInfo, dhcpv6_alloacted_address_entry_t *entry)
|
||||
|
@ -141,19 +147,58 @@ dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_socketinstanc
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int libdhcpv6_server_duid_set(dhcpv6_gua_server_entry_s *server_info, uint8_t *duid_ptr, uint16_t duid_type, uint8_t duid_length)
|
||||
{
|
||||
//Allocate dynamically new Server DUID if needed
|
||||
if (duid_length > server_info->serverDynamic_DUID_length) {
|
||||
//Allocate dynamic new bigger
|
||||
uint8_t *new_ptr = ns_dyn_mem_alloc(duid_length);
|
||||
if (!new_ptr) {
|
||||
return -1;
|
||||
}
|
||||
server_info->serverDynamic_DUID_length = duid_length;
|
||||
ns_dyn_mem_free(server_info->serverDynamic_DUID);
|
||||
server_info->serverDynamic_DUID = new_ptr;
|
||||
}
|
||||
//SET DUID
|
||||
server_info->serverDUID.duid = server_info->serverDynamic_DUID;
|
||||
memcpy(server_info->serverDUID.duid, duid_ptr, duid_length);
|
||||
server_info->serverDUID.duid_length = duid_length;
|
||||
server_info->serverDUID.type = duid_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType)
|
||||
{
|
||||
|
||||
|
||||
dhcpv6_gua_server_entry_s *entry = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefix);
|
||||
if (entry == NULL) {
|
||||
entry = libdhcpv6_server_entry_allocate();
|
||||
if (entry) {
|
||||
memcpy(entry->guaPrefix, prefix, 8);
|
||||
memcpy(entry->serverDUID, serverDUID, 8);
|
||||
entry->serverLinkType = serverDUIDType;
|
||||
entry->interfaceId = interfaceId;
|
||||
ns_list_add_to_end(&dhcpv6_gua_server_list, entry);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
//Generate Server DUID-LL by default
|
||||
uint8_t *ptr;
|
||||
uint8_t duid_ll[16];
|
||||
uint8_t duid_length;
|
||||
ptr = duid_ll;
|
||||
duid_length = libdhcpv6_duid_linktype_size(serverDUIDType) + 2;
|
||||
ptr = common_write_16_bit(serverDUIDType, ptr);
|
||||
memcpy(ptr, serverDUID, libdhcpv6_duid_linktype_size(serverDUIDType));
|
||||
|
||||
//SET DUID
|
||||
if (libdhcpv6_server_duid_set(entry, duid_ll, DHCPV6_DUID_LINK_LAYER_TYPE, duid_length) != 0) {
|
||||
ns_dyn_mem_free(entry->serverDynamic_DUID);
|
||||
ns_dyn_mem_free(entry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
memcpy(entry->guaPrefix, prefix, 8);
|
||||
entry->interfaceId = interfaceId;
|
||||
ns_list_add_to_end(&dhcpv6_gua_server_list, entry);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
@ -168,6 +213,7 @@ void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t
|
|||
ns_dyn_mem_free(cur);
|
||||
}
|
||||
ns_list_remove(&dhcpv6_gua_server_list, serverInfo);
|
||||
ns_dyn_mem_free(serverInfo->serverDynamic_DUID);
|
||||
ns_dyn_mem_free(serverInfo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#ifdef HAVE_DHCPV6_SERVER
|
||||
#include "ns_list.h"
|
||||
|
||||
#include "libDHCPv6/libDHCPv6.h"
|
||||
|
||||
typedef void (dhcp_address_prefer_remove_cb)(int8_t interfaceId, uint8_t *targetAddress, void *prefix_info);
|
||||
|
||||
typedef struct dhcpv6_alloacted_address_entry_s {
|
||||
|
@ -59,17 +61,18 @@ typedef struct dhcp_address_cache_update {
|
|||
typedef bool (dhcp_address_add_notify_cb)(int8_t interfaceId, dhcp_address_cache_update_t *address_info, void *route_src);
|
||||
|
||||
typedef struct dhcpv6_gua_server_entry_s {
|
||||
int8_t interfaceId;
|
||||
bool enableAddressAutonous;
|
||||
uint16_t socketInstance_id;
|
||||
uint8_t guaPrefix[8];
|
||||
uint8_t serverDUID[8];
|
||||
uint16_t serverLinkType;
|
||||
uint32_t maxSuppertedClients;
|
||||
uint32_t clientIdDefaultSuffics;
|
||||
uint32_t clientIdSequence; /*!< Define */
|
||||
uint32_t validLifetime;
|
||||
dhcp_address_prefer_remove_cb *removeCb;
|
||||
int8_t interfaceId;
|
||||
bool enableAddressAutonous;
|
||||
uint16_t socketInstance_id;
|
||||
uint8_t guaPrefix[8];
|
||||
uint8_t serverDynamic_DUID_length;
|
||||
uint32_t maxSuppertedClients;
|
||||
uint32_t clientIdDefaultSuffics;
|
||||
uint32_t clientIdSequence; /*!< Define */
|
||||
uint32_t validLifetime;
|
||||
dhcp_duid_options_params_t serverDUID;
|
||||
uint8_t *serverDynamic_DUID;
|
||||
dhcp_address_prefer_remove_cb *removeCb;
|
||||
dhcp_address_add_notify_cb *addCb;
|
||||
dhcpv6_alloacted_address_list_t allocatedAddressList;
|
||||
ns_list_link_t link; /*!< List link entry */
|
||||
|
@ -77,6 +80,7 @@ typedef struct dhcpv6_gua_server_entry_s {
|
|||
|
||||
bool libdhcpv6_gua_server_list_empty(void);
|
||||
dhcpv6_gua_server_entry_s *libdhcpv6_gua_server_allocate(uint8_t *prefix, int8_t interfaceId, uint8_t *serverDUID, uint16_t serverDUIDType);
|
||||
int libdhcpv6_server_duid_set(dhcpv6_gua_server_entry_s *server_info, uint8_t *duid_ptr, uint16_t duid_type, uint8_t duid_length);
|
||||
void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t interfaceId);
|
||||
void libdhcpv6_gua_servers_time_update(uint32_t timeUpdateInSeconds);
|
||||
void libdhcpv6_address_rm_from_allocated_list(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address);
|
||||
|
|
Loading…
Reference in New Issue