Merge commit '9a4e8a5964c54f2a983ffd4c13755176d4f9df52'

* commit '9a4e8a5964c54f2a983ffd4c13755176d4f9df52':
  Squashed 'connectivity/nanostack/sal-stack-nanostack/' changes from 48609aeded..d879e6db87
pull/13562/head
Arto Kinnunen 2020-09-07 14:38:37 +03:00
commit b25f05b035
58 changed files with 2728 additions and 429 deletions

View File

@ -109,6 +109,15 @@ typedef int (dhcp_service_receive_req_cb)(uint16_t instance_id, uint32_t msg_tr_
typedef int (dhcp_service_receive_resp_cb)(uint16_t instance_id, void *ptr, uint8_t msg_name, uint8_t *msg_ptr, uint16_t msg_len);
/**
* \brief Neighbour table update callback this is called for DHCP relay and server link local responses.
*
* \param interface interface where address is got
* \param ll_addr Link local which neighbour must be guarantee.
*
*/
typedef void (dhcp_relay_neighbour_cb)(int8_t interface, uint8_t ll_addr[static 16]);
/**
* \brief Initialize a new DHCP service instance.
@ -235,5 +244,16 @@ void dhcp_service_req_remove_all(void *msg_class_ptr);
*/
bool dhcp_service_timer_tick(uint16_t ticks);
/**
* \brief Register callback which is called when Relay or server RX direct message.
*
* \param interface_id Interface id for registed callback.
* \param notify_cb callback pointer
*
* \return 0, if everything went fine.
* \return -1, if error occurred.
*/
int dhcp_service_link_local_rx_cb_set(int8_t interface_id, dhcp_relay_neighbour_cb *notify_cb);
#endif //DHCP_SERVICE_API_H_

View File

@ -267,7 +267,6 @@ typedef enum {
macEdfeForceStop = 0xf2, /*< Use this command for Data wait timeout at LLC: Mac stop Edfe session data wait and enable normal FHSS mode */
macSetDataWhitening = 0xf3, /*< Enable or disable data whitening, boolean true for enable, false for disable */
macCCAThresholdStart = 0xf4, /*< Start automatic CCA threshold */
macDevicePendingAckTrig = 0xf5, /*< Trig Pending ACK for Accepted Data packet for temporary neighbour */
mac802_15_4Mode = 0xf6, /*<IEEE 802.15.4 mode*/
macDeviceDescriptionPanIDUpdate = 0xf7, /*<Thread pending link update case this will update device descrioton list pan-id to new one*/
macTXPower = 0xf8, /*<TX output power*/

View File

@ -868,6 +868,74 @@ extern int8_t arm_net_address_add_to_interface(int8_t interface_id, const uint8_
*/
extern int8_t arm_net_address_delete_from_interface(int8_t interface_id, const uint8_t address[16]);
/**
* \brief A function to Get DNS server address learned by the interface setup
*
* If interface has learned DNS server address during the setup it can be used by
* the DNS client in that interface. This may return more than one address with DNS search list
*
* DNS server address can be learned from multiple routes
* * Router advertisements from Ethernet or LTE interfaces
* * DHCPv6 address generation
*
* If this address is not working DNS client should retry queries to other DNS servers
*
* Address is written to the buffer of the caller.
*
* DNS search list is given as pointer to stack memory where the data is present.
*
* This function should be called in loop with increasing index value starting
* from 0 until error is returned.
*
* \param interface_id Network interface ID. If set to -1 all interfaces are used
* \param address The address of the DNS server.
* \param dns_search_list_ptr pointer of pointer where dns search list data is pointing.
* \param dns_search_list_len pointer where.length of search list data
* \param index DNS address index that is read by the client. if that index is not available < -1 returned
*
* \return 0 on success, -1 on errors.
*/
extern int8_t arm_net_dns_server_get(int8_t interface_id, uint8_t address[16], uint8_t **dns_search_list_ptr, uint8_t *dns_search_list_len, uint8_t index);
/**
* \brief A function to store cached DNS Query results
*
* Possibility to store or clear DNS query results to the stack.
*
* These are static query results that can be entered to specific interface.
* These are bound to single interface to allow making the actual query through other interface
*
* Lifetime should be set in value where new DNS entry is refreshed by application.
* This would be useful in case where servers are having DNS based load balancing.
*
* \param interface_id Network interface ID.
* \param address The IPv6 address of the domain. NULL to delete
* \param domain_name_ptr Domain name of the host.
* \param lifetime Lifetime of the entry 0 to delete.
*
* \return 0 on success, < 0 on errors.
*/
extern int8_t arm_net_dns_query_result_set(int8_t interface_id, const uint8_t address[16], const char *domain_name_ptr, uint32_t lifetime);
/**
* \brief A function to Get cached DNS Query results
*
* If interface has learned DNS query results during the setup or operation.
*
* These are static query results that should be checked if the DNS did not find own
* cache entry.
*
* These will be updated during the lifetime and can be unavailable some time during
* the operation. This function should be called always to see if there is more recent data available.
*
* \param interface_id Network interface ID. If set to -1 all interfaces are used
* \param address Return the IPv6 address of the domain.
* \param domain_name_ptr Domain name where address query is made.
*
* \return 0 on success, -1 on errors.
*/
extern int8_t arm_net_dns_query_result_get(int8_t interface_id, uint8_t address[16], char *domain_name_ptr);
/**
* \brief A function to add a route to the routing table.
* \param prefix Destination prefix for the route to be added.

View File

@ -62,6 +62,18 @@ typedef struct bbr_route_info {
uint8_t parent[8];
} bbr_route_info_t;
/**
* \brief Struct bbr_radius_timing_t is RADIUS timing configuration structure.
*/
typedef struct bbr_radius_timing {
/** RADIUS retry timer Imin; in 100ms units; range 1-1200; default 20 (2 seconds) */
uint16_t radius_retry_imin;
/** RADIUS retry timer Imax; in 100ms units; range 1-1200; default 30 (3 seconds) */
uint16_t radius_retry_imax;
/** RADIUS retry count; default 3 */
uint8_t radius_retry_count;
} bbr_radius_timing_t;
/**
* Start backbone border router service.
*
@ -394,7 +406,9 @@ int ws_bbr_radius_address_get(int8_t interface_id, uint8_t *address);
*
* Function sets RADIUS shared secret to Border Router. Shared secret may be an
* ASCII string. Check the format and length constraints for the shared secret from
* the documentation of RADIUS server you are connecting to.
* the documentation of RADIUS server you are connecting to. Nanostack will not
* make copy of the shared secret, therefore address and data must remain permanently
* valid.
*
* \param interface_id Network interface ID.
* \param shared_secret_len The length of the shared secret in bytes.
@ -409,7 +423,7 @@ int ws_bbr_radius_shared_secret_set(int8_t interface_id, const uint16_t shared_s
/**
* Get RADIUS shared secret
*
* Function gets RADIUS shared secret to Border Router.
* Function gets RADIUS shared secret from Border Router.
*
* \param interface_id Network interface ID.
* \param shared_secret_len On function call, is the size of the shared secret write buffer in bytes, on return is the shared secret length in bytes.
@ -421,4 +435,71 @@ int ws_bbr_radius_shared_secret_set(int8_t interface_id, const uint16_t shared_s
*/
int ws_bbr_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret_len, uint8_t *shared_secret);
/**
* Set RADIUS timing information
*
* Function sets RADIUS timing information to Border Router.
*
* \param interface_id Network interface ID.
* \param timing Timing information
*
* \return < 0 failure
* \return >= 0 success
*
*/
int ws_bbr_radius_timing_set(int8_t interface_id, bbr_radius_timing_t *timing);
/**
* Get RADIUS timing information
*
* Function sets RADIUS timing information from Border Router.
*
* \param interface_id Network interface ID.
* \param timing Timing information
*
* \return < 0 failure
* \return >= 0 success
*
*/
int ws_bbr_radius_timing_get(int8_t interface_id, bbr_radius_timing_t *timing);
/**
* Validate RADIUS timing information
*
* Function validates RADIUS timing information.
*
* \param interface_id Network interface ID.
* \param timing Timing information
*
* \return < 0 failure
* \return >= 0 success
*
*/
int ws_bbr_radius_timing_validate(int8_t interface_id, bbr_radius_timing_t *timing);
/**
* \brief A function to set DNS query results to border router
*
* Border router distributes these query results in DHCP Solicit responses to
* all the devices joining to the Wi-SUN mesh network.
*
* Border router keeps these forever, but if application does not update these in regular interval
* The address might stop working. So periodic keep alive is required.
*
* These cached query results will become available in the Wi-SUN interface.
*
* This function can be called multiple times.
* if domain name matches a existing entry address is updated.
* If domain name is set to NULL entire list is cleared
* if address is set to NULL the Domain name is removed from the list.
*
* \param interface_id Network interface ID.
* \param address The address of the DNS query result.
* \param domain_name_ptr Domain name matching the address
*
* \return < 0 failure
* \return >= 0 success
*/
int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16], char *domain_name_ptr);
#endif /* WS_BBR_API_H_ */

View File

@ -30,6 +30,7 @@
#include "ns_types.h"
#include "net_interface.h" /* Declaration for channel_list_s. */
#include "fhss_config.h"
#ifdef __cplusplus
extern "C" {
@ -112,6 +113,8 @@ typedef struct ws_stack_info {
uint8_t rsl_out;
/** parent RSSI in measured RSSI value calculated using EWMA specified by Wi-SUN from range of -174 (0) to +80 (254) dBm.*/
uint8_t rsl_in;
/** Device RF minimum sensitivity configuration. lowest level of radio signal strength packet heard. Range of -174 (0) to +80 (254) dBm*/
uint8_t device_min_sens;
/** ETX To border router */
uint16_t routing_cost;
/** Network PAN ID */
@ -614,6 +617,30 @@ int ws_stack_info_get(
int8_t interface_id,
ws_stack_info_t *info_ptr);
/**
* Set minimum RF sensitivity acceptable for the parent selection
*
* Set radio signal minimum sensitivity level acceptable for parent selection.
* Range of -174 (0) to +80 (254) dBm.
*
* If device_min_sens is set to 0 then automatic adjustment is done by the stack.
*
* Setting a value that is not suitable for Radio might prevent the device joining to the network.
*
* NOTE: Currently lower EAPOL parents are accepted if there is no parents higher than
* DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERESIS
* NOTE: Currently not using this value to limit parents as it is only RECOMENDED in specification.
*
* \param interface_id Network interface ID.
* \param device_min_sens value used in the parent selections.
*
* \return 0 Success.
* \return <0 Failure.
*/
int ws_device_min_sens_set(
int8_t interface_id,
uint8_t device_min_sens);
#ifdef __cplusplus
}
#endif

View File

@ -947,21 +947,6 @@ void mac_helper_devicetable_direct_set(struct mac_api_s *mac_api, const mlme_dev
mac_api->mlme_req(mac_api, MLME_SET, &set_req);
}
void mac_helper_devicetable_ack_trig(const mlme_device_descriptor_t *device_desc, protocol_interface_info_entry_t *cur)
{
if (!cur->mac_api) {
return;
}
mlme_set_t set_req;
set_req.attr = macDevicePendingAckTrig;
set_req.attr_index = 0;
set_req.value_pointer = (void *)device_desc;
set_req.value_size = sizeof(mlme_device_descriptor_t);
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
}
int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);

View File

@ -128,8 +128,6 @@ void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_dec, stru
void mac_helper_devicetable_direct_set(struct mac_api_s *mac_api, const mlme_device_descriptor_t *device_desc, uint8_t attribute_index);
void mac_helper_devicetable_ack_trig(const mlme_device_descriptor_t *device_desc, struct protocol_interface_info_entry *cur);
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);

View File

@ -19,6 +19,7 @@
#include "nsconfig.h"
#include "ns_types.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "net_interface.h"
#include "socket_api.h"
#include "eventOS_event.h"
@ -41,6 +42,9 @@
#include "6LoWPAN/ws/ws_pae_controller.h"
#include "DHCPv6_Server/DHCPv6_server_service.h"
#include "DHCPv6_client/dhcpv6_client_api.h"
#include "libDHCPv6/libDHCPv6_vendordata.h"
#include "libNET/src/net_dns_internal.h"
#include "ws_bbr_api.h"
@ -73,6 +77,9 @@ static uint8_t current_global_prefix[16] = {0}; // DHCP requires 16 bytes prefix
static uint32_t bbr_delay_timer = BBR_CHECK_INTERVAL; // initial delay.
static uint32_t global_prefix_unavailable_timer = 0; // initial delay.
static uint8_t *dhcp_vendor_data_ptr = NULL;
static uint8_t dhcp_vendor_data_len = 0;
static rpl_dodag_conf_t rpl_conf = {
// Lifetime values
.default_lifetime = 120,
@ -88,6 +95,17 @@ static rpl_dodag_conf_t rpl_conf = {
.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL
};
typedef struct dns_resolution {
/** Resolved address for the domain*/
uint8_t address[16];
/** Domain name string */
char *domain_name;
} dns_resolution_t;
#define MAX_DNS_RESOLUTIONS 4
static dns_resolution_t pre_resolved_dns_queries[MAX_DNS_RESOLUTIONS] = {0};
static void ws_bbr_rpl_version_timer_start(protocol_interface_info_entry_t *cur, uint8_t version)
{
// Set the next timeout value for version update
@ -364,6 +382,48 @@ static bool wisun_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_upd
return true;
}
static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *cur, uint8_t *global_id)
{
//add DNS server information to DHCP server that is learned from the backbone interface.
uint8_t dns_server_address[16];
uint8_t *dns_search_list_ptr = NULL;
uint8_t dns_search_list_len = 0;
(void)cur;
if (net_dns_server_get(backbone_interface_id, dns_server_address, &dns_search_list_ptr, &dns_search_list_len, 0) == 0) {
/*Only supporting one DNS server address*/
DHCPv6_server_service_set_dns_server(cur->id, global_id, dns_server_address, dns_search_list_ptr, dns_search_list_len);
}
//TODO Generate vendor data in Wi-SUN network include the cached DNS query results in some sort of TLV format
int vendor_data_len = 0;
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
if (pre_resolved_dns_queries[n].domain_name != NULL) {
vendor_data_len += net_dns_option_vendor_option_data_dns_query_length(pre_resolved_dns_queries[n].domain_name);
}
}
if (vendor_data_len) {
ns_dyn_mem_free(dhcp_vendor_data_ptr);
dhcp_vendor_data_ptr = ns_dyn_mem_alloc(vendor_data_len);
if (!dhcp_vendor_data_ptr) {
tr_warn("Vendor info set fail");
return;
}
dhcp_vendor_data_len = vendor_data_len;
}
if (dhcp_vendor_data_ptr) {
// Write vendor data
uint8_t *ptr = dhcp_vendor_data_ptr;
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
if (pre_resolved_dns_queries[n].domain_name != NULL) {
ptr = net_dns_option_vendor_option_data_dns_query_write(ptr, pre_resolved_dns_queries[n].address, pre_resolved_dns_queries[n].domain_name);
tr_info("set DNS query result for %s, addr: %s", pre_resolved_dns_queries[n].domain_name, tr_ipv6(pre_resolved_dns_queries[n].address));
}
}
}
DHCPv6_server_service_set_vendor_data(cur->id, global_id, ARM_ENTERPRISE_NUMBER, dhcp_vendor_data_ptr, dhcp_vendor_data_len);
}
static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8_t *global_id, uint32_t dhcp_address_lifetime)
{
uint8_t ll[16];
@ -384,6 +444,8 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8
//SEt max value for not limiting address allocation
DHCPv6_server_service_set_max_clients_accepts_count(cur->id, global_id, MAX_SUPPORTED_ADDRESS_LIST_SIZE);
ws_bbr_dhcp_server_dns_info_update(cur, global_id);
ws_dhcp_client_address_request(cur, global_id, ll);
}
static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_t *global_id)
@ -570,6 +632,7 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
// Add also global prefix and route to RPL
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, WS_ROUTE_LIFETIME, false);
}
ws_bbr_dhcp_server_dns_info_update(cur, current_global_prefix);
}
}
void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur)
@ -1137,3 +1200,115 @@ int ws_bbr_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret
return -1;
#endif
}
int ws_bbr_radius_timing_set(int8_t interface_id, bbr_radius_timing_t *timing)
{
#ifdef HAVE_WS_BORDER_ROUTER
return ws_pae_controller_radius_timing_set(interface_id, timing);
#else
(void) interface_id;
(void) timing;
return -1;
#endif
}
int ws_bbr_radius_timing_get(int8_t interface_id, bbr_radius_timing_t *timing)
{
#ifdef HAVE_WS_BORDER_ROUTER
return ws_pae_controller_radius_timing_get(interface_id, timing);
#else
(void) interface_id;
(void) timing;
return -1;
#endif
}
int ws_bbr_radius_timing_validate(int8_t interface_id, bbr_radius_timing_t *timing)
{
#ifdef HAVE_WS_BORDER_ROUTER
return ws_pae_controller_radius_timing_validate(interface_id, timing);
#else
(void) interface_id;
(void) timing;
return -1;
#endif
}
int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16], char *domain_name_ptr)
{
#ifdef HAVE_WS_BORDER_ROUTER
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return -1;
}
/* This information is only stored to the DHCPv6 server where it is distributed to the network
*
* Border router stores a list of these entries and includes a function to parse and generate the vendor data output
*
* This is included in the vendor extension where the format is decided by the vendor
*/
// Delete all entries
if (!domain_name_ptr) {
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
// Delete all entries
memset(pre_resolved_dns_queries[n].address, 0, 16);
ns_dyn_mem_free(pre_resolved_dns_queries[n].domain_name);
pre_resolved_dns_queries[n].domain_name = NULL;
}
goto update_information;
}
// Update existing entries or delete
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
if (pre_resolved_dns_queries[n].domain_name != NULL &&
strcasecmp(pre_resolved_dns_queries[n].domain_name, domain_name_ptr) == 0) {
// Matching query updated
if (address) {
// Update address
memcpy(pre_resolved_dns_queries[n].address, address, 16);
} else {
// delete entry
memset(pre_resolved_dns_queries[n].address, 0, 16);
ns_dyn_mem_free(pre_resolved_dns_queries[n].domain_name);
pre_resolved_dns_queries[n].domain_name = NULL;
}
goto update_information;
}
}
if (address && domain_name_ptr) {
// Store new entry to the list
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
if (pre_resolved_dns_queries[n].domain_name == NULL) {
// Free entry found
pre_resolved_dns_queries[n].domain_name = ns_dyn_mem_alloc(strlen(domain_name_ptr) + 1);
if (!pre_resolved_dns_queries[n].domain_name) {
// Out of memory
return -2;
}
memcpy(pre_resolved_dns_queries[n].address, address, 16);
strcpy(pre_resolved_dns_queries[n].domain_name, domain_name_ptr);
goto update_information;
}
}
// No room to store new field
return -3;
}
update_information:
if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
// Not in active state so changes are activated after start
return 0;
}
ws_bbr_dhcp_server_dns_info_update(cur, current_global_prefix);
return 0;
#else
(void) interface_id;
(void) address;
(void) domain_name_ptr;
return -1;
#endif
}

View File

