mirror of https://github.com/ARMmbed/mbed-os.git
Merge commit '9a4e8a5964c54f2a983ffd4c13755176d4f9df52'
* commit '9a4e8a5964c54f2a983ffd4c13755176d4f9df52': Squashed 'connectivity/nanostack/sal-stack-nanostack/' changes from 48609aeded..d879e6db87pull/13562/head
commit
b25f05b035
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout;
|
||||
//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)) {
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
llc_neighbour_req_t neighbor_info;
|
||||
neighbor_info.ws_neighbor = NULL;
|
||||
neighbor_info.neighbor = NULL;
|
||||
if (message->ack_requested && messsage_type == WS_FT_DATA) {
|
||||
llc_neighbour_req_t neighbor_info;
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
return -1;
|
||||
}
|
||||
memset(pae_controller_radius_settings, 0, sizeof(sec_radius_cfg_t));
|
||||
if (ws_pae_controller_configure(controller->interface_ptr, NULL, NULL) < 0) {
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
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);
|
||||
}
|
||||
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 && 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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -71,17 +72,19 @@ typedef struct {
|
|||
typedef NS_LIST_HEAD(kmp_msg_if_entry_t, link) kmp_msg_if_list_t;
|
||||
|
||||
struct kmp_service_s {
|
||||
kmp_sec_prot_list_t sec_prot_list; /**< Security protocols list */
|
||||
kmp_msg_if_list_t msg_if_list; /**< Message interface list */
|
||||
kmp_service_incoming_ind *incoming_ind; /**< Callback to application to indicate incoming KMP frame */
|
||||
kmp_service_tx_status_ind *tx_status_ind; /**< Callback to application to indicate TX status */
|
||||
kmp_service_addr_get *addr_get; /**< Callback to get addresses related to KMP */
|
||||
kmp_service_ip_addr_get *ip_addr_get; /**< Callback to get IP addresses related to KMP */
|
||||
kmp_service_api_get *api_get; /**< Callback to get KMP API from a service */
|
||||
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 */
|
||||
ns_list_link_t link; /**< Link */
|
||||
kmp_sec_prot_list_t sec_prot_list; /**< Security protocols list */
|
||||
kmp_msg_if_list_t msg_if_list; /**< Message interface list */
|
||||
kmp_service_incoming_ind *incoming_ind; /**< Callback to application to indicate incoming KMP frame */
|
||||
kmp_service_tx_status_ind *tx_status_ind; /**< Callback to application to indicate TX status */
|
||||
kmp_service_addr_get *addr_get; /**< Callback to get addresses related to KMP */
|
||||
kmp_service_ip_addr_get *ip_addr_get; /**< Callback to get IP addresses related to KMP */
|
||||
kmp_service_api_get *api_get; /**< Callback to get KMP API from a service */
|
||||
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 */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,19 +39,20 @@
|
|||
|
||||
#define TRACE_GROUP "kmsi"
|
||||
|
||||
#define SOCKET_IF_HEADER_SIZE 27
|
||||
#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,14 +108,19 @@ 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);
|
||||
}
|
||||
socket_if->socket_id = socket_open(IPV6_NH_UDP, local_port, &kmp_socket_if_socket_cb);
|
||||
if (socket_if->socket_id < 0) {
|
||||
ns_dyn_mem_free(socket_if);
|
||||
return -1;
|
||||
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_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +129,12 @@ int8_t kmp_socket_if_register(kmp_service_t *service, uint8_t *instance_id, bool
|
|||
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,11 +237,15 @@ 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) {
|
||||
socket_if = entry;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -65,20 +65,23 @@ 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) */
|
||||
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 */
|
||||
uint8_t eap_id_seq; /**< EAP sequence */
|
||||
uint8_t recv_eap_id_seq; /**< Last received EAP sequence */
|
||||
uint8_t eap_code; /**< Received EAP code */
|
||||
uint8_t eap_type; /**< Received EAP type */
|
||||
uint8_t init_key_cnt; /**< How many time initial EAPOL-key has been received */
|
||||
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 */
|
||||
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 */
|
||||
uint8_t eap_id_seq; /**< EAP sequence */
|
||||
uint8_t recv_eap_id_seq; /**< Last received EAP sequence */
|
||||
uint8_t eap_code; /**< Received EAP code */
|
||||
uint8_t eap_type; /**< Received EAP type */
|
||||
uint8_t init_key_cnt; /**< How many time initial EAPOL-key has been received */
|
||||
} radius_eap_tls_sec_prot_int_t;
|
||||
|
||||
static uint16_t radius_eap_tls_sec_prot_size(void);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
data->radius_eap_tls_send(data->radius_eap_tls_prot, (void *) data->recv_eap_msg, data->recv_eap_msg_len);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_ */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_ */
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
Loading…
Reference in New Issue