@ -63,7 +63,9 @@
#include "Service_Libs/nd_proxy/nd_proxy.h"
#include "Service_Libs/blacklist/blacklist.h"
#include "platform/topo_trace.h"
#include "dhcp_service_api.h"
#include "libDHCPv6/libDHCPv6.h"
#include "libDHCPv6/libDHCPv6_vendordata.h"
#include "DHCPv6_client/dhcpv6_client_api.h"
#include "ws_management_api.h"
#include "net_rpl.h"
@ -72,6 +74,7 @@
#include "6LoWPAN/ws/ws_eapol_pdu.h"
#include "6LoWPAN/ws/ws_eapol_auth_relay.h"
#include "6LoWPAN/ws/ws_eapol_relay.h"
#include "libNET/src/net_dns_internal.h"
#define TRACE_GROUP "wsbs"
@ -136,14 +139,37 @@ mac_neighbor_table_entry_t *ws_bootstrap_mac_neighbor_add(struct protocol_interf
}
// TODO only call these for new neighbour
mlme_device_descriptor_t device_desc;
neighbor->lifetime = WS_NEIGHBOR_LINK_TIMEOUT;
neighbor->link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT;
tr_debug("Added new neighbor %s : index:%u", trace_array(src64, 8), neighbor->index);
neighbor->lifetime = WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME;
neighbor->link_lifetime = WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME;
mac_helper_device_description_write(interface, &device_desc, neighbor->mac64, neighbor->mac16, 0, false);
mac_helper_devicetable_set(&device_desc, interface, neighbor->index, interface->mac_parameters->mac_default_key_index, true);
return neighbor;
}
void ws_bootstrap_neighbor_set_stable(struct protocol_interface_info_entry *interface, const uint8_t *src64)
{
mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), src64, MAC_ADDR_MODE_64_BIT);
if (neighbor && neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) {
neighbor->lifetime = WS_NEIGHBOR_LINK_TIMEOUT;
neighbor->link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT;
tr_info("Added new neighbor %s : index:%u", trace_array(src64, 8), neighbor->index);
}
}
void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_entry *interface, const uint8_t *src64, uint32_t valid_time)
{
mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), src64, MAC_ADDR_MODE_64_BIT);
if (neighbor && neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) {
//mlme_device_descriptor_t device_desc;
neighbor->lifetime = valid_time;
neighbor->link_lifetime = valid_time;
tr_debug("Set short response neighbor %s : index:%u", trace_array(src64, 8), neighbor->index);
}
}
static void ws_bootstrap_neighbor_delete(struct protocol_interface_info_entry *interface, mac_neighbor_table_entry_t *entry_ptr)
{
mac_helper_devicetable_remove(interface->mac_api, entry_ptr->index, entry_ptr->mac64);
@ -161,6 +187,7 @@ static void ws_bootstap_eapol_neigh_entry_allocate(struct protocol_interface_inf
if (!mac_entry) {
return;
}
ws_bootstrap_neighbor_set_stable(interface, mac_64);
mac_entry->lifetime = 0xffffffff;
mac_entry->link_lifetime = 0xffffffff;
ws_neighbor_class_entry_t *ws_neigh = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, mac_entry->index);
@ -170,14 +197,6 @@ static void ws_bootstap_eapol_neigh_entry_allocate(struct protocol_interface_inf
interface->ws_info->eapol_tx_index = mac_entry->index;
}
void ws_bootstrap_eapol_rx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64)
{
mlme_device_descriptor_t device_desc;
mac_helper_device_description_write(interface, &device_desc, src64, 0xffff, 0, false);
mac_helper_devicetable_ack_trig(&device_desc, interface);
}
ws_neighbor_class_entry_t *ws_bootstrap_eapol_tx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64)
{
mlme_device_descriptor_t device_desc;
@ -838,6 +857,97 @@ bool ws_bootstrap_nd_ns_transmit(protocol_interface_info_entry_t *cur, ipv6_neig
return true;
}
static void ws_bootstrap_dhcp_neighbour_update_cb(int8_t interface_id, uint8_t ll_addr[static 16])
{
if (memcmp(ll_addr, ADDR_LINK_LOCAL_PREFIX, 8)) {
return;
}
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur) {
return;
}
uint8_t mac64[8];
memcpy(mac64, ll_addr + 8, 8);
mac64[0] ^= 2;
ws_bootstrap_mac_neighbor_short_time_set(cur, mac64, WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME);
}
static void ws_bootstrap_dhcp_info_notify_cb(int8_t interface, dhcp_option_notify_t *options, dhcp_server_notify_info_t *server_info)
{
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface);
if (!cur) {
return;
}
uint8_t server_ll64[16];
memcpy(server_ll64, ADDR_LINK_LOCAL_PREFIX, 8);
if (server_info->duid_length == 8) {
memcpy(server_ll64 + 8, server_info->duid, 8);
} else {
server_ll64[8] = server_info->duid[0];
server_ll64[9] = server_info->duid[1];
server_ll64[10] = server_info->duid[2];
server_ll64[11] = 0xff;
server_ll64[12] = 0xfe;
server_ll64[13] = server_info->duid[3];
server_ll64[14] = server_info->duid[4];
server_ll64[15] = server_info->duid[5];
}
server_ll64[8] ^= 2;
switch (options->option_type) {
case DHCPV6_OPTION_VENDOR_SPECIFIC_INFO:
if (options->option.vendor_spesific.enterprise_number != ARM_ENTERPRISE_NUMBER) {
break;
}
while (options->option.vendor_spesific.data_length) {
uint16_t option_type;
char *domain;
uint8_t *address;
uint16_t option_len;
option_len = net_dns_option_vendor_option_data_get_next(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &option_type);
tr_debug("DHCP vendor specific data type:%u length %d", option_type, option_len);
//tr_debug("DHCP vendor specific data %s", trace_array(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length));
if (option_len == 0) {
// Option fields were corrupted
break;
}
if (option_type == ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT) {
// Process ARM DNS query result
domain = NULL;
address = NULL;
if (net_dns_option_vendor_option_data_dns_query_read(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &address, &domain) > 0 ||
domain || address) {
// Valid ARM DNS query entry
net_dns_query_result_set(interface, address, domain, server_info->life_time);
}
}
options->option.vendor_spesific.data_length -= option_len;
options->option.vendor_spesific.data += option_len;
}
break;
case DHCPV6_OPTION_DNS_SERVERS:
while (options->option.generic.data_length) {
net_dns_server_address_set(interface, server_ll64, options->option.generic.data, server_info->life_time);
options->option.generic.data_length -= 16;
options->option.generic.data += 16;
}
break;
case DHCPV6_OPTION_DOMAIN_LIST:
net_dns_server_search_list_set(interface, server_ll64, options->option.generic.data, options->option.generic.data_length, server_info->life_time);
break;
default:
break;
}
}
static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
{
int8_t ret_val = -1;
@ -886,8 +996,10 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
cur->if_ns_transmit = ws_bootstrap_nd_ns_transmit;
dhcp_client_init(cur->id, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE);
dhcp_service_link_local_rx_cb_set(cur->id, ws_bootstrap_dhcp_neighbour_update_cb);
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);
dhcp_client_option_notification_cb_set(cur->id, ws_bootstrap_dhcp_info_notify_cb);
ws_nud_table_reset(cur);
@ -1434,12 +1546,13 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
if (!neighbour_pointer_valid) {
return;
}
ws_bootstrap_neighbor_set_stable(cur, data->SrcAddr);
}
if (neighbour_pointer_valid) {
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64);
//Update Neighbor Broadcast and Unicast Parameters
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule);
ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt_ie, data->timestamp);
ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie);
@ -1484,7 +1597,11 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
tr_info("Updated PAN configuration own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version);
// restart PAN version timer
//Check Here Do we have a selected Primary parent
if (!cur->ws_info->configuration_learned || cur->ws_info->rpl_state == RPL_EVENT_DAO_DONE) {
cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout;
}
cur->ws_info->pan_information.pan_version = pan_version;
ws_pae_controller_gtk_hash_update(cur, gtkhash_ptr);
@ -1523,7 +1640,7 @@ static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_in
llc_neighbour_req_t neighbor_info;
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64);
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule);
}
@ -1603,6 +1720,10 @@ bool ws_bootstrap_validate_channel_function(ws_us_ie_t *ws_us, ws_bs_ie_t *ws_bs
static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, uint8_t message_type)
{
// Store weakest heard packet RSSI
if (cur->ws_info->weakest_received_rssi > data->signal_dbm) {
cur->ws_info->weakest_received_rssi = data->signal_dbm;
}
if (data->SrcAddrMode != MAC_ADDR_MODE_64_BIT) {
// Not from long address
@ -1691,7 +1812,7 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent
{
uint8_t ll_target[16];
if (mac_neighbor_info(interface)->neighbour_list_size <= mac_neighbor_info(interface)->list_total_size - WS_NON_CHILD_NEIGHBOUR_COUNT) {
if (mac_neighbor_info(interface)->neighbour_list_size <= mac_neighbor_info(interface)->list_total_size - ws_common_temporary_entry_size(mac_neighbor_info(interface)->list_total_size)) {
// Enough neighbor entries
return;
}
@ -1707,6 +1828,10 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent
continue;
}
if (cur->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) {
continue;
}
if (cur->link_role == PRIORITY_PARENT_NEIGHBOUR) {
//This is our primary parent we cannot delete
continue;
@ -1834,7 +1959,7 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr,
ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, entry_ptr->index);
etx_storage_t *etx_entry = etx_storage_entry_get(cur->id, entry_ptr->index);
if (!entry_ptr->trusted_device || !ws_neighbor || !etx_entry || ws_neighbor->negative_aro_send) {
if (!entry_ptr->trusted_device || !ws_neighbor || !etx_entry || ws_neighbor->negative_aro_send || entry_ptr->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) {
return false;
}
@ -2515,6 +2640,7 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle,
bool create_ok = ws_bootstrap_neighbor_info_request(cur, entry->mac64, &neigh_buffer, true);
if (create_ok) {
ws_neighbor_class_entry_t *ws_neigh = neigh_buffer.ws_neighbor;
ws_bootstrap_neighbor_set_stable(cur, entry->mac64);
//Copy fhss temporary data
*ws_neigh = entry->neigh_info_list;
//ETX Create here
@ -2613,6 +2739,7 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
cur->nwk_nd_re_scan_count = 0;
cur->ws_info->configuration_learned = false;
cur->ws_info->pan_timeout_timer = 0;
cur->ws_info->weakest_received_rssi = 0;
// Clear learned neighbours
ws_bootstrap_neighbor_list_clean(cur);
@ -3226,8 +3353,8 @@ static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, pa
ns_list_add_to_end(&cur->ws_info->parent_list_free, parent_ptr);
return -1;
}
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &parent_ptr->ws_utt, parent_ptr->timestamp);
ws_bootstrap_neighbor_set_stable(cur, parent_ptr->addr);
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &parent_ptr->ws_utt, parent_ptr->timestamp, parent_ptr->addr);
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &parent_ptr->ws_us, &cur->ws_info->hopping_schdule);
return 0;
}
@ -3374,6 +3501,11 @@ void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur)
cur->ws_info->trickle_pcs_running = false;
cur->ws_info->trickle_pc_consistency_block_period = 0;
ws_fhss_configure(cur, false);
int8_t new_default = cur->ws_info->weakest_received_rssi - 1;
if ((new_default < CCA_DEFAULT_DBM) && (new_default >= CCA_LOW_LIMIT) && (new_default <= CCA_HIGH_LIMIT)) {
// Restart automatic CCA threshold using weakest received RSSI as new default
mac_helper_start_auto_cca_threshold(cur->id, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->weakest_received_rssi - 1, CCA_HIGH_LIMIT, CCA_LOW_LIMIT);
}
ws_bootstrap_start_authentication(cur);
break;
case ER_RPL_SCAN:
@ -3535,6 +3667,7 @@ int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_
info_ptr->rsl_out = ws_neighbour->rsl_out;
info_ptr->routing_cost = ws_neighbour->routing_cost;
}
info_ptr->device_min_sens = DEVICE_MIN_SENS;
if (ws_bootstrap_state_discovery(cur)) {
info_ptr->join_state = 1;
} else if (ws_bootstrap_state_authenticate(cur)) {

View File

@ -86,14 +86,16 @@ bool ws_bootstrap_validate_channel_plan(struct ws_us_ie *ws_us, struct protocol_
bool ws_bootstrap_validate_channel_function(struct ws_us_ie *ws_us, struct ws_bs_ie *ws_bs);
void ws_bootstrap_eapol_rx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64);
struct ws_neighbor_class_entry *ws_bootstrap_eapol_tx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64);
void ws_bootstrap_eapol_tx_temporary_clear(struct protocol_interface_info_entry *interface);
void ws_bootstrap_neighbor_set_stable(struct protocol_interface_info_entry *interface, const uint8_t *src64);
int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_info *info_ptr);
void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_entry *interface, const uint8_t *src64, uint32_t valid_time);
#else
#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)
@ -101,10 +103,12 @@ int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_
#define ws_bootstrap_restart(cur)
#define ws_bootstrap_neighbor_remove(cur, ll_address)
#define ws_bootstrap_aro_failure(cur, ll_address)
#define ws_bootstrap_neighbor_set_stable(interface, src64)
#define ws_bootstrap_primary_parent_update(interface, neighbor)
#define ws_bootstrap_secondary_parent_update(interface)
#define ws_bootstrap_get_info(cur, info_ptr)
#endif //HAVE_WS
#endif /* WS_BOOTSTRAP_H_ */

View File

@ -379,12 +379,21 @@ void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8
ws_bootstrap_neighbor_remove(cur, ll_address);
}
uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size)
{
if (mac_table_size >= 128) {
return (WS_RPL_CANDIDATE_PARENT_COUNT + WS_LARGE_TEMPORARY_NEIGHBOUR_ENTRIES);
} else if (mac_table_size >= 64) {
return (WS_RPL_CANDIDATE_PARENT_COUNT + WS_MEDIUM_TEMPORARY_NEIGHBOUR_ENTRIES);
} else {
return (WS_RPL_CANDIDATE_PARENT_COUNT + WS_SMALL_TEMPORARY_NEIGHBOUR_ENTRIES);
}
}
uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64)
{
uint8_t child_count = 0;
uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - WS_NON_CHILD_NEIGHBOUR_COUNT;
uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - ws_common_temporary_entry_size(mac_neighbor_info(interface)->list_total_size);
// Test API to limit child count
if (test_max_child_count_override != 0xffff) {
@ -422,6 +431,7 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte
tr_warn("Child registration not allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size);
return ARO_FULL;
}
ws_bootstrap_neighbor_set_stable(interface, eui64);
tr_info("Child registration allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size);
return ARO_SUCCESS;
}

View File

@ -83,6 +83,8 @@ typedef struct ws_info_s {
uint8_t rpl_state; // state from rpl_event_t
uint8_t pas_requests; // Amount of PAN solicits sent
uint8_t eapol_tx_index;
uint8_t device_min_sens; // Device min sensitivity set by the application
int8_t weakest_received_rssi; // Weakest received signal (dBm)
parent_info_t parent_info[WS_PARENT_LIST_SIZE];
parent_info_list_t parent_list_free;
parent_info_list_t parent_list_reserved;
@ -155,6 +157,7 @@ void ws_common_primary_parent_update(protocol_interface_info_entry_t *interface,
void ws_common_secondary_parent_update(protocol_interface_info_entry_t *interface);
uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size);
#define ws_info(cur) ((cur)->ws_info)
#else
#define ws_info(cur) ((ws_info_t *) NULL)

View File

@ -240,6 +240,9 @@ typedef struct ws_bs_ie {
#define WS_FAN_VERSION_1_0 1
#define WS_NEIGHBOR_LINK_TIMEOUT 2200
#define WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME 5
#define WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME 60
#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
@ -342,7 +345,7 @@ typedef struct ws_bs_ie {
// With FHSS we need to check CCA twice on TX channel
#define WS_NUMBER_OF_CSMA_PERIODS 2
// Interval between two CCA checks
#define WS_CSMA_MULTI_CCA_INTERVAL 1000
#define WS_CSMA_MULTI_CCA_INTERVAL 2000
/* Default FHSS timing information
*

View File

@ -153,9 +153,10 @@ extern uint8_t DEVICE_MIN_SENS;
* Amount of ND reply entries left
* rest are used as child count, but is related to neighbour table size
*/
#define WS_RPL_CANDIDATE_PARENT_COUNT 3 // Largest possible value
#define WS_TEMPORARY_NEIGHBOUR_ENTRIES 7
#define WS_NON_CHILD_NEIGHBOUR_COUNT (WS_RPL_CANDIDATE_PARENT_COUNT + WS_TEMPORARY_NEIGHBOUR_ENTRIES)
#define WS_RPL_CANDIDATE_PARENT_COUNT 3
#define WS_SMALL_TEMPORARY_NEIGHBOUR_ENTRIES 7
#define WS_MEDIUM_TEMPORARY_NEIGHBOUR_ENTRIES 12
#define WS_LARGE_TEMPORARY_NEIGHBOUR_ENTRIES 22
/*
* Neighbour blacklist timers
@ -265,4 +266,18 @@ extern uint8_t DEVICE_MIN_SENS;
// How many times sending of initial EAPOL-key is retried
#define DEFAULT_INITIAL_KEY_RETRY_COUNT 2
/*
* RADIUS client retry timer defaults
*/
#define RADIUS_CLIENT_RETRY_IMIN 20 // First retry minimum 1 seconds
#define RADIUS_CLIENT_RETRY_IMAX 30 // First retry maximum 3 seconds
#define RADIUS_CLIENT_TIMER_EXPIRATIONS 3 // Number of retries is three
/*
* EAP-TLS fragment length
*
* Configures both EAP-TLS and the RADIUS client (Framed-MTU on RFC 2864)
*/
#define EAP_TLS_FRAGMENT_LEN_VALUE 600 // EAP-TLS fragment length
#endif /* WS_CONFIG_H_ */

View File

@ -66,11 +66,14 @@ int8_t ws_eapol_relay_start(protocol_interface_info_entry_t *interface_ptr, uint
return -1;
}
if (ws_eapol_relay_get(interface_ptr)) {
eapol_relay_t *eapol_relay = ws_eapol_relay_get(interface_ptr);
if (eapol_relay) {
memcpy(&eapol_relay->remote_addr.address, remote_addr, 16);
return 0;
}
eapol_relay_t *eapol_relay = ns_dyn_mem_alloc(sizeof(eapol_relay_t));
eapol_relay = ns_dyn_mem_alloc(sizeof(eapol_relay_t));
if (!eapol_relay) {
return -1;
}

View File

@ -413,4 +413,13 @@ int ws_stack_info_get(int8_t interface_id, ws_stack_info_t *info_ptr)
return -1;
}
int ws_device_min_sens_set(
int8_t interface_id,
uint8_t device_min_sens)
{
(void) interface_id;
(void) device_min_sens;
return -1;
}
#endif // no HAVE_WS

View File

@ -100,7 +100,7 @@ typedef struct {
typedef NS_LIST_HEAD(llc_message_t, link) llc_message_list_t;
#define MAX_NEIGH_TEMPORARY_MULTICAST_SIZE 5
#define MAX_NEIGH_TEMPORRY_EAPOL_SIZE 30
#define MAX_NEIGH_TEMPORRY_EAPOL_SIZE 20
#define MAX_NEIGH_TEMPORAY_LIST_SIZE (MAX_NEIGH_TEMPORARY_MULTICAST_SIZE + MAX_NEIGH_TEMPORRY_EAPOL_SIZE)
typedef struct {
@ -465,10 +465,16 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *
}
}
//ETX update
if (message->ack_requested && messsage_type == WS_FT_DATA) {
llc_neighbour_req_t neighbor_info;
neighbor_info.ws_neighbor = NULL;
neighbor_info.neighbor = NULL;
if (message->ack_requested && messsage_type == WS_FT_DATA) {
bool success = false;
if (message->dst_address_type == MAC_ADDR_MODE_64_BIT) {
base->ws_neighbor_info_request_cb(interface, message->dst_address, &neighbor_info, false);
}
switch (data->status) {
case MLME_SUCCESS:
case MLME_TX_NO_ACK:
@ -477,7 +483,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *
success = true;
}
if (message->dst_address_type == MAC_ADDR_MODE_64_BIT && base->ws_neighbor_info_request_cb(interface, message->dst_address, &neighbor_info, false)) {
if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime == WS_NEIGHBOR_LINK_TIMEOUT) {
etx_transm_attempts_update(interface->id, 1 + data->tx_retries, success, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64);
//TODO discover RSL from Enchanced ACK Header IE elements
ws_utt_ie_t ws_utt;
@ -487,7 +493,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *
neighbor_info.neighbor->lifetime = neighbor_info.neighbor->link_lifetime;
}
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp);
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp, neighbor_info.neighbor->mac64);
}
int8_t rsl;
@ -500,6 +506,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *
default:
break;
}
}
//Free message
llc_message_free(message, base);
@ -529,6 +536,12 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *
ns_list_remove(&base->temp_entries->llc_eap_pending_list, message);
ws_llc_mpx_eapol_send(base, message);
}
} else {
if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) {
//Remove temp neighbour
tr_debug("Remove Temp Entry by TX confirm");
mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), neighbor_info.neighbor);
}
}
return;
@ -689,7 +702,7 @@ static void ws_llc_data_indication_cb(const mac_api_t *api, const mcps_data_ind_
return;
}
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp);
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp, (uint8_t *) data->SrcAddr);
if (us_ie_inline) {
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie, &interface->ws_info->hopping_schdule);
}
@ -711,7 +724,8 @@ static void ws_llc_data_indication_cb(const mac_api_t *api, const mcps_data_ind_
neighbor_info.ws_neighbor->unicast_data_rx = true;
}
// Calculate RSL for all UDATA packages heard
// Calculate RSL for all UDATA packets heard
ws_neighbor_class_rf_sensitivity_calculate(interface->ws_info->device_min_sens, data->signal_dbm);
ws_neighbor_class_rsl_in_calculate(neighbor_info.ws_neighbor, data->signal_dbm);
if (neighbor_info.neighbor) {
@ -795,7 +809,7 @@ static void ws_llc_eapol_indication_cb(const mac_api_t *api, const mcps_data_ind
temp_entry->signal_dbm = data->signal_dbm;
}
uint8_t auth_eui64[8];
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp);
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp, (uint8_t *) data->SrcAddr);
if (us_ie_inline) {
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie, &interface->ws_info->hopping_schdule);
}

View File

@ -741,4 +741,18 @@ int ws_stack_info_get(int8_t interface_id, ws_stack_info_t *info_ptr)
return ws_bootstrap_get_info(cur, info_ptr);
}
int ws_device_min_sens_set(
int8_t interface_id,
uint8_t device_min_sens)
{
protocol_interface_info_entry_t *cur;
cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !ws_info(cur)) {
return -1;
}
DEVICE_MIN_SENS = device_min_sens;
ws_info(cur)->device_min_sens = device_min_sens;
return 0;
}
#endif // HAVE_WS

View File

@ -89,8 +89,44 @@ void ws_neighbor_class_entry_remove(ws_neighbor_class_t *class_data, uint8_t att
}
}
void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp)
#ifdef FEA_TRACE_SUPPORT
static int own_ceil(float value)
{
int ivalue = (int)value;
if (value == (float)ivalue) {
return ivalue;
}
return ivalue + 1;
}
static void ws_neighbor_calculate_ufsi_drift(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp, uint8_t address[8])
{
if (ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp && ws_neighbor->fhss_data.uc_timing_info.ufsi) {
uint32_t seq_length = 0x10000;
if (ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function == WS_TR51CF) {
seq_length = ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels;
}
// Convert 24-bit UFSI to real time before drift calculation
uint32_t time_since_seq_start_prev_ms = own_ceil((float)((uint64_t)ws_neighbor->fhss_data.uc_timing_info.ufsi * seq_length * ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval) / 0x1000000);
uint32_t time_since_seq_start_cur_ms = own_ceil((float)((uint64_t)ws_utt->ufsi * seq_length * ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval) / 0x1000000);
uint32_t time_since_last_ufsi_us = timestamp - ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp;
uint32_t ufsi_diff_ms = time_since_seq_start_cur_ms - time_since_seq_start_prev_ms;
int32_t ufsi_drift_ms = (int32_t)(time_since_last_ufsi_us / 1000 - ufsi_diff_ms);
// Only trace if there is significant error
if (ufsi_drift_ms < -5 || ufsi_drift_ms > 5) {
tr_debug("UFSI updated: %s, drift: %"PRIi32"ms in %"PRIu32" seconds", trace_array(address, 8), ufsi_drift_ms, time_since_last_ufsi_us / 1000000);
}
}
}
#endif
void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp, uint8_t address[8])
{
#ifdef FEA_TRACE_SUPPORT
ws_neighbor_calculate_ufsi_drift(ws_neighbor, ws_utt, timestamp, address);
#else
(void) address;
#endif
ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp = timestamp;
ws_neighbor->fhss_data.uc_timing_info.ufsi = ws_utt->ufsi;
}
@ -245,8 +281,13 @@ void ws_neighbor_class_neighbor_broadcast_schedule_set(ws_neighbor_class_entry_t
ws_neighbor->fhss_data.bc_timing_info.broadcast_schedule_id = ws_bs_ie->broadcast_schedule_identifier;
}
void ws_neighbor_class_rf_sensitivity_calculate(uint8_t rsl_heard)
void ws_neighbor_class_rf_sensitivity_calculate(uint8_t dev_min_sens_config, int8_t dbm_heard)
{
if (dev_min_sens_config != 0) {
// Automatic mode disabled
return;
}
uint8_t rsl_heard = ws_neighbor_class_rsl_from_dbm_calculate(dbm_heard);
if (DEVICE_MIN_SENS > rsl_heard) {
// We are hearing packet with lower than min_sens dynamically learn the sensitivity
DEVICE_MIN_SENS = rsl_heard;
@ -285,8 +326,6 @@ static void ws_neighbor_class_parent_set_analyze(ws_neighbor_class_entry_t *ws_n
void ws_neighbor_class_rsl_in_calculate(ws_neighbor_class_entry_t *ws_neighbor, int8_t dbm_heard)
{
uint8_t rsl = ws_neighbor_class_rsl_from_dbm_calculate(dbm_heard);
// Calculate minimum sensitivity from heard packets.
ws_neighbor_class_rf_sensitivity_calculate(rsl);
if (ws_neighbor->rsl_in == RSL_UNITITIALIZED) {
ws_neighbor->rsl_in = rsl << WS_RSL_SCALING;
}

View File

@ -106,7 +106,7 @@ void ws_neighbor_class_entry_remove(ws_neighbor_class_t *class_data, uint8_t att
* \param timestamp timestamp for received data
*
*/
void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp);
void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp, uint8_t address[8]);
/**
* ws_neighbor_class_neighbor_unicast_schedule_set a function for update neighbor unicast shedule information
@ -146,7 +146,7 @@ void ws_neighbor_class_neighbor_broadcast_schedule_set(ws_neighbor_class_entry_t
* \param rsl_heard; rsl_heard heard from Radio
*
*/
void ws_neighbor_class_rf_sensitivity_calculate(uint8_t rsl_heard);
void ws_neighbor_class_rf_sensitivity_calculate(uint8_t dev_min_sens_config, int8_t dbm_heard);
/**
* ws_neighbor_class_rsl_from_dbm_calculate

View File

@ -94,6 +94,7 @@ typedef struct {
ws_pae_auth_nw_info_updated *nw_info_updated; /**< Security keys network info updated callback */
ws_pae_auth_ip_addr_get *ip_addr_get; /**< IP address get callback */
supp_list_t active_supp_list; /**< List of active supplicants */
shared_comp_list_t shared_comp_list; /**< Shared component list */
arm_event_storage_t *timer; /**< Timer */
sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */
const sec_prot_certs_t *certs; /**< Certificates */
@ -121,6 +122,8 @@ static int8_t ws_pae_auth_timer_if_start(kmp_service_t *service, kmp_api_t *kmp)
static int8_t ws_pae_auth_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp);
static int8_t ws_pae_auth_timer_start(pae_auth_t *pae_auth);
static int8_t ws_pae_auth_timer_stop(pae_auth_t *pae_auth);
static int8_t ws_pae_auth_shared_comp_add(kmp_service_t *service, kmp_shared_comp_t *data);
static int8_t ws_pae_auth_shared_comp_remove(kmp_service_t *service, kmp_shared_comp_t *data);
static bool ws_pae_auth_timer_running(pae_auth_t *pae_auth);
static void ws_pae_auth_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr);
static void ws_pae_auth_kmp_service_ip_addr_get(kmp_service_t *service, kmp_api_t *kmp, uint8_t *address);
@ -156,6 +159,7 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
pae_auth->pan_id = 0xffff;
pae_auth->interface_ptr = interface_ptr;
ws_pae_lib_supp_list_init(&pae_auth->active_supp_list);
ws_pae_lib_shared_comp_list_init(&pae_auth->shared_comp_list);
pae_auth->timer = NULL;
pae_auth->hash_set = NULL;
@ -192,6 +196,10 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
goto error;
}
if (kmp_service_shared_comp_if_register(pae_auth->kmp_service, ws_pae_auth_shared_comp_add, ws_pae_auth_shared_comp_remove)) {
goto error;
}
if (auth_key_sec_prot_register(pae_auth->kmp_service) < 0) {
goto error;
}
@ -594,6 +602,8 @@ static void ws_pae_auth_free(pae_auth_t *pae_auth)
return;
}
ws_pae_lib_shared_comp_list_free(&pae_auth->shared_comp_list);
ws_pae_lib_supp_list_delete(&pae_auth->active_supp_list);
kmp_socket_if_unregister(pae_auth->kmp_service);
@ -741,6 +751,8 @@ void ws_pae_auth_slow_timer(uint16_t seconds)
}
ws_pae_lib_supp_list_slow_timer_update(&pae_auth->active_supp_list, seconds);
ws_pae_lib_shared_comp_list_timeout(&pae_auth->shared_comp_list, seconds);
}
// Update key storage timer
@ -837,6 +849,26 @@ static int8_t ws_pae_auth_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp)
return 0;
}
static int8_t ws_pae_auth_shared_comp_add(kmp_service_t *service, kmp_shared_comp_t *data)
{
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
if (!pae_auth) {
return -1;
}
return ws_pae_lib_shared_comp_list_add(&pae_auth->shared_comp_list, data);
}
static int8_t ws_pae_auth_shared_comp_remove(kmp_service_t *service, kmp_shared_comp_t *data)
{
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
if (!pae_auth) {
return -1;
}
return ws_pae_lib_shared_comp_list_remove(&pae_auth->shared_comp_list, data);
}
static int8_t ws_pae_auth_timer_start(pae_auth_t *pae_auth)
{
pae_auth->timer_running = true;
@ -948,7 +980,7 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, uint8_t m
kmp_type_e kmp_type_to_search = type;
// If radius is enabled, route EAP-TLS to radius EAP-TLS
if (pae_auth->sec_cfg->radius_cfg.radius_addr_set && type == IEEE_802_1X_MKA) {
if (pae_auth->sec_cfg->radius_cfg != NULL && pae_auth->sec_cfg->radius_cfg->radius_addr_set && type == IEEE_802_1X_MKA) {
kmp_type_to_search = RADIUS_IEEE_802_1X_MKA;
}
@ -1118,7 +1150,7 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry
if (sec_keys->pmk_mismatch) {
sec_keys->ptk_mismatch = true;
// start EAP-TLS towards supplicant
if (pae_auth->sec_cfg->radius_cfg.radius_addr_set) {
if (pae_auth->sec_cfg->radius_cfg != NULL && pae_auth->sec_cfg->radius_cfg->radius_addr_set) {
next_type = RADIUS_IEEE_802_1X_MKA;
} else {
next_type = IEEE_802_1X_MKA;

View File

@ -24,6 +24,7 @@
#include "fhss_config.h"
#include "ns_address.h"
#include "ws_management_api.h"
#include "ws_bbr_api.h"
#include "Service_Libs/utils/ns_file.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "6LoWPAN/ws/ws_config.h"
@ -106,6 +107,7 @@ typedef struct {
} pae_controller_t;
typedef struct {
sec_radius_cfg_t *radius_cfg; /**< Radius configuration settings */
uint16_t node_limit; /**< Max number of stored supplicants */
bool node_limit_set : 1; /**< Node limit set */
bool ext_cert_valid_enabled : 1; /**< Extended certificate validation enabled */
@ -146,13 +148,12 @@ static const char *NW_INFO_FILE = NW_INFO_FILE_NAME;
static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link);
pae_controller_config_t pae_controller_config = {
.radius_cfg = NULL,
.node_limit = 0,
.node_limit_set = false,
.ext_cert_valid_enabled = false
};
sec_radius_cfg_t *pae_controller_radius_settings;
int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr)
{
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
@ -217,16 +218,16 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in
return -1;
}
if (pae_controller_radius_settings) {
// If either address or password is set, both must be set
if (controller->sec_cfg.radius_cfg.radius_addr_set || controller->sec_cfg.radius_cfg.radius_shared_secret_len > 0) {
if (!controller->sec_cfg.radius_cfg.radius_addr_set) {
// If either radius address or password is set, both must be set
if (controller->sec_cfg.radius_cfg != NULL) {
if (controller->sec_cfg.radius_cfg->radius_addr_set || controller->sec_cfg.radius_cfg->radius_shared_secret_len > 0) {
if (!controller->sec_cfg.radius_cfg->radius_addr_set) {
return -1;
}
if (controller->sec_cfg.radius_cfg.radius_shared_secret_len == 0) {
if (controller->sec_cfg.radius_cfg->radius_shared_secret_len == 0) {
return -1;
}
if (ws_pae_auth_radius_address_set(interface_ptr, controller->sec_cfg.radius_cfg.radius_addr) < 0) {
if (ws_pae_auth_radius_address_set(interface_ptr, controller->sec_cfg.radius_cfg->radius_addr) < 0) {
return -1;
}
}
@ -704,9 +705,7 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt
ws_pae_timers_settings_init(&controller->sec_cfg.timer_cfg, sec_timer_cfg);
}
if (pae_controller_radius_settings) {
controller->sec_cfg.radius_cfg = *pae_controller_radius_settings;
}
controller->sec_cfg.radius_cfg = pae_controller_config.radius_cfg;
return 0;
}
@ -1171,36 +1170,59 @@ int8_t ws_pae_controller_certificate_revocation_list_remove(const arm_cert_revoc
return ret;
}
sec_radius_cfg_t *ws_pae_controller_radius_config_get(void)
{
if (pae_controller_config.radius_cfg != NULL) {
return pae_controller_config.radius_cfg;
}
pae_controller_config.radius_cfg = ns_dyn_mem_alloc(sizeof(sec_radius_cfg_t));
if (pae_controller_config.radius_cfg == NULL) {
return NULL;
}
pae_controller_config.radius_cfg->radius_retry_trickle_params.Imin = RADIUS_CLIENT_RETRY_IMIN;
pae_controller_config.radius_cfg->radius_retry_trickle_params.Imax = RADIUS_CLIENT_RETRY_IMAX;
pae_controller_config.radius_cfg->radius_retry_trickle_params.k = 0;
pae_controller_config.radius_cfg->radius_retry_trickle_params.TimerExpirations = RADIUS_CLIENT_TIMER_EXPIRATIONS;
pae_controller_config.radius_cfg->radius_addr_set = false;
pae_controller_config.radius_cfg->radius_shared_secret_len = 0;
pae_controller_config.radius_cfg->radius_shared_secret = NULL;
return pae_controller_config.radius_cfg;
}
int8_t ws_pae_controller_radius_address_set(int8_t interface_id, const uint8_t *address)
{
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get();
if (radius_cfg == NULL) {
return -1;
}
// If remote address is not set, clear radius information
if (!address) {
if (pae_controller_radius_settings != NULL) {
pae_controller_radius_settings->radius_addr_set = false;
}
if (controller) {
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
if (address != NULL) {
memcpy(radius_cfg->radius_addr, address, 16);
radius_cfg->radius_addr_set = true;
} else {
radius_cfg->radius_addr_set = false;
}
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
if (!controller) {
return 0;
}
if (pae_controller_radius_settings == NULL) {
pae_controller_radius_settings = ns_dyn_mem_alloc(sizeof(sec_radius_cfg_t));
if (!pae_controller_radius_settings) {
if (ws_pae_controller_configure(controller->interface_ptr, NULL, NULL) < 0) {
return -1;
}
memset(pae_controller_radius_settings, 0, sizeof(sec_radius_cfg_t));
}
memcpy(pae_controller_radius_settings->radius_addr, address, 16);
pae_controller_radius_settings->radius_addr_set = true;
if (controller) {
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
if (ws_pae_auth_radius_address_set(controller->interface_ptr, controller->sec_cfg.radius_cfg.radius_addr) < 0) {
return -1;
if (!radius_cfg->radius_addr_set) {
return 0;
}
if (ws_pae_auth_radius_address_set(controller->interface_ptr, radius_cfg->radius_addr) < 0) {
// If not set here since authenticator not created, then set on authenticator initialization
return 0;
}
return 0;
@ -1214,54 +1236,31 @@ int8_t ws_pae_controller_radius_address_get(int8_t interface_id, uint8_t *addres
return -1;
}
if (pae_controller_radius_settings == NULL || !pae_controller_radius_settings->radius_addr_set) {
sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get();
if (radius_cfg == NULL) {
return -1;
}
memcpy(address, pae_controller_radius_settings->radius_addr, 16);
if (!radius_cfg->radius_addr_set) {
return -1;
}
memcpy(address, radius_cfg->radius_addr, 16);
return 0;
}
int8_t ws_pae_controller_radius_shared_secret_set(int8_t interface_id, const uint16_t shared_secret_len, const uint8_t *shared_secret)
{
sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get();
if (radius_cfg == NULL) {
return -1;
}
radius_cfg->radius_shared_secret = shared_secret;
radius_cfg->radius_shared_secret_len = shared_secret_len;
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
// If shared secret is not set, clear radius information
if (shared_secret_len == 0 || !shared_secret) {
if (pae_controller_radius_settings != NULL) {
memset(pae_controller_radius_settings->radius_shared_secret, 0, pae_controller_radius_settings->radius_shared_secret_len);
pae_controller_radius_settings->radius_shared_secret_len = 0;
}
if (controller) {
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
}
return 0;
}
if (pae_controller_radius_settings == NULL) {
pae_controller_radius_settings = ns_dyn_mem_alloc(sizeof(sec_radius_cfg_t));
if (!pae_controller_radius_settings) {
return -1;
}
memset(pae_controller_radius_settings, 0, sizeof(sec_radius_cfg_t));
}
if (pae_controller_radius_settings->radius_shared_secret != NULL &&
pae_controller_radius_settings->radius_shared_secret_len != shared_secret_len) {
ns_dyn_mem_free(pae_controller_radius_settings->radius_shared_secret);
pae_controller_radius_settings->radius_shared_secret = NULL;
}
if (pae_controller_radius_settings->radius_shared_secret == NULL) {
pae_controller_radius_settings->radius_shared_secret = ns_dyn_mem_alloc(shared_secret_len);
if (pae_controller_radius_settings->radius_shared_secret == NULL) {
return -1;
}
}
memcpy(pae_controller_radius_settings->radius_shared_secret, shared_secret, shared_secret_len);
pae_controller_radius_settings->radius_shared_secret_len = shared_secret_len;
if (controller) {
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
}
@ -1277,16 +1276,18 @@ int8_t ws_pae_controller_radius_shared_secret_get(int8_t interface_id, uint16_t
return -1;
}
uint16_t length = 0;
if (pae_controller_radius_settings != NULL) {
length = pae_controller_radius_settings->radius_shared_secret_len;
sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get();
if (radius_cfg == NULL) {
return -1;
}
uint16_t length = radius_cfg->radius_shared_secret_len;
if (shared_secret != NULL) {
if (length > *shared_secret_len) {
length = *shared_secret_len;
}
if (length > 0 && pae_controller_radius_settings->radius_shared_secret != NULL) {
memcpy(shared_secret, pae_controller_radius_settings->radius_shared_secret, length);
}
if (length > 0 && radius_cfg->radius_shared_secret != NULL) {
memcpy(shared_secret, radius_cfg->radius_shared_secret, length);
}
}
@ -1295,6 +1296,74 @@ int8_t ws_pae_controller_radius_shared_secret_get(int8_t interface_id, uint16_t
return 0;
}
int8_t ws_pae_controller_radius_timing_set(int8_t interface_id, bbr_radius_timing_t *timing)
{
(void) interface_id;
if (timing == NULL) {
return -1;
}
sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get();
if (radius_cfg == NULL) {
return -1;
}
radius_cfg->radius_retry_trickle_params.Imin = timing->radius_retry_imin;
radius_cfg->radius_retry_trickle_params.Imax = timing->radius_retry_imax;
radius_cfg->radius_retry_trickle_params.TimerExpirations = timing->radius_retry_count;
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
if (controller) {
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
}
return 0;
}
int8_t ws_pae_controller_radius_timing_get(int8_t interface_id, bbr_radius_timing_t *timing)
{
(void) interface_id;
if (timing == NULL) {
return -1;
}
if (pae_controller_config.radius_cfg == NULL) {
timing->radius_retry_imin = RADIUS_CLIENT_RETRY_IMIN;
timing->radius_retry_imax = RADIUS_CLIENT_RETRY_IMAX;
timing->radius_retry_count = RADIUS_CLIENT_TIMER_EXPIRATIONS;
return 0;
}
sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get();
if (radius_cfg == NULL) {
return -1;
}
timing->radius_retry_imin = radius_cfg->radius_retry_trickle_params.Imin;
timing->radius_retry_imax = radius_cfg->radius_retry_trickle_params.Imax;
timing->radius_retry_count = radius_cfg->radius_retry_trickle_params.TimerExpirations;
return 0;
}
int8_t ws_pae_controller_radius_timing_validate(int8_t interface_id, bbr_radius_timing_t *timing)
{
(void) interface_id;
if (timing == NULL) {
return -1;
}
if (timing->radius_retry_imin == 0 || timing->radius_retry_imax == 0 ||
timing->radius_retry_imin > timing->radius_retry_imax) {
return -1;
}
return 0;
}
int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
{
if (!eui_64) {

View File

@ -30,6 +30,7 @@ typedef enum {
struct nvm_tlv_entry;
struct ws_sec_timer_cfg_s;
struct ws_sec_prot_cfg_s;
struct bbr_radius_timing;
/**
* ws_pae_controller_set_target sets EAPOL target for PAE supplicant
@ -282,6 +283,42 @@ int8_t ws_pae_controller_radius_shared_secret_set(int8_t interface_id, const uin
*/
int8_t ws_pae_controller_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret_len, uint8_t *shared_secret);
/**
* ws_pae_controller_radius_timing_set set radius timing information
*
* \param interface_id interface identifier
* \param timing timing information
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_controller_radius_timing_set(int8_t interface_id, struct bbr_radius_timing *timing);
/**
* ws_pae_controller_radius_timing_get get radius timing information
*
* \param interface_id interface identifier
* \param timing timing information
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_controller_radius_timing_get(int8_t interface_id, struct bbr_radius_timing *timing);
/**
* ws_pae_controller_radius_timing_validate validate radius timing information
*
* \param interface_id interface identifier
* \param timing timing information
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_controller_radius_timing_validate(int8_t interface_id, struct bbr_radius_timing *timing);
/**
* ws_pae_controller_nw_info_set set network information
*

View File

@ -448,4 +448,64 @@ supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list)
return retry_supp;
}
int8_t ws_pae_lib_shared_comp_list_init(shared_comp_list_t *comp_list)
{
ns_list_init(comp_list);
return 0;
}
int8_t ws_pae_lib_shared_comp_list_free(shared_comp_list_t *comp_list)
{
ns_list_foreach_safe(shared_comp_entry_t, entry, comp_list) {
if (entry->data->delete) {
entry->data->delete ();
}
ns_list_remove(comp_list, entry);
ns_dyn_mem_free(entry);
}
return 0;
}
int8_t ws_pae_lib_shared_comp_list_add(shared_comp_list_t *comp_list, kmp_shared_comp_t *data)
{
ns_list_foreach(shared_comp_entry_t, entry, comp_list) {
if (entry->data == data) {
return -1;
}
}
shared_comp_entry_t *entry = ns_dyn_mem_alloc(sizeof(shared_comp_entry_t));
if (!entry) {
return -1;
}
entry->data = data;
ns_list_add_to_end(comp_list, entry);
return 0;
}
int8_t ws_pae_lib_shared_comp_list_remove(shared_comp_list_t *comp_list, kmp_shared_comp_t *data)
{
ns_list_foreach(shared_comp_entry_t, entry, comp_list) {
if (entry->data == data) {
ns_list_remove(comp_list, entry);
ns_dyn_mem_free(entry);
return 0;
}
}
return 0;
}
int8_t ws_pae_lib_shared_comp_list_timeout(shared_comp_list_t *comp_list, uint16_t ticks)
{
ns_list_foreach(shared_comp_entry_t, entry, comp_list) {
if (entry->data->timeout) {
entry->data->timeout(ticks);
}
}
return 0;
}
#endif /* HAVE_WS */

View File

@ -45,6 +45,13 @@ typedef struct supp_entry_s {
typedef NS_LIST_HEAD(supp_entry_t, link) supp_list_t;
typedef struct {
kmp_shared_comp_t *data; /**< KMP shared component data */
ns_list_link_t link; /**< Link */
} shared_comp_entry_t;
typedef NS_LIST_HEAD(shared_comp_entry_t, link) shared_comp_list_t;
/**
* ws_pae_lib_kmp_list_init initializes KMP list
*
@ -388,4 +395,62 @@ kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const
*/
supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list);
/**
* ws_pae_lib_shared_comp_list_init init shared component list
*
* \param comp_list component list
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_lib_shared_comp_list_init(shared_comp_list_t *comp_list);
/**
* ws_pae_lib_shared_comp_list_free free shared component list
*
* \param comp_list component list
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_lib_shared_comp_list_free(shared_comp_list_t *comp_list);
/**
* ws_pae_lib_shared_comp_list_add add to shared component list
*
* \param comp_list component list
* \param data shared component
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_lib_shared_comp_list_add(shared_comp_list_t *comp_list, kmp_shared_comp_t *data);
/**
* ws_pae_lib_shared_comp_list_remove remove from shared component list
*
* \param comp_list component list
* \param data shared component
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_lib_shared_comp_list_remove(shared_comp_list_t *comp_list, kmp_shared_comp_t *data);
/**
* ws_pae_lib_shared_comp_list_timeout timeout to shared component list
*
* \param comp_list component list
* \param ticks elapsed time in seconds
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_lib_shared_comp_list_timeout(shared_comp_list_t *comp_list, uint16_t ticks);
#endif /* WS_PAE_AUTH_H_ */

View File

@ -46,6 +46,7 @@
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
#include "6LoWPAN/ws/ws_common_defines.h"
#include "6LoWPAN/ws/ws_common.h"
#include "libNET/src/net_dns_internal.h"
#define TRACE_GROUP "icmp"
@ -638,6 +639,21 @@ if_address_entry_t *icmpv6_slaac_address_add(protocol_interface_info_entry_t *cu
}
#ifdef HAVE_IPV6_ND
static uint8_t icmpv6_dns_search_list_remove_pad(uint8_t *data_ptr, uint8_t length)
{
while (length) {
if (data_ptr[length - 2] && data_ptr[length - 1] == 0) {
break;
} else if (data_ptr[length - 2] == 0 && data_ptr[length - 1] == 0) {
length--;
}
}
return length;
}
static buffer_t *icmpv6_ra_handler(buffer_t *buf)
{
protocol_interface_info_entry_t *cur;
@ -868,13 +884,11 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf)
uint32_t dns_lifetime = common_read_32_bit(dptr + 2); // 2 x reserved
uint8_t *dns_search_list = dptr + 6;
uint8_t dns_search_list_len = length - 8; // Length includes type and length
tr_info("DNS Search List: %s Lifetime: %lu", trace_array(dns_search_list, dns_search_list_len), (unsigned long) dns_lifetime);
// TODO Add DNS server to DNS information storage.
// dns_search_list_storage(cur, buf->src_sa.address, dns_search_list, dns_search_list_len, dns_lifetime);
(void)dns_search_list;
(void)dns_search_list_len;
(void)dns_lifetime;
//Cut Padding
dns_search_list_len = icmpv6_dns_search_list_remove_pad(dns_search_list, dns_search_list_len);
//tr_info("DNS Search List: %s Lifetime: %lu", trace_array(dns_search_list, dns_search_list_len), (unsigned long) dns_lifetime);
// Add DNS server to DNS information storage.
net_dns_server_search_list_set(cur->id, buf->src_sa.address, dns_search_list, dns_search_list_len, dns_lifetime);
} else if (type == ICMPV6_OPT_RECURSIVE_DNS_SERVER) {
uint8_t dns_length = length / 8;
@ -887,11 +901,9 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf)
uint32_t dns_lifetime = common_read_32_bit(dptr + 2); // 2 x reserved
for (int n = 0; n < dns_count; n++) {
uint8_t *dns_srv_addr = dptr + 6 + n * 16;
tr_info("DNS Server: %s Lifetime: %lu", trace_ipv6(dns_srv_addr), (unsigned long) dns_lifetime);
// TODO Add DNS server to DNS information storage.
// dns_server_storage(cur, buf->src_sa.address, dns_srv_addr, dns_lifetime);
(void)dns_srv_addr;
(void)dns_lifetime;
//tr_info("DNS Server: %s Lifetime: %lu", trace_ipv6(dns_srv_addr), (unsigned long) dns_lifetime);
// Add DNS server to DNS information storage.
net_dns_server_address_set(cur->id, buf->src_sa.address, dns_srv_addr, dns_lifetime);
}
} else if (type == ICMPV6_OPT_6LOWPAN_CONTEXT) {
nd_ra_process_lowpan_context_option(cur, dptr - 2);

View File

@ -115,12 +115,29 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r
}
response->responseLength = libdhcpv6_address_reply_message_len(replyPacket->clientDUID.duid_length, replyPacket->serverDUID.duid_length, 0, replyPacket->rapidCommit, address_allocated);
//Calculate DNS LIST and Vendor data lengths here
response->responseLength += libdhcpv6_dns_server_message_sizes(serverBase);
response->responseLength += libdhcpv6_vendor_data_message_sizes(serverBase);
response->responsePtr = ns_dyn_mem_temporary_alloc(response->responseLength);
if (response->responsePtr) {
uint8_t *ptr = response->responsePtr;
//Write Generic data at beginning
ptr = libdhcpv6_header_write(ptr, DHCPV6_REPLY_TYPE, replyPacket->transaction_ID);
ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_SERVER_ID_OPTION, &replyPacket->serverDUID); //16
ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_CLIENT_ID_OPTION, &replyPacket->clientDUID); //16
if (address_allocated) {
libdhcpv6_reply_message_write(response->responsePtr, replyPacket, &nonTemporalAddress, NULL);
ptr = libdhcpv6_identity_association_option_write(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, true);
ptr = libdhcpv6_ia_address_option_write(ptr, nonTemporalAddress.requestedAddress, nonTemporalAddress.preferredLifeTime, nonTemporalAddress.validLifeTime);
//Write DNS LIST and Vendor data here
ptr = libdhcpv6_dns_server_message_writes(serverBase, ptr);
ptr = libdhcpv6_vendor_data_message_writes(serverBase, ptr);
} else {
libdhcpv6_reply_message_write(response->responsePtr, replyPacket, NULL, NULL);
ptr = libdhcpv6_identity_association_option_write_with_status(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, DHCPV6_STATUS_NO_ADDR_AVAILABLE_CODE);
}
if (replyPacket->rapidCommit) {
ptr = libdhcpv6_rapid_commit_option_write(ptr);
}
return 0;
}
@ -407,6 +424,71 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu
return 0;
}
int DHCPv6_server_service_set_dns_server(int8_t interface, uint8_t guaPrefix[static 16], uint8_t dns_server_address[static 16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len)
{
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
if (!serverInfo) {
return -1;
}
dhcpv6_dns_server_data_t *dns_entry = libdhcpv6_dns_server_allocate(serverInfo, dns_server_address);
if (!dns_entry) {
return -1;
}
if (dns_entry->search_list_length != dns_search_list_len) {
ns_dyn_mem_free(dns_entry->search_list);
dns_entry->search_list = NULL;
dns_entry->search_list_length = 0;
if (dns_search_list_len) {
dns_entry->search_list = ns_dyn_mem_alloc(dns_search_list_len);
if (dns_entry->search_list) {
dns_entry->search_list_length = dns_search_list_len;
}
}
}
if (dns_entry->search_list_length) {
//Copy Search List to allocated buffer
memcpy(dns_entry->search_list, dns_search_list_ptr, dns_entry->search_list_length);
}
return 0;
}
int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint8_t dhcp_vendor_data_len)
{
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
if (!serverInfo) {
return -1;
}
dhcpv6_vendor_data_t *vendor_data_entry = libdhcpv6_vendor_data_allocate(serverInfo, enterprise_number);
if (!vendor_data_entry) {
return -1;
}
if (vendor_data_entry->vendor_data_length != dhcp_vendor_data_len) {
ns_dyn_mem_free(vendor_data_entry->vendor_data);
vendor_data_entry->vendor_data = NULL;
vendor_data_entry->vendor_data_length = 0;
if (dhcp_vendor_data_len) {
vendor_data_entry->vendor_data = ns_dyn_mem_alloc(dhcp_vendor_data_len);
if (vendor_data_entry->vendor_data) {
vendor_data_entry->vendor_data_length = dhcp_vendor_data_len;
}
}
}
if (vendor_data_entry->vendor_data_length) {
//Copy Venfor Data to allocated buffer
memcpy(vendor_data_entry->vendor_data, dhcp_vendor_data_ptr, vendor_data_entry->vendor_data_length);
}
return 0;
}
#else
int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType)

View File

@ -89,6 +89,11 @@ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_
* /param validLifeTimne in seconds
*/
int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne);
int DHCPv6_server_service_set_dns_server(int8_t interface, uint8_t guaPrefix[static 16], uint8_t dns_server_address[static 16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len);
int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint8_t dhcp_vendor_data_len);
#else
#define DHCPv6_server_service_delete(interface, guaPrefix, delete_gua_addresses)
#endif

View File

@ -79,8 +79,48 @@ void dhcp_client_delete(int8_t interface);
*/
typedef void (dhcp_client_global_adress_cb)(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status);
typedef struct dhcp_server_notify_info {
uint16_t duid_type;
uint16_t duid_length;
uint32_t life_time;
uint8_t *duid;
} dhcp_server_notify_info_t;
typedef struct dhcp_gen_option {
uint16_t data_length;
uint8_t *data;
} dhcp_gen_option_t;
typedef struct dhcp_vendor_spesific_option {
uint32_t enterprise_number;
uint16_t data_length;
uint8_t *data;
} dhcp_vendor_spesific_option_t;
typedef struct dhcp_option_notify_s {
uint8_t option_type;
union {
dhcp_gen_option_t generic;
dhcp_vendor_spesific_option_t vendor_spesific;
} option;
} dhcp_option_notify_t;
/* give dhcp Client server Optional options notication
*
* /param interface interface id
* /param option_type Type of option
* /param option_data data of options.
* /param option_length length of option.
* /param server_info info inclu DUID and Life-time for notify options
*
*/
typedef void (dhcp_client_options_notify_cb)(int8_t interface, dhcp_option_notify_t *options, dhcp_server_notify_info_t *server_info);
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);
int dhcp_client_option_notification_cb_set(int8_t interface, dhcp_client_options_notify_cb *notify_cb);
/* Renew all leased adddresses might be used when short address changes
*
* /param interface interface where address is got

View File

@ -33,6 +33,7 @@
typedef struct {
dhcp_client_global_adress_cb *global_address_cb;
dhcp_client_options_notify_cb *option_information_cb;
uint16_t service_instance;
uint16_t relay_instance;
uint16_t sol_timeout;
@ -152,6 +153,17 @@ void dhcp_client_solicit_timeout_set(int8_t interface, uint16_t timeout, uint16_
return;
}
int dhcp_client_option_notification_cb_set(int8_t interface, dhcp_client_options_notify_cb *notify_cb)
{
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
if (!dhcp_client) {
return -1;
}
dhcp_client->option_information_cb = notify_cb;
return 0;
}
void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16])
{
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
@ -215,6 +227,67 @@ void dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr)
}
static void dhcp_vendor_information_notify(uint8_t *ptr, uint16_t data_len, dhcp_client_class_t *dhcp_client, dhcpv6_client_server_data_t *srv_data_ptr)
{
if (!dhcp_client->option_information_cb) {
return;
}
if (!srv_data_ptr->iaNontemporalAddress.validLifetime) {
return; //Valid Lifetime zero
}
dhcp_option_notify_t dhcp_option;
uint16_t type, length;
bool valid_optional_options;
dhcp_server_notify_info_t server_info;
server_info.life_time = srv_data_ptr->iaNontemporalAddress.validLifetime;
server_info.duid = srv_data_ptr->serverDUID.duid + 2; // Skip the type
server_info.duid_type = srv_data_ptr->serverDUID.type;
server_info.duid_length = srv_data_ptr->serverDUID.duid_length - 2;// remove the type
while (data_len >= 4) {
type = common_read_16_bit(ptr);
ptr += 2;
length = common_read_16_bit(ptr);
ptr += 2;
data_len -= 4;
if (data_len < length) {
return;
}
valid_optional_options = false;
//Accept only listed items below with validated lengths
if ((type == DHCPV6_OPTION_VENDOR_SPECIFIC_INFO || type == DHCPV6_OPTION_VENDOR_CLASS) && data_len >= 4) {
valid_optional_options = true;
//Parse enterprise number
dhcp_option.option.vendor_spesific.enterprise_number = common_read_32_bit(ptr);
ptr += 4;
data_len -= 4;
length -= 4;
dhcp_option.option.vendor_spesific.data = ptr;
dhcp_option.option.vendor_spesific.data_length = length;
} else if (type == DHCPV6_OPTION_DNS_SERVERS && (length >= 16 && ((length % 16) == 0))) {
valid_optional_options = true;
dhcp_option.option.generic.data = ptr;
dhcp_option.option.generic.data_length = length;
} else if (type == DHCPV6_OPTION_DOMAIN_LIST) {
valid_optional_options = true;
dhcp_option.option.generic.data = ptr;
dhcp_option.option.generic.data_length = length;
}
if (valid_optional_options) {
dhcp_option.option_type = type;
dhcp_client->option_information_cb(dhcp_client->interface, &dhcp_option, &server_info);
}
data_len -= length;
ptr += length;
}
}
/* solication responce received for either global address or routter id assignment */
int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uint8_t *msg_ptr, uint16_t msg_len)
{
@ -310,6 +383,10 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
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);
}
//Optional Options notify from Reply
dhcp_vendor_information_notify(msg_ptr, msg_len, dhcp_client, srv_data_ptr);
return RET_MSG_ACCEPTED;
error_exit:
dhcpv6_client_send_error_cb(srv_data_ptr);

View File

@ -204,7 +204,6 @@ typedef struct protocol_interface_rf_mac_setup {
bool macBroadcastDisabled: 1;
bool scan_active: 1;
bool rf_csma_extension_supported: 1;
bool ack_tx_possible: 1;
uint16_t mac_short_address;
uint16_t pan_id;
uint8_t mac64[8];

View File

@ -1883,6 +1883,9 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in
//Remember to update security counter here!
key_desc = mac_frame_security_key_get(rf_ptr, buffer);
if (!key_desc) {
#ifdef __linux__
tr_debug("Drop a ACK missing key desc");
#endif
buffer->status = MLME_UNAVAILABLE_KEY;
return -2;
}
@ -1890,6 +1893,9 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in
buffer->aux_header.frameCounter = mac_sec_mib_key_outgoing_frame_counter_get(rf_ptr, key_desc);
}
if (!mac_frame_security_parameters_init(&ccm_ptr, rf_ptr, buffer, key_desc)) {
#ifdef __linux__
tr_debug("Drop a ACK ignored by security init");
#endif
return -2;
}
if (init_build) {
@ -1921,6 +1927,9 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in
mac_sec_mib_key_outgoing_frame_counter_decrement(rf_ptr, key_desc);
ccm_free(&ccm_ptr);
}
#ifdef __linux__
tr_debug("Drop a ACK send by frame too long %u", frame_length);
#endif
return -1;
}
@ -1932,7 +1941,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in
tx_buf->ack_len = frame_length;
uint8_t *mhr_start = ptr;
buffer->tx_time = mac_mcps_sap_get_phy_timestamp(rf_ptr) + 300; //Send 300 us later
buffer->tx_time = mac_mcps_sap_get_phy_timestamp(rf_ptr) + 1000; // 1ms delay before Ack
ptr = mac_generic_packet_write(rf_ptr, ptr, buffer);
@ -2092,6 +2101,11 @@ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, m
if (rf_ptr->active_pd_data_request) {
mac_csma_backoff_start(rf_ptr);
}
#ifdef __linux__
if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) {
tr_debug("Drop ACK by CCA request");
}
#endif
platform_exit_critical();
return -1;
}

View File

@ -673,50 +673,13 @@ static int8_t mac_mlme_set_ack_wait_duration(protocol_interface_rf_mac_setup_s *
return 0;
}
static void mac_mlme_trig_pending_ack(protocol_interface_rf_mac_setup_s *rf_mac_setup, mlme_device_descriptor_t *device_ptr)
{
platform_enter_critical();
if (rf_mac_setup->mac_ack_tx_active && !rf_mac_setup->ack_tx_possible &&
device_ptr->PANId == rf_mac_setup->enhanced_ack_buffer.DstPANId) {
//Compare address for pending neigbour add
if (rf_mac_setup->enhanced_ack_buffer.fcf_dsn.DstAddrMode == MAC_ADDR_MODE_16_BIT) {
uint16_t short_id = common_read_16_bit(rf_mac_setup->enhanced_ack_buffer.DstAddr);
if (short_id == device_ptr->ShortAddress) {
rf_mac_setup->ack_tx_possible = true;
}
} else if (rf_mac_setup->enhanced_ack_buffer.fcf_dsn.DstAddrMode == MAC_ADDR_MODE_64_BIT) {
if (memcmp(device_ptr->ExtAddress, rf_mac_setup->enhanced_ack_buffer.DstAddr, 8) == 0) {
rf_mac_setup->ack_tx_possible = true;
}
}
}
platform_exit_critical();
}
static int8_t mac_mlme_device_description_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
{
if (set_req->value_size != sizeof(mlme_device_descriptor_t)) {
return -1;
}
if (mac_sec_mib_device_description_set(set_req->attr_index, (mlme_device_descriptor_t *) set_req->value_pointer, rf_mac_setup) != 0) {
return -1;
}
mac_mlme_trig_pending_ack(rf_mac_setup, (mlme_device_descriptor_t *) set_req->value_pointer);
return 0;
}
static int8_t mac_mlme_device_pending_ack_trig(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
{
if (set_req->value_size != sizeof(mlme_device_descriptor_t)) {
return -1;
}
mac_mlme_trig_pending_ack(rf_mac_setup, (mlme_device_descriptor_t *) set_req->value_pointer);
return 0;
return mac_sec_mib_device_description_set(set_req->attr_index, (mlme_device_descriptor_t *) set_req->value_pointer, rf_mac_setup);
}
static int8_t mac_mlme_key_description_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req)
@ -795,8 +758,6 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
return mac_mlme_set_ack_wait_duration(rf_mac_setup, set_req);
case macDeviceTable:
return mac_mlme_device_description_set(rf_mac_setup, set_req);
case macDevicePendingAckTrig:
return mac_mlme_device_pending_ack_trig(rf_mac_setup, set_req);
case macKeyTable:
return mac_mlme_key_description_set(rf_mac_setup, set_req);
case macDefaultKeySource:
@ -1659,6 +1620,7 @@ int8_t mac_mlme_rf_channel_change(protocol_interface_rf_mac_setup_s *rf_mac_setu
if (new_channel == rf_mac_setup->mac_channel) {
return 0;
}
platform_enter_critical();
if (rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL, &new_channel) == 0) {
rf_mac_setup->mac_channel = new_channel;

View File

@ -453,37 +453,18 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
if (status == PHY_LINK_CCA_PREPARE) {
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) {
#ifdef TIMING_TOOL_TRACES
tr_info("%u TX_start %u", mac_mcps_sap_get_phy_timestamp(rf_ptr), rf_ptr->mac_channel);
#endif
return PHY_TX_ALLOWED;
}
//Compare time to started time
if (mac_mcps_sap_get_phy_timestamp(rf_ptr) - rf_ptr->enhanced_ack_handler_timestamp > ENHANCED_ACK_NEIGHBOUR_POLL_MAX_TIME_US || mcps_generic_ack_build(rf_ptr, false) != 0) {
mac_data_ack_tx_finish(rf_ptr);
}
return PHY_TX_NOT_ALLOWED;
}
if (rf_ptr->mac_edfe_tx_active) {
return PHY_TX_ALLOWED;
if (rf_ptr->mac_ack_tx_active || rf_ptr->mac_edfe_tx_active) {
goto VALIDATE_TX_TIME;
}
if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request)) {
#ifdef TIMING_TOOL_TRACES
tr_info("%u TX_start %u", mac_mcps_sap_get_phy_timestamp(rf_ptr), rf_ptr->mac_channel);
#endif
rf_ptr->active_pd_data_request->initial_tx_channel = rf_ptr->mac_channel;
int8_t channel_cca_threshold = mac_cca_thr_get_dbm(rf_ptr, rf_ptr->mac_channel);
if (CCA_FAILED_DBM != channel_cca_threshold) {
rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD, (uint8_t *)&channel_cca_threshold);
}
return PHY_TX_ALLOWED;
goto VALIDATE_TX_TIME;
}
if (rf_ptr->fhss_api) {
@ -525,10 +506,19 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
return PHY_RESTART_CSMA;
}
}
VALIDATE_TX_TIME:
if (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->tx_time && !rf_ptr->mac_ack_tx_active && !rf_ptr->mac_edfe_tx_active) {
int32_t tx_time_error_us = mac_mcps_sap_get_phy_timestamp(rf_ptr) - rf_ptr->active_pd_data_request->tx_time;
// Positive error means that TX is too late. Do not allow transmit if transmission is delayed over 5ms
if (tx_time_error_us > 5000) {
mac_sap_cca_fail_cb(rf_ptr, 0xffff);
return PHY_TX_NOT_ALLOWED;
}
}
#ifdef TIMING_TOOL_TRACES
tr_info("%u TX_start %u", mac_mcps_sap_get_phy_timestamp(rf_ptr), rf_ptr->mac_channel);
#endif
return 0;
return PHY_TX_ALLOWED;
}
if (rf_ptr->mac_ack_tx_active) {
@ -851,6 +841,9 @@ static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr,
return 0;
}
if (rf_ptr->mac_ack_tx_active) {
#ifdef __linux__
tr_debug("Drop a New ack by pending request");
#endif
return -1;
}
@ -863,18 +856,6 @@ static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr,
return -1;
}
if (rf_ptr->enhanced_ack_buffer.fcf_dsn.securityEnabled == 0 || rf_ptr->enhanced_ack_buffer.aux_header.securityLevel == 0) {
//Unsecured data will be acked immediately
rf_ptr->ack_tx_possible = true;
} else {
if (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;
}
}
return mcps_generic_ack_build(rf_ptr, true);
}
@ -909,11 +890,17 @@ static mac_pre_parsed_frame_t *mac_pd_sap_allocate_receive_buffer(protocol_inter
if (fcf_read->frametype != FC_ACK_FRAME) {
if (!ns_monitor_packet_allocation_allowed()) {
// stack can not handle new packets for routing
#ifdef __linux__
tr_debug("Packet ingress drop buffer allocation");
#endif
return NULL;
}
}
mac_pre_parsed_frame_t *buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len);
if (!buffer) {
#ifdef __linux__
tr_debug("macPD buffer allocate fail %u", pd_data_ind->data_len);
#endif
return NULL;
}
//Copy Pre Parsed values
@ -1004,6 +991,9 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
arm_pd_sap_generic_ind_t *pd_data_ind = &(message->message.generic_data_ind);
mac_pre_parsed_frame_t *buffer = NULL;
if (pd_data_ind->data_len == 0) {
#ifdef TIMING_TOOL_TRACES
tr_info("Collission at RF?");
#endif
goto ERROR_HANDLER;
}
@ -1027,9 +1017,13 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
goto ERROR_HANDLER;
}
if (!mac_pd_sap_rx_filter(pd_data_ind->data_ptr, &fcf_read, rf_ptr->mac_frame_filters, rf_ptr->mac64, rf_ptr->mac_short_address, rf_ptr->pan_id)) {
pd_data_ind->data_len = 0; // Do not update RX drop in that case
goto ERROR_HANDLER;
}
if (mac_pd_sap_generate_ack(rf_ptr, &fcf_read, pd_data_ind)) {
#ifdef __linux__
tr_debug("Drop a Data by ignored ACK generation");
#endif
goto ERROR_HANDLER;
}
if (buffer) {

View File

@ -83,6 +83,7 @@
#include "Service_Libs/load_balance/load_balance_api.h"
#include "Service_Libs/pan_blacklist/pan_blacklist_api.h"
#include "Service_Libs/etx/etx.h"
#include "libNET/src/net_dns_internal.h"
#include "mac_api.h"
#include "ethernet_mac_api.h"
@ -304,6 +305,8 @@ void core_timer_event_handle(uint16_t ticksUpdate)
ipv6_destination_cache_timer(seconds);
ipv6_frag_timer(seconds);
cipv6_frag_timer(seconds);
net_dns_timer_seconds(seconds);
#ifdef HAVE_WS
ws_pae_controller_slow_timer(seconds);
#endif

View File

@ -64,6 +64,7 @@ typedef NS_LIST_HEAD(kmp_sec_prot_entry_t, link) kmp_sec_prot_list_t;
typedef struct {
uint8_t instance_id; /**< Message interface instance identifier */
uint8_t header_size; /**< Message interface header size */
uint8_t number_of_conn; /**< Message interface number of connections */
kmp_service_msg_if_send *send; /**< Message interface callback to send KMP frames */
ns_list_link_t link; /**< Link */
} kmp_msg_if_entry_t;
@ -81,6 +82,8 @@ struct kmp_service_s {
kmp_service_timer_if_start *timer_start; /**< Callback to start timer */
kmp_service_timer_if_stop *timer_stop; /**< Callback to stop timer */
kmp_service_event_if_event_send *event_send; /**< Callback to send event */
kmp_service_shared_comp_add *shared_comp_add; /**< Callback to shared component add */
kmp_service_shared_comp_remove *shared_comp_remove; /**< Callback to shared component remove */
ns_list_link_t link; /**< Link */
};
@ -100,8 +103,11 @@ 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);
static void kmp_api_sec_prot_finished(sec_prot_t *prot);
static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size);
static int8_t kmp_sec_prot_conn_send(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number, uint8_t flags);
static void kmp_sec_prot_timer_start(sec_prot_t *prot);
static void kmp_sec_prot_timer_stop(sec_prot_t *prot);
static int8_t kmp_sec_prot_shared_comp_add(sec_prot_t *prot, shared_comp_data_t *data);
static int8_t kmp_sec_prot_shared_comp_remove(sec_prot_t *prot, shared_comp_data_t *data);
static void kmp_sec_prot_state_machine_call(sec_prot_t *prot);
static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64);
static void kmp_sec_prot_ip_addr_get(sec_prot_t *prot, uint8_t *address);
@ -157,13 +163,17 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, uint8_t msg_i
kmp->sec_prot.header_size = msg_if_entry->header_size;
kmp->sec_prot.receive_peer_hdr_size = msg_if_entry->header_size;
kmp->sec_prot.number_of_conn = msg_if_entry->number_of_conn;
kmp->sec_prot.create_conf = kmp_api_sec_prot_create_confirm;
kmp->sec_prot.create_ind = kmp_api_sec_prot_create_indication;
kmp->sec_prot.finished_ind = kmp_api_sec_prot_finished_indication;
kmp->sec_prot.finished = kmp_api_sec_prot_finished;
kmp->sec_prot.send = kmp_sec_prot_send;
kmp->sec_prot.conn_send = kmp_sec_prot_conn_send;
kmp->sec_prot.timer_start = kmp_sec_prot_timer_start;
kmp->sec_prot.timer_stop = kmp_sec_prot_timer_stop;
kmp->sec_prot.shared_comp_add = kmp_sec_prot_shared_comp_add;
kmp->sec_prot.shared_comp_remove = kmp_sec_prot_shared_comp_remove;
kmp->sec_prot.state_machine_call = kmp_sec_prot_state_machine_call;
kmp->sec_prot.addr_get = kmp_sec_prot_eui64_addr_get;
kmp->sec_prot.ip_addr_get = kmp_sec_prot_ip_addr_get;
@ -237,6 +247,11 @@ static void kmp_api_sec_prot_finished(sec_prot_t *prot)
}
static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size)
{
return kmp_sec_prot_conn_send(prot, pdu, size, 0, 0);
}
static int8_t kmp_sec_prot_conn_send(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number, uint8_t flags)
{
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
@ -256,7 +271,7 @@ static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size)
int8_t result = -1;
if (msg_if_entry->send) {
result = msg_if_entry->send(kmp->service, prot->msg_if_instance_id, kmp_id, kmp->addr, pdu, size, kmp->instance_identifier);
result = msg_if_entry->send(kmp->service, prot->msg_if_instance_id, kmp_id, kmp->addr, pdu, size, kmp->instance_identifier, conn_number, flags);
}
if (result < 0) {
@ -269,6 +284,7 @@ static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size)
static void kmp_sec_prot_timer_start(sec_prot_t *prot)
{
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
kmp->timer_start_pending = false;
if (kmp->service->timer_start(kmp->service, kmp) < 0) {
kmp->timer_start_pending = true;
@ -278,10 +294,33 @@ static void kmp_sec_prot_timer_start(sec_prot_t *prot)
static void kmp_sec_prot_timer_stop(sec_prot_t *prot)
{
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
kmp->service->timer_stop(kmp->service, kmp);
kmp->timer_start_pending = false;
}
static int8_t kmp_sec_prot_shared_comp_add(sec_prot_t *prot, shared_comp_data_t *data)
{
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
if (kmp->service->shared_comp_add == NULL) {
return -1;
}
kmp->service->shared_comp_add(kmp->service, (kmp_shared_comp_t *) data);
return 0;
}
static int8_t kmp_sec_prot_shared_comp_remove(sec_prot_t *prot, shared_comp_data_t *data)
{
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
if (kmp->service->shared_comp_add == NULL) {
return -1;
}
kmp->service->shared_comp_remove(kmp->service, (kmp_shared_comp_t *) data);
return 0;
}
static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64)
{
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
@ -444,6 +483,8 @@ kmp_service_t *kmp_service_create(void)
service->tx_status_ind = 0;
service->addr_get = 0;
service->api_get = 0;
service->shared_comp_add = NULL;
service->shared_comp_remove = NULL;
ns_list_add_to_start(&kmp_service_list, service);
@ -496,7 +537,7 @@ int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind
return 0;
}
int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size)
int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size, uint8_t number_of_conn)
{
if (!service) {
return -1;
@ -533,11 +574,12 @@ int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id,
entry->instance_id = instance_id;
entry->send = send;
entry->header_size = header_size;
entry->number_of_conn = number_of_conn;
return 0;
}
int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size)
int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t connection_num)
{
if (!service) {
return -1;
@ -553,7 +595,14 @@ int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, k
return -1;
}
int8_t ret = kmp->sec_prot.receive(&kmp->sec_prot, pdu, size);
int8_t ret = -1;
if (kmp->sec_prot.receive != NULL) {
ret = kmp->sec_prot.receive(&kmp->sec_prot, pdu, size);
}
if (kmp->sec_prot.conn_receive != NULL) {
ret = kmp->sec_prot.conn_receive(&kmp->sec_prot, pdu, size, connection_num);
}
return ret;
}
@ -642,6 +691,17 @@ int8_t kmp_service_timer_if_register(kmp_service_t *service, kmp_service_timer_i
return 0;
}
int8_t kmp_service_shared_comp_if_register(kmp_service_t *service, kmp_service_shared_comp_add add, kmp_service_shared_comp_remove remove)
{
if (!service) {
return -1;
}
service->shared_comp_add = add;
service->shared_comp_remove = remove;
return 0;
}
void kmp_service_event_if_event(kmp_service_t *service, void *data)
{
(void) service;

View File

@ -59,6 +59,9 @@ typedef enum {
KMP_TX_ERR_UNSPEC = -2, // Other reason
} kmp_tx_status_e;
// On message interface send, do not deallocate pdu buffer
#define MSG_IF_SEND_FLAG_NO_DEALLOC 0x01
typedef void kmp_sec_keys_t;
typedef struct sec_prot_s sec_prot_t;
typedef struct kmp_api_s kmp_api_t;
@ -367,12 +370,13 @@ int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind
* \param addr address
* \param pdu pdu
* \param size pdu size
* \param conn_number connection number (0 for default)
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size);
int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t conn_number);
/**
* kmp_service_msg_if_send send a message
@ -384,12 +388,14 @@ int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, k
* \param pdu pdu
* \param size pdu size
* \param tx_identifier TX identifier
* \param conn_number connection number (0 for default)
* \param flags flags
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier, uint8_t conn_number, uint8_t flags);
/**
* kmp_service_msg_if_register registers message interface
@ -398,12 +404,13 @@ typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, uint8_t instance_
* \param instance_id message interface instance identifier
* \param send KMP PDU send callback
* \param header_size header size
* \param number_of_conn number of connections
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size);
int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size, uint8_t number_of_conn);
/**
* kmp_service_tx_status tx status indication
@ -467,6 +474,7 @@ int8_t kmp_service_sec_protocol_unregister(kmp_service_t *service, kmp_type_e ty
* kmp_service_timer_if_timeout timer timeout
*
* \param service KMP instance
* \param ticks Ticks
*
*/
void kmp_service_timer_if_timeout(kmp_api_t *kmp, uint16_t ticks);
@ -508,6 +516,68 @@ typedef int8_t kmp_service_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp)
*/
int8_t kmp_service_timer_if_register(kmp_service_t *service, kmp_service_timer_if_start start, kmp_service_timer_if_stop stop);
/**
* kmp_service_shared_comp_timer_timeout shared component timer timeout
*
* \param ticks timer ticks
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t kmp_service_shared_comp_timer_timeout(uint16_t ticks);
/**
* kmp_service_shared_comp_delete shared component delete
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t kmp_service_shared_comp_delete(void);
typedef struct {
kmp_service_shared_comp_timer_timeout *timeout;
kmp_service_shared_comp_delete *delete;
} kmp_shared_comp_t;
/**
* kmp_service_shared_comp_add add shared component
*
* \param service KMP service
* \param data shared component data
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t kmp_service_shared_comp_add(kmp_service_t *service, kmp_shared_comp_t *data);
/**
* kmp_service_shared_comp_remove remove shared component
*
* \param service KMP service
* \param data shared component data
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t kmp_service_shared_comp_remove(kmp_service_t *service, kmp_shared_comp_t *data);
/**
* kmp_service_shared_comp_if_register register a continuous timer interface to KMP service
*
* \param service KMP service
* \param add shared component
* \param remove remove shared component
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t kmp_service_shared_comp_if_register(kmp_service_t *service, kmp_service_shared_comp_add add, kmp_service_shared_comp_remove remove);
/**
* kmp_service_event_if_event event callback
*

View File

@ -49,7 +49,7 @@ 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, uint8_t instance_id, 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_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier, uint8_t conn_number, uint8_t flags);
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)
@ -72,7 +72,7 @@ int8_t kmp_eapol_pdu_if_register(kmp_service_t *service, protocol_interface_info
eapol_pdu_if->kmp_service = service;
eapol_pdu_if->interface_ptr = interface_ptr;
if (kmp_service_msg_if_register(service, 0, kmp_eapol_pdu_if_send, EAPOL_PDU_IF_HEADER_SIZE) < 0) {
if (kmp_service_msg_if_register(service, 0, kmp_eapol_pdu_if_send, EAPOL_PDU_IF_HEADER_SIZE, 0) < 0) {
ns_dyn_mem_free(eapol_pdu_if);
return -1;
}
@ -92,17 +92,19 @@ int8_t kmp_eapol_pdu_if_unregister(kmp_service_t *service)
if (entry->kmp_service == service) {
ns_list_remove(&kmp_eapol_pdu_if_list, entry);
ns_dyn_mem_free(entry);
kmp_service_msg_if_register(service, 0, NULL, 0);
kmp_service_msg_if_register(service, 0, NULL, 0, 0);
}
}
return 0;
}
static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, uint8_t instance_id, 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_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier, uint8_t conn_number, uint8_t flags)
{
(void) instance_id; // Only one instance of eapol interface possible
(void) conn_number; // Only one connection of eapol interface possible
if (!service || !addr || !pdu) {
// No flags supported
if (!service || !addr || !pdu || flags) {
return -1;
}
@ -159,7 +161,7 @@ int8_t kmp_eapol_pdu_if_receive(protocol_interface_info_entry_t *interface_ptr,
return -1;
}
int8_t ret = kmp_service_msg_if_receive(service, 0, type, &addr, data_pdu, data_pdu_size);
int8_t ret = kmp_service_msg_if_receive(service, 0, type, &addr, data_pdu, data_pdu_size, 0);
return ret;
}

View File

@ -40,18 +40,19 @@
#define TRACE_GROUP "kmsi"
#define SOCKET_IF_HEADER_SIZE 27
#define INSTANCE_SOCKETS_NUMBER 3
typedef struct {
kmp_service_t *kmp_service; /**< KMP service */
uint8_t instance_id; /**< Instance identifier */
bool relay; /**< Interface is relay interface */
ns_address_t remote_addr; /**< Remote address */
int8_t socket_id; /**< Socket ID */
bool socket_id_set; /**< Socket ID is set */
int8_t socket_id[INSTANCE_SOCKETS_NUMBER]; /**< Socket ID */
unsigned socket_id_in_use : 4; /**< Socket ID is in use */
ns_list_link_t link; /**< Link */
} kmp_socket_if_t;
static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier, uint8_t connection_num, uint8_t flags);
static void kmp_socket_if_socket_cb(void *ptr);
static NS_LIST_DEFINE(kmp_socket_if_list, kmp_socket_if_t, link);
@ -78,7 +79,10 @@ int8_t kmp_socket_if_register(kmp_service_t *service, uint8_t *instance_id, bool
return -1;
}
memset(socket_if, 0, sizeof(kmp_socket_if_t));
socket_if->socket_id = -1;
for (uint8_t socket_num = 0; socket_num < INSTANCE_SOCKETS_NUMBER; socket_num++) {
socket_if->socket_id[socket_num] = -1;
}
socket_if->socket_id_in_use = 1;
new_socket_if_allocated = true;
}
@ -87,7 +91,7 @@ int8_t kmp_socket_if_register(kmp_service_t *service, uint8_t *instance_id, bool
if (*instance_id == 0) {
socket_if->instance_id = kmp_socket_if_instance_id++;
if (socket_if->instance_id == 0) {
socket_if->instance_id++;
socket_if->instance_id = kmp_socket_if_instance_id++;
}
*instance_id = socket_if->instance_id;
}
@ -104,23 +108,33 @@ int8_t kmp_socket_if_register(kmp_service_t *service, uint8_t *instance_id, bool
memcpy(&socket_if->remote_addr.address, remote_addr, 16);
socket_if->remote_addr.identifier = remote_port;
if (socket_if->socket_id < 0 || address_changed) {
if (socket_if->socket_id >= 0) {
socket_close(socket_if->socket_id);
for (uint8_t socket_num = 0; socket_num < INSTANCE_SOCKETS_NUMBER; socket_num++) {
if (socket_if->socket_id_in_use & (1 << socket_num)) {
if ((socket_if->socket_id[socket_num] < 1) || address_changed) {
if (socket_if->socket_id[socket_num] >= 0) {
socket_close(socket_if->socket_id[socket_num]);
}
socket_if->socket_id = socket_open(IPV6_NH_UDP, local_port, &kmp_socket_if_socket_cb);
if (socket_if->socket_id < 0) {
socket_if->socket_id[socket_num] = socket_open(IPV6_NH_UDP, local_port, &kmp_socket_if_socket_cb);
if (socket_if->socket_id[socket_num] < 0) {
ns_dyn_mem_free(socket_if);
return -1;
}
}
}
}
uint8_t header_size = 0;
if (relay) {
header_size = SOCKET_IF_HEADER_SIZE;
}
if (kmp_service_msg_if_register(service, *instance_id, kmp_socket_if_send, header_size) < 0) {
if (kmp_service_msg_if_register(service, *instance_id, kmp_socket_if_send, header_size, INSTANCE_SOCKETS_NUMBER) < 0) {
for (uint8_t socket_num = 0; socket_num < INSTANCE_SOCKETS_NUMBER; socket_num++) {
if (socket_if->socket_id[socket_num] >= 0) {
socket_close(socket_if->socket_id[socket_num]);
}
}
ns_dyn_mem_free(socket_if);
return -1;
}
@ -141,15 +155,19 @@ int8_t kmp_socket_if_unregister(kmp_service_t *service)
ns_list_foreach_safe(kmp_socket_if_t, entry, &kmp_socket_if_list) {
if (entry->kmp_service == service) {
ns_list_remove(&kmp_socket_if_list, entry);
socket_close(entry->socket_id);
kmp_service_msg_if_register(service, entry->instance_id, NULL, 0);
for (uint8_t socket_num = 0; socket_num < INSTANCE_SOCKETS_NUMBER; socket_num++) {
if (entry->socket_id[socket_num] >= 0) {
socket_close(entry->socket_id[socket_num]);
}
}
kmp_service_msg_if_register(service, entry->instance_id, NULL, 0, 0);
ns_dyn_mem_free(entry);
}
}
return 0;
}
static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier)
static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier, uint8_t connection_num, uint8_t flags)
{
(void) tx_identifier;
@ -157,6 +175,10 @@ static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, km
return -1;
}
if (connection_num >= INSTANCE_SOCKETS_NUMBER) {
return -1;
}
kmp_socket_if_t *socket_if = NULL;
ns_list_foreach(kmp_socket_if_t, entry, &kmp_socket_if_list) {
@ -181,7 +203,26 @@ static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, km
*ptr = kmp_id;
}
socket_sendto(socket_if->socket_id, &socket_if->remote_addr, pdu, size);
int8_t socket_id = -1;
if ((socket_if->socket_id_in_use & (1 << connection_num)) && socket_if->socket_id[connection_num] >= 0) {
socket_id = socket_if->socket_id[connection_num];
} else {
if (socket_if->socket_id[connection_num] < 0) {
socket_if->socket_id[connection_num] = socket_open(IPV6_NH_UDP, 0, &kmp_socket_if_socket_cb);
}
if (socket_if->socket_id[connection_num] < 0) {
return -1;
}
socket_if->socket_id_in_use |= (1 << connection_num);
}
socket_sendto(socket_id, &socket_if->remote_addr, pdu, size);
// Deallocate unless flags deny it
if (flags & MSG_IF_SEND_FLAG_NO_DEALLOC) {
return 0;
}
ns_dyn_mem_free(pdu);
return 0;
@ -196,13 +237,17 @@ static void kmp_socket_if_socket_cb(void *ptr)
}
kmp_socket_if_t *socket_if = NULL;
uint8_t connection_num = 0;
ns_list_foreach(kmp_socket_if_t, entry, &kmp_socket_if_list) {
if (entry->socket_id == cb_data->socket_id) {
for (uint8_t socket_num = 0; socket_num < INSTANCE_SOCKETS_NUMBER; socket_num++) {
if (entry->socket_id[socket_num] == cb_data->socket_id) {
socket_if = entry;
connection_num = socket_num;
break;
}
}
}
if (!socket_if) {
return;
@ -237,7 +282,7 @@ static void kmp_socket_if_socket_cb(void *ptr)
cb_data->d_len -= SOCKET_IF_HEADER_SIZE;
}
kmp_service_msg_if_receive(socket_if->kmp_service, socket_if->instance_id, type, &addr, data_ptr, cb_data->d_len);
kmp_service_msg_if_receive(socket_if->kmp_service, socket_if->instance_id, type, &addr, data_ptr, cb_data->d_len, connection_num);
ns_dyn_mem_free(pdu);
}

View File

@ -177,7 +177,7 @@ uint8_t *eap_tls_sec_prot_lib_message_build(uint8_t eap_code, uint8_t eap_type,
uint8_t *data_ptr = NULL;
// Write EAP-TLS data (from EAP-TLS flags field onward)
if (tls_send->data) {
if (tls_send != NULL && tls_send->data) {
data_ptr = eap_tls_sec_prot_lib_fragment_write(tls_send->data + TLS_HEAD_LEN, tls_send->total_len, tls_send->handled_len, &eap_len, flags);
}
@ -201,8 +201,8 @@ static int8_t eap_tls_sec_prot_lib_ack_update(tls_data_t *tls)
return false;
}
if (tls->handled_len + TLS_FRAGMENT_LEN < tls->total_len) {
tls->handled_len += TLS_FRAGMENT_LEN;
if (tls->handled_len + EAP_TLS_FRAGMENT_LEN_VALUE < tls->total_len) {
tls->handled_len += EAP_TLS_FRAGMENT_LEN_VALUE;
return false;
}
@ -236,8 +236,8 @@ static uint8_t *eap_tls_sec_prot_lib_fragment_write(uint8_t *data, uint16_t tota
data_begin[0] = *flags;
}
if (total_len - handled_len > TLS_FRAGMENT_LEN) {
*message_len += TLS_FRAGMENT_LEN;
if (total_len - handled_len > EAP_TLS_FRAGMENT_LEN_VALUE) {
*message_len += EAP_TLS_FRAGMENT_LEN_VALUE;
if (handled_len == 0) {
data_begin -= 4; // length

View File

@ -54,7 +54,6 @@ typedef struct {
uint16_t handled_len; /**< Handled length of the data buffer (e.g. acked by other end) */
} tls_data_t;
#define TLS_FRAGMENT_LEN 1100 //EAP-TLS fragment length
#define TLS_HEAD_LEN 5 //EAP-TLS flags and EAP-TLS length
extern const uint8_t eap_msg_trace[4][10];

View File

@ -65,12 +65,15 @@ typedef enum {
// How many times initial EAPOL-key is accepted on wait for identity response state
#define INITIAL_EAPOL_KEY_MAX_COUNT 2
// How long to wait RADIUS client to proceed with handshake (RADIUS server to answer)
#define RADIUS_EAP_TLS_CLIENT_TIMEOUT 60 * 10 // 60 seconds
typedef struct {
sec_prot_common_t common; /**< Common data */
sec_prot_t *radius_client_prot; /**< RADIUS client security protocol */
sec_prot_receive *radius_client_send; /**< RADIUS client security protocol send (receive from peer) */
sec_prot_delete *radius_client_deleted; /**< RADIUS client security protocol peer deleted (notify to peer that radius EAP-TLS deleted) */
eapol_pdu_t recv_eapol_pdu; /**< Received EAPOL PDU */
tls_data_t tls_send; /**< EAP-TLS send buffer */
uint16_t recv_eap_msg_len; /**< Received EAP message length */
uint8_t *recv_eap_msg; /**< Received EAP message */
uint16_t burst_filt_timer; /**< Burst filter timer */
@ -88,15 +91,18 @@ static void radius_eap_tls_sec_prot_create_request(sec_prot_t *prot, sec_prot_ke
static void radius_eap_tls_sec_prot_delete(sec_prot_t *prot);
static int8_t radius_eap_tls_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size);
static int8_t radius_eap_tls_sec_prot_radius_client_receive(sec_prot_t *radius_client, void *pdu, uint16_t size);
static void radius_eap_tls_sec_prot_eap_tls_msg_free(sec_prot_t *prot);
static int8_t radius_eap_tls_sec_prot_radius_eap_message_forward(sec_prot_t *prot, uint8_t *eap_code);
static int8_t radius_eap_tls_sec_prot_radius_eap_message_retry(sec_prot_t *prot);
static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot);
static int8_t radius_eap_tls_sec_prot_message_handle(sec_prot_t *prot, uint8_t *data_ptr, uint16_t *length);
static int8_t radius_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state);
static int8_t radius_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type);
static void radius_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
static int8_t radius_eap_tls_sec_prot_init_radius_client(sec_prot_t *prot);
static void radius_eap_tls_sec_prot_radius_client_deleted(sec_prot_t *prot);
static void radius_eap_tls_sec_prot_seq_id_update(sec_prot_t *prot);
@ -126,6 +132,7 @@ static int8_t radius_eap_tls_sec_prot_init(sec_prot_t *prot)
prot->create_resp = 0;
prot->receive = radius_eap_tls_sec_prot_receive;
prot->receive_peer = radius_eap_tls_sec_prot_radius_client_receive;
prot->peer_deleted = radius_eap_tls_sec_prot_radius_client_deleted;
prot->delete = radius_eap_tls_sec_prot_delete;
prot->state_machine = radius_eap_tls_sec_prot_state_machine;
prot->timer_timeout = radius_eap_tls_sec_prot_timer_timeout;
@ -142,7 +149,6 @@ static int8_t radius_eap_tls_sec_prot_init(sec_prot_t *prot)
data->recv_eap_id_seq = 0;
data->eap_code = 0;
data->eap_type = 0;
eap_tls_sec_prot_lib_message_init(&data->tls_send);
data->init_key_cnt = 0;
return 0;
}
@ -150,7 +156,10 @@ static int8_t radius_eap_tls_sec_prot_init(sec_prot_t *prot)
static void radius_eap_tls_sec_prot_delete(sec_prot_t *prot)
{
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
eap_tls_sec_prot_lib_message_free(&data->tls_send);
if (data->recv_eap_msg != NULL) {
ns_dyn_mem_free(data->recv_eap_msg);
}
}
static void radius_eap_tls_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_keys)
@ -242,30 +251,13 @@ static int8_t radius_eap_tls_sec_prot_message_handle(sec_prot_t *prot, uint8_t *
return EAP_TLS_MSG_CONTINUE;
}
static int8_t radius_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state)
static int8_t radius_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type)
{
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
uint8_t flags = 0xff;
// EAP-TLS flags field is always present during TLS exchange
if (tls_state == EAP_TLS_EXCHANGE_ONGOING) {
flags = 0x00;
}
if (eap_code == EAP_REQ) {
if (eap_type == EAP_TLS && tls_state == EAP_TLS_EXCHANGE_START) {
eap_tls_sec_prot_lib_message_allocate(&data->tls_send, TLS_HEAD_LEN, 0);
flags = EAP_TLS_START;
}
} else if (eap_code == EAP_SUCCESS || eap_code == EAP_FAILURE) {
// Send Success and Failure with same identifier as received in EAP Response
data->eap_id_seq = data->recv_eap_id_seq;
} else {
return -1;
}
uint16_t eapol_pdu_size;
uint8_t *eapol_decoded_data = eap_tls_sec_prot_lib_message_build(eap_code, eap_type, &flags, data->eap_id_seq, prot->header_size, &data->tls_send, &eapol_pdu_size);
uint8_t *eapol_decoded_data = eap_tls_sec_prot_lib_message_build(eap_code, eap_type, &flags, data->eap_id_seq, prot->header_size, NULL, &eapol_pdu_size);
if (!eapol_decoded_data) {
return -1;
}
@ -327,7 +319,23 @@ static int8_t radius_eap_tls_sec_prot_radius_eap_message_forward(sec_prot_t *pro
eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", data->eap_id_seq, flags, eapol_pdu_size,
trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
if (prot->send(prot, data->recv_eap_msg, eapol_pdu_size + prot->header_size) < 0) {
if (prot->conn_send(prot, data->recv_eap_msg, eapol_pdu_size + prot->header_size, 0, SEC_PROT_SEND_FLAG_NO_DEALLOC) < 0) {
return -1;
}
data->recv_eap_msg_len = eapol_pdu_size + prot->header_size;
return 0;
}
static int8_t radius_eap_tls_sec_prot_radius_eap_message_retry(sec_prot_t *prot)
{
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
if (data->recv_eap_msg == NULL || data->recv_eap_msg_len == 0) {
return -1;
}
if (prot->conn_send(prot, data->recv_eap_msg, data->recv_eap_msg_len, 0, SEC_PROT_SEND_FLAG_NO_DEALLOC) < 0) {
return -1;
}
@ -357,6 +365,10 @@ static int8_t radius_eap_tls_sec_prot_radius_client_receive(sec_prot_t *radius_c
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
if (data->recv_eap_msg != NULL) {
ns_dyn_mem_free(data->recv_eap_msg);
}
data->recv_eap_msg_len = size;
data->recv_eap_msg = pdu;
@ -365,6 +377,18 @@ static int8_t radius_eap_tls_sec_prot_radius_client_receive(sec_prot_t *radius_c
return 0;
}
static void radius_eap_tls_sec_prot_eap_tls_msg_free(sec_prot_t *prot)
{
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
if (data->recv_eap_msg != NULL) {
ns_dyn_mem_free(data->recv_eap_msg);
}
data->recv_eap_msg = NULL;
data->recv_eap_msg_len = 0;
}
static int8_t radius_eap_tls_sec_prot_init_radius_client(sec_prot_t *prot)
{
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
@ -377,10 +401,22 @@ static int8_t radius_eap_tls_sec_prot_init_radius_client(sec_prot_t *prot)
return -1;
}
data->radius_client_send = data->radius_client_prot->receive_peer;
data->radius_client_deleted = data->radius_client_prot->peer_deleted;
return 0;
}
static void radius_eap_tls_sec_prot_radius_client_deleted(sec_prot_t *prot)
{
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
tr_debug("EAP-TLS: client deleted");
data->radius_client_prot = NULL;
data->radius_client_send = NULL;
data->radius_client_deleted = NULL;
}
static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
{
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
@ -390,14 +426,14 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
// EAP-TLS authenticator state machine
switch (sec_prot_state_get(&data->common)) {
case EAP_TLS_STATE_INIT:
tr_info("EAP-TLS init");
tr_info("EAP-TLS: init");
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_CREATE_REQ);
prot->timer_start(prot);
break;
// Wait KMP-CREATE.request
case EAP_TLS_STATE_CREATE_REQ:
tr_info("EAP-TLS start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
tr_info("EAP-TLS: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
// Set default timeout for the total maximum length of the negotiation
sec_prot_default_timeout_set(&data->common);
@ -409,7 +445,7 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
radius_eap_tls_sec_prot_seq_id_update(prot);
// Sends EAP request, Identity
radius_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE);
radius_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY);
// Start trickle timer to re-send if no response
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
@ -423,7 +459,7 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
// On timeout
if (sec_prot_result_timeout_check(&data->common)) {
// Re-sends EAP request, Identity
radius_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE);
radius_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY);
return;
}
@ -432,13 +468,22 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
return;
}
tr_info("EAP-TLS EAP response id, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
tr_info("EAP-TLS: EAP response id, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
if (radius_eap_tls_sec_prot_init_radius_client(prot) < 0) {
tr_error("EAP-TLS: radius client init failed");
return;
}
// Free EAP request buffer since answer received and retries not needed
radius_eap_tls_sec_prot_eap_tls_msg_free(prot);
// Stop trickle timer, radius client will continue
sec_prot_timer_trickle_stop(&data->common);
// Set timeout to wait for RADIUS client to continue
data->common.ticks = RADIUS_EAP_TLS_CLIENT_TIMEOUT;
// Send to radius client
data->radius_client_send(data->radius_client_prot, (void *) &data->recv_eapol_pdu, length);
@ -450,11 +495,11 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
// On timeout
if (sec_prot_result_timeout_check(&data->common)) {
// Do nothing for now
// Do nothing (trickle timer not running, so should not happen)
return;
}
tr_info("EAP-TLS EAP request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
tr_info("EAP-TLS: EAP request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
uint8_t eap_code;
if (radius_eap_tls_sec_prot_radius_eap_message_forward(prot, &eap_code) < 0) {
@ -470,6 +515,9 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_FINISH);
}
// Start trickle timer to re-send if no response
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_EAP_RESPONSE);
break;
@ -478,17 +526,29 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
// On timeout
if (sec_prot_result_timeout_check(&data->common)) {
// Do nothing for now
tr_debug("EAP-TLS: retry EAP request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
if (radius_eap_tls_sec_prot_radius_eap_message_retry(prot) < 0) {
tr_error("EAP-TLS: retry msg send error");
}
return;
}
tr_info("EAP-TLS EAP response, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
tr_info("EAP-TLS: EAP response, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
// Handle EAP response
if (radius_eap_tls_sec_prot_message_handle(prot, data_ptr, &length) != EAP_TLS_MSG_CONTINUE) {
return;
}
// Free EAP request buffer since answer received and retries not needed
radius_eap_tls_sec_prot_eap_tls_msg_free(prot);
// Stop trickle timer, radius client will continue
sec_prot_timer_trickle_stop(&data->common);
// Set timeout to wait for RADIUS client to continue
data->common.ticks = RADIUS_EAP_TLS_CLIENT_TIMEOUT;
// Send to radius client
data->radius_client_send(data->radius_client_prot, (void *) &data->recv_eapol_pdu, length);
@ -507,6 +567,12 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
case EAP_TLS_STATE_FINISHED: {
uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot);
tr_info("EAP-TLS finished, eui-64: %s", remote_eui_64 ? trace_array(sec_prot_remote_eui_64_addr_get(prot), 8) : "not set");
// Indicate to radius client peer protocol that radius EAP-TLS has been deleted
if (data->radius_client_deleted) {
data->radius_client_deleted(data->radius_client_prot);
}
prot->timer_stop(prot);
prot->finished(prot);
break;

View File

@ -46,8 +46,8 @@
// EUI-64 in ascii string: 00-11-..-77
#define STATION_ID_LEN 16 + 7
// MTU value TBD
#define FRAMED_MTU 1400
// MTU value is set by EAP-TLS fragment length
#define FRAMED_MTU EAP_TLS_FRAGMENT_LEN_VALUE
#define NAS_PORT 1

View File

@ -75,12 +75,17 @@ typedef enum {
#define MS_MPPE_RECV_KEY_SALT_LEN 2
#define MS_MPPE_RECV_KEY_BLOCK_LEN 16
#define RADIUS_CONN_NUMBER 3
#define RADIUS_ID_RANGE_SIZE 10
#define RADIUS_ID_RANGE_NUM (255 / RADIUS_ID_RANGE_SIZE) - 1
typedef struct radius_client_sec_prot_lib_int_s radius_client_sec_prot_lib_int_t;
typedef struct {
sec_prot_common_t common; /**< Common data */
sec_prot_t *radius_eap_tls_prot; /**< Radius EAP-TLS security protocol */
sec_prot_receive *radius_eap_tls_send; /**< Radius EAP-TLS security protocol send (receive from peer) */
sec_prot_delete *radius_eap_tls_deleted; /**< Radius EAP-TLS security protocol peer deleted (notify to peer that radius client deleted) */
uint8_t radius_eap_tls_header_size; /**< Radius EAP-TLS header size */
uint8_t new_pmk[PMK_LEN]; /**< New Pair Wise Master Key */
uint16_t recv_eap_msg_len; /**< Received EAP message length */
@ -91,34 +96,46 @@ typedef struct {
uint8_t *identity; /**< Supplicant EAP identity */
uint8_t radius_code; /**< Radius code that was received */
uint8_t radius_identifier; /**< Radius identifier that was last sent */
uint8_t radius_id_conn_num; /**< Radius identifier connection number (socket instance) */
uint8_t radius_id_range; /**< Radius identifier range */
uint8_t request_authenticator[16]; /**< Radius request authenticator that was last sent */
uint8_t state_len; /**< Radius state length that was last received */
uint8_t *state; /**< Radius state that was last received */
uint8_t remote_eui_64_hash[8]; /**< Remote EUI-64 hash used for calling station id */
bool remote_eui_64_hash_set : 1; /**< Remote EUI-64 hash used for calling station id set */
bool new_pmk_set : 1; /**< New Pair Wise Master Key set */
bool radius_id_range_set : 1; /**< Radius identifier start value set */
} radius_client_sec_prot_int_t;
typedef struct {
uint8_t radius_client_identifier; /**< Radius client identifier */
uint8_t radius_identifier_timer[RADIUS_CONN_NUMBER][RADIUS_ID_RANGE_NUM];
shared_comp_data_t comp_data; /**< Shared component data (timer, delete) */
uint8_t local_eui64_hash[8]; /**< Local EUI-64 hash used for called stations id */
uint8_t hash_random[16]; /**< Random used to generate local and remote EUI-64 hashes */
bool local_eui64_hash_set : 1; /**< Local EUI-64 hash used for called stations id set */
bool hash_random_set : 1; /**< Random used to generate local and remote EUI-64 hashes set */
bool radius_id_timer_running : 1; /**> Radius identifier timer running */
} radius_client_sec_prot_shared_t;
static uint16_t radius_client_sec_prot_size(void);
static int8_t radius_client_sec_prot_init(sec_prot_t *prot);
static int8_t radius_client_sec_prot_shared_data_timeout(uint16_t ticks);
static void radius_identifier_timer_value_set(uint8_t conn_num, uint8_t id_range, uint8_t value);
static int8_t radius_client_sec_prot_shared_data_delete(void);
static void radius_identifier_timer_value_set(uint8_t conn_num, uint8_t id_range, uint8_t value);
static void radius_client_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result);
static void radius_client_sec_prot_delete(sec_prot_t *prot);
static int8_t radius_client_sec_prot_receive_check(sec_prot_t *prot, const void *pdu, uint16_t size);
static int8_t radius_client_sec_prot_init_radius_eap_tls(sec_prot_t *prot);
static void radius_client_sec_prot_radius_eap_tls_deleted(sec_prot_t *prot);
static uint16_t radius_client_sec_prot_eap_avps_handle(uint16_t avp_length, uint8_t *avp_ptr, uint8_t *copy_to_ptr);
static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size);
static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number);
static int8_t radius_client_sec_prot_radius_eap_receive(sec_prot_t *prot, void *pdu, uint16_t size);
static void radius_client_sec_prot_allocate_and_create_radius_message(sec_prot_t *prot);
static int8_t radius_client_sec_prot_radius_msg_send(sec_prot_t *prot);
static uint8_t radius_client_sec_prot_identifier_allocate(void);
static void radius_client_sec_prot_radius_msg_free(sec_prot_t *prot);
static uint8_t radius_client_sec_prot_identifier_allocate(sec_prot_t *prot, uint8_t value);
static void radius_client_sec_prot_identifier_free(sec_prot_t *prot);
static uint8_t radius_client_sec_prot_hex_to_ascii(uint8_t value);
static int8_t radius_client_sec_prot_eui_64_hash_generate(uint8_t *eui_64, uint8_t *hashed_eui_64);
static void radius_client_sec_prot_station_id_generate(uint8_t *eui_64, uint8_t *station_id_ptr);
@ -152,12 +169,55 @@ static uint16_t radius_client_sec_prot_size(void)
return sizeof(radius_client_sec_prot_int_t);
}
static int8_t radius_client_sec_prot_shared_data_timeout(uint16_t ticks)
{
if (shared_data == NULL || !shared_data->radius_id_timer_running) {
return -1;
}
bool timer_running = false;
for (uint8_t conn_num = 0; conn_num < RADIUS_CONN_NUMBER; conn_num++) {
for (uint8_t id_range = 0; id_range < RADIUS_ID_RANGE_NUM; id_range++) {
if (shared_data->radius_identifier_timer[conn_num][id_range] > ticks) {
shared_data->radius_identifier_timer[conn_num][id_range] -= ticks;
timer_running = true;
} else {
shared_data->radius_identifier_timer[conn_num][id_range] = 0;
}
}
}
if (!timer_running) {
shared_data->radius_id_timer_running = false;
}
return 0;
}
static void radius_identifier_timer_value_set(uint8_t conn_num, uint8_t id_range, uint8_t value)
{
shared_data->radius_identifier_timer[conn_num][id_range] = value;
shared_data->radius_id_timer_running = true;
}
static int8_t radius_client_sec_prot_shared_data_delete(void)
{
if (shared_data == NULL) {
return -1;
}
ns_dyn_mem_free(shared_data);
shared_data = NULL;
return 0;
}
static int8_t radius_client_sec_prot_init(sec_prot_t *prot)
{
prot->create_req = NULL;
prot->create_resp = radius_client_sec_prot_create_response;
prot->receive = radius_client_sec_prot_receive;
prot->conn_receive = radius_client_sec_prot_receive;
prot->receive_peer = radius_client_sec_prot_radius_eap_receive;
prot->peer_deleted = radius_client_sec_prot_radius_eap_tls_deleted;
prot->delete = radius_client_sec_prot_delete;
prot->state_machine = radius_client_sec_prot_state_machine;
prot->timer_timeout = radius_client_sec_prot_timer_timeout;
@ -192,11 +252,14 @@ static int8_t radius_client_sec_prot_init(sec_prot_t *prot)
if (!shared_data) {
return -1;
}
shared_data->radius_client_identifier = 0;
memset(shared_data->local_eui64_hash, 0, 8);
memset(shared_data->hash_random, 0, 16);
memset(shared_data, 0, sizeof(radius_client_sec_prot_shared_t));
shared_data->local_eui64_hash_set = false;
shared_data->hash_random_set = false;
shared_data->radius_id_timer_running = false;
// Add as shared component to enable timers and delete
shared_data->comp_data.timeout = radius_client_sec_prot_shared_data_timeout;
shared_data->comp_data.delete = radius_client_sec_prot_shared_data_delete;
prot->shared_comp_add(prot, &shared_data->comp_data);
}
return 0;
@ -256,10 +319,22 @@ static int8_t radius_client_sec_prot_init_radius_eap_tls(sec_prot_t *prot)
}
data->radius_eap_tls_header_size = data->radius_eap_tls_prot->receive_peer_hdr_size;
data->radius_eap_tls_send = data->radius_eap_tls_prot->receive_peer;
data->radius_eap_tls_deleted = data->radius_eap_tls_prot->peer_deleted;
return 0;
}
static void radius_client_sec_prot_radius_eap_tls_deleted(sec_prot_t *prot)
{
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
tr_info("Radius: EAP-TLS deleted");
data->radius_eap_tls_prot = NULL;
data->radius_eap_tls_send = NULL;
data->radius_eap_tls_deleted = NULL;
}
static uint16_t radius_client_sec_prot_eap_avps_handle(uint16_t avp_length, uint8_t *avp_ptr, uint8_t *copy_to_ptr)
{
// Calculate EAP AVPs length and copy EAP AVPs to continuous buffer if buffer is give
@ -290,8 +365,10 @@ static uint16_t radius_client_sec_prot_eap_avps_handle(uint16_t avp_length, uint
return eap_len;
}
static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size)
static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number)
{
(void) conn_number;
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
if (size < RADIUS_MSG_FIXED_LENGTH) {
@ -312,6 +389,10 @@ static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16
uint16_t length = common_read_16_bit(radius_msg_ptr);
radius_msg_ptr += 2;
if (length < RADIUS_MSG_FIXED_LENGTH) {
return -1;
}
// Store response authenticator
uint8_t recv_response_authenticator[16];
memcpy(recv_response_authenticator, radius_msg_ptr, 16);
@ -333,11 +414,23 @@ static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16
return -1;
}
uint16_t avp_length = length - RADIUS_MSG_FIXED_LENGTH;
// Response authenticator matches, start validating radius EAP-TLS specific fields
data->recv_eap_msg = NULL;
data->recv_eap_msg_len = 0;
uint16_t avp_length = 0;
if (length >= RADIUS_MSG_FIXED_LENGTH) {
avp_length = length - RADIUS_MSG_FIXED_LENGTH;
}
uint8_t *message_authenticator = avp_message_authenticator_read(radius_msg_ptr, avp_length);
if (message_authenticator == NULL) {
if (message_authenticator == NULL || avp_length == 0) {
tr_error("No message authenticator");
// Message does not have radius EAP-TLS specific fields
data->radius_code = code;
prot->state_machine(prot);
return 0;
}
// Store message authenticator
@ -415,7 +508,9 @@ static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16
if (radius_client_sec_prot_ms_mppe_recv_key_pmk_decrypt(prot, recv_key,
recv_key_len - AVP_FIXED_LEN, data->request_authenticator, data->new_pmk) >= 0) {
data->new_pmk_set = true;
#ifdef EXTRA_DEBUG_INFO
tr_info("RADIUS PMK: %s %s", tr_array(data->new_pmk, 16), tr_array(data->new_pmk + 16, 16));
#endif
}
}
}
@ -442,9 +537,43 @@ static int8_t radius_client_sec_prot_radius_eap_receive(sec_prot_t *prot, void *
return 0;
}
static uint8_t radius_client_sec_prot_identifier_allocate(void)
static uint8_t radius_client_sec_prot_identifier_allocate(sec_prot_t *prot, uint8_t value)
{
return shared_data->radius_client_identifier++;
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
if (!data->radius_id_range_set || value >= (data->radius_id_range * RADIUS_ID_RANGE_SIZE) + RADIUS_ID_RANGE_SIZE) {
for (uint8_t conn_num = 0; conn_num < RADIUS_CONN_NUMBER; conn_num++) {
for (uint8_t id_range = 0; id_range < RADIUS_ID_RANGE_NUM; id_range++) {
if (shared_data->radius_identifier_timer[conn_num][id_range] == 0) {
// If range has been already reserved
if (data->radius_id_range_set) {
// Set previous range to timeout in 5 seconds
radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, 5);
}
// Set timeout for new range to 60 seconds
radius_identifier_timer_value_set(conn_num, id_range, 60);
data->radius_id_conn_num = conn_num;
data->radius_id_range = id_range;
data->radius_id_range_set = true;
return id_range * RADIUS_ID_RANGE_SIZE;
}
}
}
} else {
radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, 60);
return value + 1;
}
return 0;
}
static void radius_client_sec_prot_identifier_free(sec_prot_t *prot)
{
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
if (data->radius_id_range_set) {
radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, 5);
}
}
static uint8_t radius_client_sec_prot_eui_64_hash_get(sec_prot_t *prot, uint8_t *local_eui_64_hash, uint8_t *remote_eui_64_hash, bool remote_eui_64_hash_set)
@ -524,7 +653,7 @@ static void radius_client_sec_prot_allocate_and_create_radius_message(sec_prot_t
uint8_t *radius_msg_start_ptr = radius_msg_ptr;
*radius_msg_ptr++ = RADIUS_ACCESS_REQUEST; // code
data->radius_identifier = radius_client_sec_prot_identifier_allocate();
data->radius_identifier = radius_client_sec_prot_identifier_allocate(prot, data->radius_identifier);
*radius_msg_ptr++ = data->radius_identifier; // identifier
radius_msg_ptr = common_write_16_bit(radius_msg_length, radius_msg_ptr); // length
@ -604,15 +733,25 @@ static int8_t radius_client_sec_prot_radius_msg_send(sec_prot_t *prot)
return -1;
}
if (prot->send(prot, data->send_radius_msg, data->send_radius_msg_len) < 0) {
if (prot->conn_send(prot, data->send_radius_msg, data->send_radius_msg_len, data->radius_id_conn_num, SEC_PROT_SEND_FLAG_NO_DEALLOC) < 0) {
return -1;
}
data->send_radius_msg = NULL;
data->send_radius_msg_len = 0;
return 0;
}
static void radius_client_sec_prot_radius_msg_free(sec_prot_t *prot)
{
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
if (data->send_radius_msg != NULL) {
ns_dyn_mem_free(data->send_radius_msg);
}
data->send_radius_msg = NULL;
data->send_radius_msg_len = 0;
}
static int8_t radius_client_sec_prot_eui_64_hash_generate(uint8_t *eui_64, uint8_t *hashed_eui_64)
{
int8_t ret_val = 0;
@ -678,12 +817,13 @@ static void radius_client_sec_prot_station_id_generate(uint8_t *eui_64, uint8_t
static int8_t radius_client_sec_prot_message_authenticator_calc(sec_prot_t *prot, uint16_t msg_len, uint8_t *msg_ptr, uint8_t *auth_ptr)
{
const uint8_t *key = prot->sec_cfg->radius_cfg.radius_shared_secret;
uint16_t key_len = prot->sec_cfg->radius_cfg.radius_shared_secret_len;
if (prot->sec_cfg->radius_cfg.radius_shared_secret_len == 0) {
if (prot->sec_cfg->radius_cfg->radius_shared_secret == NULL || prot->sec_cfg->radius_cfg->radius_shared_secret_len == 0) {
return -1;
}
const uint8_t *key = prot->sec_cfg->radius_cfg->radius_shared_secret;
uint16_t key_len = prot->sec_cfg->radius_cfg->radius_shared_secret_len;
#ifndef MBEDTLS_MD5_C
tr_error("FATAL: MD5 MBEDTLS_MD5_C not enabled");
#endif
@ -698,9 +838,13 @@ static int8_t radius_client_sec_prot_message_authenticator_calc(sec_prot_t *prot
static int8_t radius_client_sec_prot_response_authenticator_calc(sec_prot_t *prot, uint16_t msg_len, uint8_t *msg_ptr, uint8_t *auth_ptr)
{
#ifdef MBEDTLS_MD5_C
const uint8_t *key = prot->sec_cfg->radius_cfg.radius_shared_secret;
uint16_t key_len = prot->sec_cfg->radius_cfg.radius_shared_secret_len;
if (prot->sec_cfg->radius_cfg.radius_shared_secret_len == 0) {
if (prot->sec_cfg->radius_cfg->radius_shared_secret == NULL || prot->sec_cfg->radius_cfg->radius_shared_secret_len == 0) {
return -1;
}
const uint8_t *key = prot->sec_cfg->radius_cfg->radius_shared_secret;
uint16_t key_len = prot->sec_cfg->radius_cfg->radius_shared_secret_len;
if (prot->sec_cfg->radius_cfg->radius_shared_secret_len == 0) {
return -1;
}
@ -747,9 +891,13 @@ end:
static int8_t radius_client_sec_prot_ms_mppe_recv_key_pmk_decrypt(sec_prot_t *prot, uint8_t *recv_key, uint8_t recv_key_len, uint8_t *request_authenticator, uint8_t *pmk_ptr)
{
#ifdef MBEDTLS_MD5_C
const uint8_t *key = prot->sec_cfg->radius_cfg.radius_shared_secret;
uint16_t key_len = prot->sec_cfg->radius_cfg.radius_shared_secret_len;
if (prot->sec_cfg->radius_cfg.radius_shared_secret_len == 0) {
if (prot->sec_cfg->radius_cfg->radius_shared_secret == NULL || prot->sec_cfg->radius_cfg->radius_shared_secret_len == 0) {
return -1;
}
const uint8_t *key = prot->sec_cfg->radius_cfg->radius_shared_secret;
uint16_t key_len = prot->sec_cfg->radius_cfg->radius_shared_secret_len;
if (prot->sec_cfg->radius_cfg->radius_shared_secret_len == 0) {
return -1;
}
@ -852,8 +1000,7 @@ static void radius_client_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t tick
{
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
sec_prot_timer_timeout_handle(prot, &data->common,
&prot->sec_cfg->prot_cfg.sec_prot_trickle_params, ticks);
sec_prot_timer_timeout_handle(prot, &data->common, &prot->sec_cfg->radius_cfg->radius_retry_trickle_params, ticks);
}
static void radius_client_sec_prot_state_machine(sec_prot_t *prot)
@ -862,14 +1009,14 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot)
switch (sec_prot_state_get(&data->common)) {
case RADIUS_STATE_INIT:
tr_debug("Radius: init");
tr_info("Radius: init");
sec_prot_state_set(prot, &data->common, RADIUS_STATE_STATE_RESPONSE_ID);
prot->timer_start(prot);
break;
// Wait EAP response, Identity (starts RADIUS Client protocol)
case RADIUS_STATE_STATE_RESPONSE_ID:
tr_debug("Radius: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
tr_info("Radius: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
// Set default timeout for the total maximum length of the negotiation
sec_prot_default_timeout_set(&data->common);
@ -899,14 +1046,14 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot)
break;
case RADIUS_STATE_SEND_INITIAL_ACCESS_REQUEST:
tr_debug("Radius: send initial access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
tr_info("Radius: send initial access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
if (radius_client_sec_prot_radius_msg_send(prot) < 0) {
tr_error("Radius: msg send error");
}
// Start trickle timer to re-send if no response
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->radius_cfg->radius_retry_trickle_params);
sec_prot_state_set(prot, &data->common, RADIUS_STATE_ACCESS_ACCEPT_REJECT_CHALLENGE);
break;
@ -915,14 +1062,32 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot)
// On timeout
if (sec_prot_result_timeout_check(&data->common)) {
// Do nothing for now
tr_info("Radius: retry access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
if (radius_client_sec_prot_radius_msg_send(prot) < 0) {
tr_error("Radius: retry msg send error");
}
return;
}
tr_debug("Radius: received access accept/reject/challenge, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
tr_info("Radius: received access accept/reject/challenge, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
// Free radius access-request buffer since answer received and retries not needed
radius_client_sec_prot_radius_msg_free(prot);
// Stop trickle timer, EAP-TLS will continue and on reject/accept negotiation will end
sec_prot_timer_trickle_stop(&data->common);
// Set timeout to wait for EAP-TLS to continue
data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout;
// Send to radius EAP-TLS
if (data->radius_eap_tls_send && data->radius_eap_tls_prot && data->recv_eap_msg && data->recv_eap_msg_len > 0) {
data->radius_eap_tls_send(data->radius_eap_tls_prot, (void *) data->recv_eap_msg, data->recv_eap_msg_len);
} else {
if (data->recv_eap_msg) {
ns_dyn_mem_free(data->recv_eap_msg);
}
}
data->recv_eap_msg = NULL;
data->recv_eap_msg_len = 0;
@ -945,11 +1110,14 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot)
// On timeout
if (sec_prot_result_timeout_check(&data->common)) {
// Do nothing for now
tr_info("Radius: retry access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
if (radius_client_sec_prot_radius_msg_send(prot) < 0) {
tr_error("Radius: retry msg send error");
}
return;
}
tr_debug("Radius: send access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
tr_info("Radius: send access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
radius_client_sec_prot_allocate_and_create_radius_message(prot);
@ -957,11 +1125,14 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot)
tr_error("Radius: msg send error");
}
// Start trickle timer to re-send if no response
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->radius_cfg->radius_retry_trickle_params);
sec_prot_state_set(prot, &data->common, RADIUS_STATE_ACCESS_ACCEPT_REJECT_CHALLENGE);
break;
case RADIUS_STATE_FINISH:
tr_debug("Radius: finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
tr_info("Radius: finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
if (sec_prot_result_ok_check(&data->common)) {
sec_prot_keys_pmk_write(prot->sec_keys, data->new_pmk, prot->sec_cfg->timer_cfg.pmk_lifetime);
@ -980,7 +1151,14 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot)
case RADIUS_STATE_FINISHED: {
uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot);
tr_debug("Radius: finished, eui-64: %s", remote_eui_64 ? trace_array(remote_eui_64, 8) : "not set");
tr_info("Radius: finished, eui-64: %s", remote_eui_64 ? trace_array(remote_eui_64, 8) : "not set");
radius_client_sec_prot_identifier_free(prot);
// Indicate to radius EAP-TLS peer protocol that radius client has been deleted
if (data->radius_eap_tls_deleted) {
data->radius_eap_tls_deleted(data->radius_eap_tls_prot);
}
prot->timer_stop(prot);
prot->finished(prot);

View File

@ -61,6 +61,9 @@ typedef enum {
SEC_PROT_TX_ERR_UNSPEC = -2, // Other reason
} sec_prot_tx_status_e;
// On security protocol send, do not deallocate pdu buffer
#define SEC_PROT_SEND_FLAG_NO_DEALLOC 0x01
/**
* sec_prot_create_request KMP-CREATE.request to security protocol
*
@ -128,6 +131,7 @@ typedef void sec_prot_finished_send(sec_prot_t *prot);
* \param prot protocol
* \param pdu pdu
* \param size pdu size
* \param conn_number connection number
*
* \return < 0 failure
* \return >= 0 success
@ -148,6 +152,35 @@ 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_conn_receive receive a message for a connection number
*
* \param prot protocol
* \param pdu pdu
* \param size pdu size
* \param conn_number connection number
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t sec_prot_conn_receive(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number);
/**
* sec_prot_conn_send send a message for a connection number and/or with flags
*
* \param prot protocol
* \param pdu pdu
* \param size pdu size
* \param conn_number connection number
* \param flags flags
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t sec_prot_conn_send(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number, uint8_t flags);
/**
* sec_prot_tx_status_ind tx status indication
*
@ -184,6 +217,14 @@ typedef void sec_prot_state_machine(sec_prot_t *prot);
*/
typedef void sec_prot_state_machine_call(sec_prot_t *prot);
/**
* sec_prot_cont_timer_timeout cont timer timeout
*
* \param ticks timer ticks
*
*/
typedef void sec_prot_cont_timer_timeout(uint16_t ticks);
/**
* sec_prot_timer_start start timer
*
@ -209,6 +250,55 @@ typedef void sec_prot_timer_stop(sec_prot_t *prot);
*/
typedef void sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
/**
* sec_prot_shared_comp_timer_timeout shared component timer timeout
*
* \param ticks timer ticks
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t sec_prot_shared_comp_timer_timeout(uint16_t ticks);
/**
* sec_prot_shared_comp_delete shared component delete
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t sec_prot_shared_comp_delete(void);
typedef struct {
sec_prot_shared_comp_timer_timeout *timeout;
sec_prot_shared_comp_delete *delete;
} shared_comp_data_t;
/**
* sec_prot_shared_comp_add add shared component
*
* \param prot protocol
* \param data shared component data
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t sec_prot_shared_comp_add(sec_prot_t *prot, shared_comp_data_t *data);
/**
* sec_prot_shared_comp_remove remove shared component
*
* \param prot protocol
* \param data shared component data
*
* \return < 0 failure
* \return >= 0 success
*
*/
typedef int8_t sec_prot_shared_comp_remove(sec_prot_t *prot, shared_comp_data_t *data);
/**
* sec_prot_eui64_addr_get gets EUI-64 addresses
*
@ -277,7 +367,10 @@ struct sec_prot_s {
sec_prot_send *send; /**< Protocol send */
sec_prot_receive *receive; /**< Protocol receive */
sec_prot_conn_send *conn_send; /**< Protocol connection send */
sec_prot_conn_receive *conn_receive; /**< Protocol connection receive */
sec_prot_receive *receive_peer; /**< Protocol receive from peer (used by peer protocol for send) */
sec_prot_delete *peer_deleted; /**< Protocol peer has been deleted (notifies that peer no longer exists */
sec_prot_tx_status_ind *tx_status_ind; /**< TX status indication */
@ -290,6 +383,9 @@ struct sec_prot_s {
sec_prot_timer_stop *timer_stop; /**< Stop timer */
sec_prot_timer_timeout *timer_timeout; /**< Timer timeout */
sec_prot_shared_comp_add *shared_comp_add; /**< Shared component add */
sec_prot_shared_comp_remove *shared_comp_remove; /**< Shared component remove */
sec_prot_eui64_addr_get *addr_get; /**< Gets EUI-64 addresses */
sec_prot_ip_addr_get *ip_addr_get; /**< Gets IP address */
sec_prot_by_type_get *type_get; /**< Gets security protocol by type */
@ -300,6 +396,7 @@ struct sec_prot_s {
sec_cfg_t *sec_cfg; /**< Security configuration configuration pointer */
uint8_t header_size; /**< Header size */
uint8_t receive_peer_hdr_size; /**< Receive from peer header size */
uint8_t number_of_conn; /**< Number of connections */
uint8_t msg_if_instance_id; /**< Message interface instance identifier */
sec_prot_int_data_t *data; /**< Protocol internal data */
};

View File

@ -47,15 +47,16 @@ typedef struct sec_timer_cfg_s {
typedef struct sec_radius_cfg_s {
uint8_t radius_addr[16]; /**< Radius server IPv6 address */
uint8_t *radius_shared_secret; /**< Radius shared secret */
const uint8_t *radius_shared_secret; /**< Radius shared secret */
uint16_t radius_shared_secret_len; /**< Radius shared secret length */
trickle_params_t radius_retry_trickle_params; /**< Radius retry trickle params */
bool radius_addr_set : 1; /**< Radius server address is set */
} sec_radius_cfg_t;
typedef struct sec_cfg_s {
sec_prot_cfg_t prot_cfg;
sec_timer_cfg_t timer_cfg;
sec_radius_cfg_t radius_cfg;
sec_radius_cfg_t *radius_cfg;
} sec_cfg_t;
#endif /* SEC_PROT_CONF_H_ */

View File

@ -419,7 +419,7 @@ static uint32_t fhss_ws_calculate_ufsi(fhss_structure_t *fhss_structure, uint32_
cur_slot--;
uint32_t remaining_time_ms = 0;
if (fhss_structure->ws->unicast_timer_running == true) {
remaining_time_ms = US_TO_MS(get_remaining_slots_us(fhss_structure, fhss_unicast_handler, MS_TO_US(dwell_time) - NS_TO_US(dwell_time * fhss_structure->ws->drift_per_millisecond_ns)));
remaining_time_ms = US_TO_MS(get_remaining_slots_us(fhss_structure, fhss_unicast_handler, MS_TO_US(dwell_time) - NS_TO_US((int64_t)(fhss_structure->ws->drift_per_millisecond_ns * dwell_time))));
}
uint32_t time_to_tx = 0;
uint32_t cur_time = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api);
@ -859,13 +859,13 @@ static uint32_t fhss_ws_get_retry_period_callback(const fhss_api_t *api, uint8_t
if (!fhss_structure) {
return return_value;
}
// We don't know the broadcast schedule, use large backoff with MAC retries
// We don't know the broadcast schedule, use randomised large backoff with MAC retries
if (fhss_structure->ws->broadcast_timer_running == false) {
return 100000;
return (uint32_t) randLIB_get_random_in_range(20000, 45000);
}
// We don't know the TX/RX slots, use randomised large backoff with MAC retries
if (fhss_structure->own_hop == 0xff) {
return ((uint32_t) randLIB_get_random_in_range(50, 150) * 1000);
return (uint32_t) randLIB_get_random_in_range(20000, 45000);
}
if (fhss_structure->ws->is_on_bc_channel == true) {
return return_value;
@ -980,7 +980,6 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_TR51CF) {
fhss_structure->ws->bc_slot %= fhss_structure->number_of_channels;
}
platform_exit_critical();
//TODO: support multiple parents
fhss_structure->ws->parent_bc_info = bc_timing_info;
if (prev_synchronization_time && fhss_structure->ws->fhss_configuration.ws_bc_channel_function != WS_FIXED_CHANNEL) {
@ -993,11 +992,15 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
} else if (drift_per_ms_tmp < -MAX_DRIFT_COMPENSATION_STEP) {
drift_per_ms_tmp = -MAX_DRIFT_COMPENSATION_STEP;
}
// Timer drift is unpredictable with linux platform. Do not set drift compensation
#ifndef __linux__
fhss_structure->ws->drift_per_millisecond_ns += drift_per_ms_tmp;
#endif
fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, NS_TO_US((int64_t)(fhss_structure->ws->drift_per_millisecond_ns * bc_timing_info->broadcast_dwell_interval)));
}
tr_debug("synch to parent: %s, drift: %"PRIi32"ms in %"PRIu64" seconds, compensation: %"PRIi32"ns per ms", trace_array(eui64, 8), true_bc_interval_offset - own_bc_interval_offset + ((int32_t)(fhss_structure->ws->bc_slot - own_bc_slot) * bc_timing_info->broadcast_interval), US_TO_S(time_since_last_synch_us), fhss_structure->ws->drift_per_millisecond_ns);
}
platform_exit_critical();
fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_INTERVAL, US_TO_S(time_since_last_synch_us));
return 0;
}

View File

@ -86,10 +86,18 @@ typedef struct {
} msg_tr_t;
typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t;
typedef struct {
dhcp_relay_neighbour_cb *recv_notify_cb;
int8_t interface_id;
ns_list_link_t link;
} relay_notify_t;
typedef NS_LIST_HEAD(relay_notify_t, link) relay_notify_list_t;
typedef struct {
ns_address_t src_address;
server_instance_list_t srv_list;
relay_instance_list_t relay_list;
relay_notify_list_t notify_list;
tr_list_t tr_list;
int8_t dhcp_server_socket;
int8_t dhcp_client_socket;
@ -134,6 +142,7 @@ bool dhcp_service_allocate(void)
if (dhcp_service) {
ns_list_init(&dhcp_service->srv_list);
ns_list_init(&dhcp_service->relay_list);
ns_list_init(&dhcp_service->notify_list);
ns_list_init(&dhcp_service->tr_list);
dhcp_service->dhcp_client_socket = -1;
dhcp_service->dhcp_server_socket = -1;
@ -255,6 +264,16 @@ static uint16_t dhcp_service_relay_interface_get(int8_t interface_id)
return 0;
}
static relay_notify_t *dhcp_service_notify_find(int8_t interface_id)
{
relay_notify_t *result = NULL;
ns_list_foreach(relay_notify_t, cur_ptr, &dhcp_service->notify_list) {
if (cur_ptr->interface_id == interface_id) {
result = cur_ptr;
}
}
return result;
}
static relay_instance_t *dhcp_service_relay_find(uint16_t instance_id)
@ -294,6 +313,8 @@ void recv_dhcp_server_msg(void *cb_res)
if (sckt_data->event_type != SOCKET_DATA || sckt_data->d_len < 4) {
return;
}
relay_notify_t *neigh_notify = NULL;
tr_debug("dhcp Server recv request");
msg_tr_ptr = dhcp_tr_create();
msg_ptr = ns_dyn_mem_temporary_alloc(sckt_data->d_len);
@ -322,6 +343,9 @@ void recv_dhcp_server_msg(void *cb_res)
} else if (msg_type == DHCPV6_RELAY_REPLY) {
tr_error("Relay reply drop at server");
goto cleanup;
} else {
//Search only for direct messages here
neigh_notify = dhcp_service_notify_find(sckt_data->interface_id);
}
//TODO use real function from lib also call validity check
@ -331,6 +355,11 @@ void recv_dhcp_server_msg(void *cb_res)
tr_error("Malformed packet");
goto cleanup;
}
if (neigh_notify && neigh_notify->recv_notify_cb) {
neigh_notify->recv_notify_cb(sckt_data->interface_id, msg_tr_ptr->addr.address);
}
msg_tr_ptr->socket = sckt_data->socket_id;
// call all receivers until found.
ns_list_foreach(server_instance_t, cur_ptr, &dhcp_service->srv_list) {
@ -451,6 +480,12 @@ void recv_dhcp_relay_msg(void *cb_res)
libdhcpv6_dhcp_relay_msg_write(relay_frame, DHCPV6_RELAY_FORWARD, 0, src_address.address, gp_address);
libdhcpv6_dhcp_option_header_write(relay_frame + 34, msg_len);
//Update Neighbour table if necessary
relay_notify_t *neigh_notify = dhcp_service_notify_find(sckt_data->interface_id);
if (neigh_notify && neigh_notify->recv_notify_cb) {
neigh_notify->recv_notify_cb(sckt_data->interface_id, src_address.address);
}
//Copy DST address
memcpy(src_address.address, relay_srv->server_address, 16);
src_address.type = ADDRESS_IPV6;
@ -884,6 +919,31 @@ bool dhcp_service_timer_tick(uint16_t ticks)
}
return activeTimerNeed;
}
int dhcp_service_link_local_rx_cb_set(int8_t interface_id, dhcp_relay_neighbour_cb *notify_cb)
{
if (dhcp_service == NULL) {
return -1;
}
relay_notify_t *notify_srv = dhcp_service_notify_find(interface_id);
if (notify_srv) {
notify_srv->recv_notify_cb = notify_cb;
return 0;
}
notify_srv = ns_dyn_mem_alloc(sizeof(relay_notify_t));
if (!notify_srv) {
return -1;
}
ns_list_add_to_start(&dhcp_service->notify_list, notify_srv);
notify_srv->recv_notify_cb = notify_cb;
notify_srv->interface_id = interface_id;
return 0;
}
#else
uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_type, dhcp_service_receive_req_cb *receive_req_cb)
{
@ -948,4 +1008,11 @@ void dhcp_service_req_remove_all(void *msg_class_ptr)
(void)msg_class_ptr;
}
int dhcp_service_link_local_rx_cb_set(int8_t interface_id, dhcp_relay_neighbour_cb *notify_cb)
{
(void) interface_id;
(void) notify_cb;
return -1;
}
#endif

View File

@ -234,6 +234,10 @@ dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_validate_class_pointer(void *
return NULL;
}
uint16_t libdhcpv6_vendor_option_size(uint16_t vendor_data_length)
{
return vendor_data_length + 8; // ID Type 2, length 2 ,Enterpise number 4
}
uint16_t libdhcpv6_duid_option_size(uint16_t duidLength)
{
@ -324,15 +328,6 @@ uint8_t *libdhcpv6_rapid_commit_option_write(uint8_t *ptr)
return ptr;
}
uint8_t *libdhcvp6_vendor_specific_option_write(uint8_t *ptr, uint8_t *data, uint16_t dataLength)
{
ptr = common_write_16_bit(DHCPV6_OPTION_VENDOR_SPECIFIC_INFO, ptr);
ptr = common_write_16_bit(dataLength, ptr);
memcpy(ptr, data, dataLength);
ptr += dataLength;
return ptr;
}
uint8_t *libdhcvp6_request_option_write(uint8_t *ptr, uint8_t optionCnt, uint16_t *optionPtr)
{
uint16_t optionLength = libdhcvp6_request_option_size(optionCnt);
@ -840,31 +835,6 @@ uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv
return ptr;
}
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)
{
ptr = libdhcpv6_header_write(ptr, DHCPV6_REPLY_TYPE, replyPacket->transaction_ID);
ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_SERVER_ID_OPTION, &replyPacket->serverDUID); //16
ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_CLIENT_ID_OPTION, &replyPacket->clientDUID); //16
if (nonTemporalAddress) {
ptr = libdhcpv6_identity_association_option_write(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, true);
ptr = libdhcpv6_ia_address_option_write(ptr, nonTemporalAddress->requestedAddress, nonTemporalAddress->preferredLifeTime, nonTemporalAddress->validLifeTime);
} else {
ptr = libdhcpv6_identity_association_option_write_with_status(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, DHCPV6_STATUS_NO_ADDR_AVAILABLE_CODE);
}
if (vendorData) {
ptr = libdhcvp6_vendor_specific_option_write(ptr, vendorData->vendorData, vendorData->vendorDataLength);
}
if (replyPacket->rapidCommit) {
ptr = libdhcpv6_rapid_commit_option_write(ptr);
}
return ptr;
}
uint16_t libdhcpv6_solication_message_length(uint16_t clientDUIDLength, bool addressDefined, uint8_t requestOptionCount)
{
uint16_t length = 0;

View File

@ -217,9 +217,13 @@ typedef struct dhcpv6_relay_msg {
#define DHCPV6_OPTION_IA_PREFIX_DELEGATION_MIN_LENGTH 0x000c
/** Identity Association END */
#define DHCPV6_OPTION_VENDOR_CLASS 0x0010
#define DHCPV6_OPTION_VENDOR_SPECIFIC_INFO 0x0011
/** SEQUENCYID, RouterIDMask 32-bit*/
#define DHCPV6_OPTION_DNS_SERVERS 0x0017
#define DHCPV6_OPTION_DOMAIN_LIST 0x0018
#define DHCPV6_STATUS_CODE_OPTION 0x000d
#define DHCPV6_STATUS_CODE_OPTION_LEN 0x0002
#define DHCPV6_STATUS_NO_ADDR_AVAILABLE_CODE 0x0002
@ -277,6 +281,7 @@ 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_vendor_option_size(uint16_t vendor_data_length);
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);
@ -287,7 +292,6 @@ uint16_t libdhcpv6_address_reply_message_len(uint16_t clientDUIDLength, uint16_t
#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_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);
@ -327,17 +331,6 @@ uint8_t *libdhcpv6_elapsed_time_option_write(uint8_t *ptr, uint16_t elapsedTime)
*/
uint8_t *libdhcpv6_rapid_commit_option_write(uint8_t *ptr);
/**
* This Function write dhcpv6 thread requested vendor spesific data
*
* \param ptr pointer where option will be writed
* \param data Vendor Data
* \param dataLength Vendor Data length
*
* return incremented pointer after write
*/
uint8_t *libdhcvp6_vendor_specific_option_write(uint8_t *ptr, uint8_t *data, uint16_t dataLength);
/**
* This Function write dhcpv6 request option write
*
@ -379,6 +372,6 @@ int libdhcpv6_solication_message_options_validate(uint8_t *ptr, uint16_t data_le
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);
bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t *relay_msg);
#endif /* LIBDHCPV6_H_ */

View File

@ -58,6 +58,8 @@ static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void)
entry->removeCb = NULL;
entry->addCb = NULL;
ns_list_init(&entry->allocatedAddressList);
ns_list_init(&entry->dnsServerList);
ns_list_init(&entry->vendorDataList);
return entry;
}
@ -338,6 +340,20 @@ void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t
ns_list_remove(&serverInfo->allocatedAddressList, cur);
ns_dyn_mem_free(cur);
}
ns_list_foreach_safe(dhcpv6_dns_server_data_t, cur, &serverInfo->dnsServerList) {
//DNS Server Info Remove
ns_list_remove(&serverInfo->dnsServerList, cur);
ns_dyn_mem_free(cur->search_list);
ns_dyn_mem_free(cur);
}
ns_list_foreach_safe(dhcpv6_vendor_data_t, cur, &serverInfo->vendorDataList) {
ns_list_remove(&serverInfo->vendorDataList, cur);
ns_dyn_mem_free(cur->vendor_data);
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);
@ -494,5 +510,119 @@ dhcpv6_allocated_address_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_ser
return newEntry;
}
dhcpv6_dns_server_data_t *libdhcpv6_dns_server_discover(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address)
{
ns_list_foreach(dhcpv6_dns_server_data_t, cur, &serverInfo->dnsServerList) {
if (memcmp(cur->server_address, address, 16) == 0) {
return cur;
}
}
return NULL;
}
dhcpv6_dns_server_data_t *libdhcpv6_dns_server_allocate(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address)
{
dhcpv6_dns_server_data_t *entry = libdhcpv6_dns_server_discover(serverInfo, address);
if (entry) {
return entry;
}
entry = ns_dyn_mem_alloc(sizeof(dhcpv6_dns_server_data_t));
if (!entry) {
return NULL;
}
ns_list_add_to_end(&serverInfo->dnsServerList, entry);
memcpy(entry->server_address, address, 16);
entry->search_list = NULL;
entry->search_list_length = 0;
return entry;
}
dhcpv6_vendor_data_t *libdhcpv6_vendor_data_discover(dhcpv6_gua_server_entry_s *serverInfo, uint32_t enterprise_number)
{
ns_list_foreach(dhcpv6_vendor_data_t, cur, &serverInfo->vendorDataList) {
if (cur->enterprise_number == enterprise_number) {
return cur;
}
}
return NULL;
}
dhcpv6_vendor_data_t *libdhcpv6_vendor_data_allocate(dhcpv6_gua_server_entry_s *serverInfo, uint32_t enterprise_number)
{
dhcpv6_vendor_data_t *entry = libdhcpv6_vendor_data_discover(serverInfo, enterprise_number);
if (entry) {
return entry;
}
entry = ns_dyn_mem_alloc(sizeof(dhcpv6_vendor_data_t));
if (!entry) {
return NULL;
}
ns_list_add_to_end(&serverInfo->vendorDataList, entry);
entry->enterprise_number = enterprise_number;
entry->vendor_data = NULL;
entry->vendor_data_length = 0;
return entry;
}
uint16_t libdhcpv6_dns_server_message_sizes(dhcpv6_gua_server_entry_s *serverInfo)
{
uint16_t message_size = 0;
ns_list_foreach(dhcpv6_dns_server_data_t, cur, &serverInfo->dnsServerList) {
message_size += 4 + 16; //Type Length + address //
//Search List part
message_size += 4 + cur->search_list_length; //Type Length + search_list_length
}
return message_size;
}
uint16_t libdhcpv6_vendor_data_message_sizes(dhcpv6_gua_server_entry_s *serverInfo)
{
uint16_t message_size = 0;
ns_list_foreach(dhcpv6_vendor_data_t, cur, &serverInfo->vendorDataList) {
message_size += 4 + 4 + cur->vendor_data_length; //Type + Length + enterprise + vendor_data_length
}
return message_size;
}
uint8_t *libdhcpv6_dns_server_message_writes(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *ptr)
{
ns_list_foreach(dhcpv6_dns_server_data_t, cur, &serverInfo->dnsServerList) {
//Write first DNS Server info
ptr = common_write_16_bit(DHCPV6_OPTION_DNS_SERVERS, ptr);
ptr = common_write_16_bit(16, ptr); //Length
memcpy(ptr, cur->server_address, 16);
ptr += 16;
ptr = common_write_16_bit(DHCPV6_OPTION_DOMAIN_LIST, ptr);
ptr = common_write_16_bit(cur->search_list_length, ptr); //Length
if (cur->search_list_length) {
memcpy(ptr, cur->search_list, cur->search_list_length);
ptr += cur->search_list_length;
}
}
return ptr;
}
uint8_t *libdhcpv6_vendor_data_message_writes(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *ptr)
{
ns_list_foreach(dhcpv6_vendor_data_t, cur, &serverInfo->vendorDataList) {
uint16_t length = cur->vendor_data_length + 4;
ptr = common_write_16_bit(DHCPV6_OPTION_VENDOR_SPECIFIC_INFO, ptr);
ptr = common_write_16_bit(length, ptr); //Length
ptr = common_write_32_bit(cur->enterprise_number, ptr);
if (cur->vendor_data_length) {
memcpy(ptr, cur->vendor_data, cur->vendor_data_length);
ptr += cur->vendor_data_length;
}
}
return ptr;
}
#endif

View File

@ -45,6 +45,20 @@ typedef struct dhcpv6_allocated_address_entry_s {
ns_list_link_t link; /*!< List link entry */
} dhcpv6_allocated_address_entry_t;
typedef struct dhcpv6_dns_server_data_s {
uint8_t server_address[16];
uint8_t *search_list;
uint8_t search_list_length;
ns_list_link_t link; /*!< List link entry */
} dhcpv6_dns_server_data_t;
typedef struct dhcpv6_vendor_data_s {
uint32_t enterprise_number;
uint8_t *vendor_data;
uint8_t vendor_data_length;
ns_list_link_t link; /*!< List link entry */
} dhcpv6_vendor_data_t;
typedef struct dhcpv6_allocated_address_s {
uint8_t nonTemporalAddress[16];
@ -58,6 +72,8 @@ typedef struct dhcpv6_allocated_address_s {
} dhcpv6_allocated_address_t;
typedef NS_LIST_HEAD(dhcpv6_allocated_address_entry_t, link) dhcpv6_allocated_address_list_t;
typedef NS_LIST_HEAD(dhcpv6_dns_server_data_t, link) dhcpv6_dns_server_list_t;
typedef NS_LIST_HEAD(dhcpv6_vendor_data_t, link) dhcpv6_vendor_data_list_t;
typedef struct dhcp_address_cache_update {
uint8_t *allocatedAddress;
@ -84,6 +100,8 @@ typedef struct dhcpv6_gua_server_entry_s {
dhcp_address_prefer_remove_cb *removeCb;
dhcp_address_add_notify_cb *addCb;
dhcpv6_allocated_address_list_t allocatedAddressList;
dhcpv6_dns_server_list_t dnsServerList;
dhcpv6_vendor_data_list_t vendorDataList;
dhcpv6_allocated_address_t tempAddressEntry;
ns_list_link_t link; /*!< List link entry */
} dhcpv6_gua_server_entry_s;
@ -99,6 +117,14 @@ dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_interfaceid(i
dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_socketinstance(uint16_t socketInstance, uint8_t *prefixPtr);
dhcpv6_allocated_address_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *euid64, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew);
void libdhcpv6_allocated_address_write(uint8_t *ptr, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo);
dhcpv6_dns_server_data_t *libdhcpv6_dns_server_discover(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address);
dhcpv6_dns_server_data_t *libdhcpv6_dns_server_allocate(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address);
dhcpv6_vendor_data_t *libdhcpv6_vendor_data_discover(dhcpv6_gua_server_entry_s *serverInfo, uint32_t enterprise_number);
dhcpv6_vendor_data_t *libdhcpv6_vendor_data_allocate(dhcpv6_gua_server_entry_s *serverInfo, uint32_t enterprise_number);
uint16_t libdhcpv6_dns_server_message_sizes(dhcpv6_gua_server_entry_s *serverInfo);
uint16_t libdhcpv6_vendor_data_message_sizes(dhcpv6_gua_server_entry_s *serverInfo);
uint8_t *libdhcpv6_dns_server_message_writes(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *ptr);
uint8_t *libdhcpv6_vendor_data_message_writes(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *ptr);
#else
#define libdhcpv6_gua_server_list_empty() true
#define libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefixPtr) NULL

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2020, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include "ns_types.h"
#include "ns_trace.h"
#include <string.h>
#include "common_functions.h"
#include "libDHCPv6.h"
#include "libDHCPv6_vendordata.h"
#define TRACE_GROUP "vend"
/* DHCPv6 vendor options to distribute ARM vendor data*/
uint16_t net_dns_option_vendor_option_data_dns_query_length(char *domain)
{
return 4 + 16 + strlen(domain) + 1;
}
uint8_t *net_dns_option_vendor_option_data_dns_query_write(uint8_t *ptr, uint8_t *address, char *domain)
{
int domain_len = strlen(domain);
int length = 16 + domain_len + 1;
ptr = common_write_16_bit(ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT, ptr);
ptr = common_write_16_bit(length, ptr);
memcpy(ptr, address, 16);
ptr += 16;
memcpy(ptr, domain, domain_len + 1);
ptr += domain_len + 1;
return ptr;
}
uint16_t net_dns_option_vendor_option_data_get_next(uint8_t *ptr, uint16_t length, uint16_t *type)
{
uint16_t option_len;
if (length < 4) {
// Corrupted
return 0;
}
if (type) {
*type = common_read_16_bit(ptr);
}
option_len = common_read_16_bit(ptr + 2);
if (option_len + 4 > length) {
// Corrupted
return 0;
}
return option_len + 4;
}
uint16_t net_dns_option_vendor_option_data_dns_query_read(uint8_t *ptr, uint16_t length, uint8_t **address, char **domain)
{
uint16_t option_len;
option_len = common_read_16_bit(ptr + 2);
if (length < 4 + 16 + 1) {
// Corrupted as there is no room for all fields
return 0;
}
if (option_len < 17) {
// Corrupted as not enough room in field
return 0;
}
if (*(ptr + 4 + option_len - 1) != 0) {
// Not nul terminated string for domain
return 0;
}
if (common_read_16_bit(ptr) != ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT) {
return 0;
}
if (address) {
*address = ptr + 4;
}
if (domain) {
*domain = (char *)(ptr + 4 + 16);
}
return option_len;
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2020, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIBDHCPV6_VENDOR_DATA_H_
#define LIBDHCPV6_VENDOR_DATA_H_
/*ARM enterprise number used to identify ARM generated Vendor data options*/
#define ARM_ENTERPRISE_NUMBER 4128
/* ARM Defined vendor data option to distribute DNS query results through DHCP server
* Format
*
* uint8_t address[16]
* domain string nul terminated.
*
* multiple results must be in separated vendor option data fields
* */
#define ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT 297
/* DHCPv6 vendor options to distribute ARM vendor data*/
uint16_t net_dns_option_vendor_option_data_dns_query_length(char *domain);
uint8_t *net_dns_option_vendor_option_data_dns_query_write(uint8_t *ptr, uint8_t *address, char *domain);
uint16_t net_dns_option_vendor_option_data_get_next(uint8_t *ptr, uint16_t length, uint16_t *type);
uint16_t net_dns_option_vendor_option_data_dns_query_read(uint8_t *ptr, uint16_t length, uint8_t **address, char **domain);
#endif /* LIBDHCPV6_VENDOR_DATA_H_ */

View File

@ -0,0 +1,330 @@
/*
* Copyright (c) 2020, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nsconfig.h"
#include "ns_types.h"
#include "ns_trace.h"
#include <string.h>
#include "net_dns_internal.h"
#include "net_interface.h"
#include "NWK_INTERFACE/Include/protocol.h"
#include "nsdynmemLIB.h"
#include "ns_list.h"
#include "libNET/src/net_dns_internal.h"
#define TRACE_GROUP "Ndns"
typedef struct dns_server_info {
uint8_t address[16];
uint8_t dns_server_address[16];
uint32_t lifetime;
uint8_t *dns_search_list_ptr;
uint16_t dns_search_list_len;
int8_t interface_id;
ns_list_link_t link;
} dns_server_info_t;
static NS_LIST_DEFINE(dns_server_list, dns_server_info_t, link);
typedef struct dns_query {
uint8_t address[16];
char *domain_str;
uint32_t lifetime;
int8_t interface_id;
ns_list_link_t link;
} dns_query_t;
static NS_LIST_DEFINE(dns_query_list, dns_query_t, link);
static dns_server_info_t *dns_server_info_find(int8_t interface_id, const uint8_t address[16])
{
dns_server_info_t *this = NULL;
ns_list_foreach(dns_server_info_t, cur_ptr, &dns_server_list) {
if (interface_id != -1 && cur_ptr->interface_id != interface_id) {
continue;
}
if (address && memcmp(cur_ptr->address, address, 16) == 0) {
this = cur_ptr;
break;
}
}
return this;
}
static dns_server_info_t *dns_server_info_create(int8_t interface_id, const uint8_t address[16])
{
dns_server_info_t *this = ns_dyn_mem_alloc(sizeof(dns_server_info_t));
if (!this) {
return NULL;
}
memset(this, 0, sizeof(dns_server_info_t));
this->interface_id = interface_id;
memcpy(this->address, address, 16);
ns_list_add_to_start(&dns_server_list, this);
tr_debug("Create DNS entry for %s", trace_ipv6(address));
return this;
}
static void dns_server_info_delete(dns_server_info_t *this)
{
if (!this) {
return;
}
tr_debug("delete DNS entry for %s", trace_ipv6(this->address));
ns_list_remove(&dns_server_list, this);
ns_dyn_mem_free(this->dns_search_list_ptr);
ns_dyn_mem_free(this);
}
int8_t net_dns_server_address_set(int8_t interface_id, const uint8_t address[16], const uint8_t dns_server_address[16], uint32_t lifetime)
{
dns_server_info_t *info_ptr;
if (!address || interface_id < 0) {
return -1;
}
info_ptr = dns_server_info_find(interface_id, address);
if (!dns_server_address || lifetime == 0) {
// Delete the entry
dns_server_info_delete(info_ptr);
return 0;
}
if (!info_ptr) {
info_ptr = dns_server_info_create(interface_id, address);
}
info_ptr->lifetime = lifetime;
memcpy(info_ptr->dns_server_address, dns_server_address, 16);
tr_info("DNS Server: %s from: %s Lifetime: %lu", trace_ipv6(info_ptr->dns_server_address), trace_ipv6(info_ptr->address), (unsigned long) info_ptr->lifetime);
return 0;
}
int8_t net_dns_server_search_list_set(int8_t interface_id, const uint8_t address[16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len, uint32_t lifetime)
{
dns_server_info_t *info_ptr;
if (!address || interface_id < 0) {
return -1;
}
info_ptr = dns_server_info_find(interface_id, address);
if (info_ptr && (!dns_search_list_ptr || lifetime == 0)) {
// remove search list information
tr_debug("DNS Search List clear");
ns_dyn_mem_free(info_ptr->dns_search_list_ptr);
info_ptr->dns_search_list_ptr = NULL;
info_ptr->dns_search_list_len = 0;
return 0;
}
if (!info_ptr) {
info_ptr = dns_server_info_create(interface_id, address);
if (!info_ptr) {
return -1;
}
info_ptr->lifetime = lifetime;
}
if (info_ptr->dns_search_list_ptr && info_ptr->dns_search_list_len != dns_search_list_len) {
ns_dyn_mem_free(info_ptr->dns_search_list_ptr);
info_ptr->dns_search_list_ptr = NULL;
}
if (!info_ptr->dns_search_list_ptr) {
info_ptr->dns_search_list_ptr = ns_dyn_mem_alloc(dns_search_list_len);
}
if (!info_ptr->dns_search_list_ptr) {
return -2;
}
memcpy(info_ptr->dns_search_list_ptr, dns_search_list_ptr, dns_search_list_len);
info_ptr->dns_search_list_len = dns_search_list_len;
tr_info("DNS Search List: %s Lifetime: %lu", trace_array(info_ptr->dns_search_list_ptr, info_ptr->dns_search_list_len), (unsigned long) info_ptr->lifetime);
return 0;
}
int8_t net_dns_server_get(int8_t interface_id, uint8_t dns_server_address[16], uint8_t **dns_search_list_ptr, uint8_t *dns_search_list_len, uint8_t index)
{
dns_server_info_t *info_ptr = NULL;
uint8_t n = 0;
ns_list_foreach(dns_server_info_t, cur_ptr, &dns_server_list) {
if (interface_id != -1 && cur_ptr->interface_id != interface_id) {
continue;
}
if (index == n) {
info_ptr = cur_ptr;
break;
}
n++;
}
if (!info_ptr) {
return -1;
}
if (dns_server_address) {
memcpy(dns_server_address, info_ptr->dns_server_address, 16);
}
if (dns_search_list_ptr) {
*dns_search_list_ptr = info_ptr->dns_search_list_ptr;
}
if (dns_search_list_len) {
*dns_search_list_len = info_ptr->dns_search_list_len;
}
return 0;
}
/**
* Storage for DNS query results
*/
static dns_query_t *dns_query_result_find(int8_t interface_id, const char *domain_str)
{
dns_query_t *this = NULL;
ns_list_foreach(dns_query_t, cur_ptr, &dns_query_list) {
if (interface_id != -1 && cur_ptr->interface_id != interface_id) {
continue;
}
if (strcasecmp(cur_ptr->domain_str, domain_str) == 0) {
this = cur_ptr;
break;
}
}
return this;
}
static dns_query_t *dns_query_result_create(int8_t interface_id, const char *domain_str)
{
dns_query_t *this = NULL;
if (!domain_str) {
return NULL;
}
this = ns_dyn_mem_alloc(sizeof(dns_query_t));
if (!this) {
return NULL;
}
memset(this, 0, sizeof(dns_query_t));
this->domain_str = ns_dyn_mem_alloc(strlen(domain_str) + 1);
if (!this->domain_str) {
ns_dyn_mem_free(this);
return NULL;
}
this->interface_id = interface_id;
strcpy(this->domain_str, domain_str);
//tr_debug("Create DNS query entry for %s", this->domain_str);
ns_list_add_to_start(&dns_query_list, this);
return this;
}
static void dns_query_result_delete(dns_query_t *this)
{
if (!this) {
return;
}
tr_debug("Delete DNS query entry for %s", this->domain_str);
ns_list_remove(&dns_query_list, this);
ns_dyn_mem_free(this->domain_str);
ns_dyn_mem_free(this);
}
int8_t net_dns_query_result_set(int8_t interface_id, const uint8_t address[16], const char *domain_name_ptr, uint32_t lifetime)
{
dns_query_t *this;
if (!domain_name_ptr || interface_id < 0) {
return -1;
}
this = dns_query_result_find(interface_id, domain_name_ptr);
if (!address || lifetime == 0) {
// Delete the entry
dns_query_result_delete(this);
return 0;
}
if (!this) {
this = dns_query_result_create(interface_id, domain_name_ptr);
}
if (!this) {
return -2;
}
// update address and lifetime also to old query results
memcpy(this->address, address, 16);
this->lifetime = lifetime;
tr_info("DNS query set: %s address %s Lifetime: %lu", this->domain_str, trace_ipv6(this->address), (unsigned long) this->lifetime);
return 0;
}
int8_t net_dns_query_result_get(int8_t interface_id, uint8_t address[16], const char *domain_name_ptr)
{
dns_query_t *this;
if (!domain_name_ptr) {
return -1;
}
this = dns_query_result_find(interface_id, domain_name_ptr);
if (!this) {
return -1;
}
if (address) {
memcpy(address, this->address, 16);
}
return 0;
}
/**
* Generic timeout handler for all interfaces and entries.
*/
void net_dns_timer_seconds(uint32_t seconds)
{
ns_list_foreach_safe(dns_query_t, cur_ptr, &dns_query_list) {
if (cur_ptr->lifetime == 0xffffffff) {
continue;
}
if (cur_ptr->lifetime <= seconds) {
dns_query_result_delete(cur_ptr);
continue;
}
cur_ptr->lifetime -= seconds;
}
ns_list_foreach_safe(dns_server_info_t, cur_ptr, &dns_server_list) {
if (cur_ptr->lifetime == 0xffffffff) {
continue;
}
if (cur_ptr->lifetime <= seconds) {
dns_server_info_delete(cur_ptr);
continue;
}
cur_ptr->lifetime -= seconds;
}
return;
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2020, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NET_DNS_INTERNAL_H_
#define NET_DNS_INTERNAL_H_
/**
* These functions are used to store DNS server related information
* IF DNS information is learned from IPv6 Router advertisements
* or from the DHCPv6 elements
*
* Address is the link local address of the default router or DHCPv6 server address
*/
int8_t net_dns_server_address_set(int8_t interface_id, const uint8_t address[16], const uint8_t dns_server_address[16], uint32_t lifetime);
int8_t net_dns_server_search_list_set(int8_t interface_id, const uint8_t address[16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len, uint32_t lifetime);
int8_t net_dns_server_get(int8_t interface_id, uint8_t dns_server_address[16], uint8_t **dns_search_list_ptr, uint8_t *dns_search_list_len, uint8_t index);
/**
* Storage for DNS query results
*/
int8_t net_dns_query_result_set(int8_t interface_id, const uint8_t address[16], const char *domain_name_ptr, uint32_t lifetime);
int8_t net_dns_query_result_get(int8_t interface_id, uint8_t address[16], const char *domain_name_ptr);
/**
* Generic timeout handler for all interfaces and entries.
*/
void net_dns_timer_seconds(uint32_t seconds);
#endif /* NET_DNS_INTERNAL_H_ */

View File

@ -61,6 +61,7 @@
#include "Security/Common/sec_lib_definitions.h"
#include "ipv6_stack/protocol_ipv6.h"
#include "ipv6_stack/ipv6_routing_table.h"
#include "libNET/src/net_dns_internal.h"
#include "net_thread_test.h"
#include "6LoWPAN/Thread/thread_common.h"
#include "6LoWPAN/Thread/thread_routing.h"
@ -656,6 +657,24 @@ int8_t arm_net_address_delete_from_interface(int8_t interface_id, const uint8_t
return addr_delete(cur, address);
}
/* DNS cache functions
*/
int8_t arm_net_dns_server_get(int8_t interface_id, uint8_t address[16], uint8_t **dns_search_list_ptr, uint8_t *dns_search_list_len, uint8_t index)
{
return net_dns_server_get(interface_id, address, dns_search_list_ptr, dns_search_list_len, index);
}
int8_t arm_net_dns_query_result_set(int8_t interface_id, const uint8_t address[16], const char *domain_name_ptr, uint32_t lifetime)
{
return net_dns_query_result_set(interface_id, address, domain_name_ptr, lifetime);
}
int8_t arm_net_dns_query_result_get(int8_t interface_id, uint8_t address[16], char *domain_name_ptr)
{
return net_dns_query_result_get(interface_id, address, domain_name_ptr);
}
int8_t arm_net_route_add(const uint8_t *prefix, uint8_t prefix_len, const uint8_t *next_hop, uint32_t lifetime, uint8_t metric, int8_t interface_id)
{
ipv6_route_t *entry;
@ -682,7 +701,6 @@ int8_t arm_net_route_delete(const uint8_t *prefix, uint8_t prefix_len, const uin
return ipv6_route_delete(prefix, prefix_len, interface_id, next_hop, ROUTE_USER);
}
int8_t arm_nwk_interface_ethernet_init(eth_mac_api_t *api, const char *interface_name_ptr)
{
#ifdef HAVE_ETHERNET

View File

@ -67,6 +67,7 @@ SRCS += \
source/libNET/src/net_mle.c \
source/libNET/src/net_rpl.c \
source/libNET/src/net_load_balance.c \
source/libNET/src/net_dns.c \
source/libNET/src/ns_net.c \
source/libNET/src/socket_api.c \
source/libNET/src/multicast_api.c \
@ -204,6 +205,7 @@ SRCS += \
source/DHCPv6_client/dhcpv6_client_service.c \
source/libDHCPv6/dhcp_service_api.c \
source/libDHCPv6/libDHCPv6.c \
source/libDHCPv6/libDHCPv6_vendordata.c \
source/libDHCPv6/libDHCPv6_server.c \
source/Service_Libs/utils/ns_crc.c \
source/Service_Libs/utils/isqrt.c \