mirror of https://github.com/ARMmbed/mbed-os.git
1612 lines
49 KiB
C
1612 lines
49 KiB
C
/*
|
|
* Copyright (c) 2014-2021, Pelion 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.
|
|
*/
|
|
/**
|
|
* \file net.c
|
|
* \brief Network API for library model
|
|
*
|
|
* The network API functions for library model
|
|
*/
|
|
#include "nsconfig.h"
|
|
#include "ns_types.h"
|
|
#include "eventOS_scheduler.h"
|
|
#include "string.h"
|
|
#include "ns_trace.h"
|
|
#include "socket_api.h"
|
|
#include "nsdynmemLIB.h"
|
|
#include "NWK_INTERFACE/Include/protocol.h"
|
|
#include "Core/include/ns_socket.h"
|
|
#ifdef HAVE_RPL
|
|
#include "RPL/rpl_of0.h"
|
|
#include "RPL/rpl_mrhof.h"
|
|
#include "RPL/rpl_control.h"
|
|
#include "RPL/rpl_data.h"
|
|
#endif
|
|
#include "ccmLIB.h"
|
|
#include "6LoWPAN/lowpan_adaptation_interface.h"
|
|
#include "6LoWPAN/Bootstraps/network_lib.h"
|
|
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
|
|
#include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
|
|
#include "6LoWPAN/ND/nd_router_object.h"
|
|
#include "6LoWPAN/MAC/mac_helper.h"
|
|
#include "6LoWPAN/MAC/beacon_handler.h"
|
|
#ifndef NO_MLE
|
|
#include "MLE/mle.h"
|
|
#endif
|
|
#include "platform/arm_hal_interrupt.h"
|
|
#include "common_functions.h"
|
|
#include "Service_Libs/whiteboard/whiteboard.h"
|
|
#include "net_pana_parameters_api.h"
|
|
#ifdef ECC
|
|
#include "libX509_V3.h"
|
|
#include "ecc.h"
|
|
#endif
|
|
#include "Security/PANA/pana.h"
|
|
#include "Security/PANA/pana_internal_api.h"
|
|
#include "nwk_stats_api.h"
|
|
#include "NWK_INTERFACE/Include/protocol_stats.h"
|
|
#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"
|
|
#include "6LoWPAN/Thread/thread_bootstrap.h"
|
|
#include "6LoWPAN/Thread/thread_management_internal.h"
|
|
#include "6LoWPAN/ws/ws_common.h"
|
|
#ifdef HAVE_WS
|
|
#include "6LoWPAN/ws/ws_pae_controller.h"
|
|
#endif
|
|
#include "BorderRouter/border_router.h"
|
|
#include "Service_Libs/mle_service/mle_service_api.h"
|
|
#include "6LoWPAN/MAC/mac_data_poll.h"
|
|
#include "sw_mac.h"
|
|
#include "mac_api.h"
|
|
#include "ethernet_mac_api.h"
|
|
#include <stdarg.h>
|
|
|
|
|
|
#define TRACE_GROUP "lNet"
|
|
/**
|
|
* \brief A function checks that the channel list is not empty. Channel pages 9 and 10 can have eight 32-bit channel masks.
|
|
* \param scan_list is a pointer to the channel list structure given by the application.
|
|
* \return 0 on success.
|
|
* \return -1 if channel list is empty.
|
|
*/
|
|
static int arm_channel_list_validation(const channel_list_s *scan_list)
|
|
{
|
|
uint8_t i = 1;
|
|
if (scan_list) {
|
|
if (scan_list->channel_page == CHANNEL_PAGE_9 || scan_list->channel_page == CHANNEL_PAGE_10) {
|
|
i = 8;
|
|
}
|
|
while (i--)
|
|
if (scan_list->channel_mask[i]) {
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
/* Energy & Active Scan API */
|
|
int8_t arm_net_energy_scan(int8_t interface_id, channel_list_s *scan_list, void (*passed_fptr)(int8_t if_id, const mlme_scan_conf_t *conf), uint8_t energy_tresshold)
|
|
{
|
|
(void)interface_id;
|
|
(void)scan_list;
|
|
(void)passed_fptr;
|
|
(void)energy_tresshold;
|
|
int8_t ret_val = -3;
|
|
#ifdef HAVE_RF_TUNNEL
|
|
(void)interface_id;
|
|
(void)scan_list;
|
|
(void)passed_fptr;
|
|
(void)energy_tresshold;
|
|
#else
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
|
ret_val = -1;
|
|
} else {
|
|
|
|
nwk_scan_params_t *scan_params = 0;
|
|
if (cur->mac_parameters) {
|
|
scan_params = &cur->mac_parameters->nwk_scan_params;
|
|
scan_params->stack_chan_list = *scan_list;
|
|
scan_params->energy_treshold = energy_tresshold;
|
|
|
|
mlme_scan_t req;
|
|
mac_create_scan_request(MAC_ED_SCAN_TYPE, &cur->mac_parameters->nwk_scan_params.stack_chan_list, 5, &req);
|
|
if (cur->mac_api) {
|
|
cur->scan_cb = passed_fptr;
|
|
cur->mac_api->mlme_req(cur->mac_api, MLME_SCAN, &req);
|
|
ret_val = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
int8_t arm_net_nwk_scan(int8_t interface_id, channel_list_s *scan_list, void (*passed_fptr)(int8_t if_id, const mlme_scan_conf_t *conf), uint8_t scan_level)
|
|
{
|
|
(void)interface_id;
|
|
(void)scan_list;
|
|
(void)passed_fptr;
|
|
(void)scan_level;
|
|
int8_t ret_val = -3;
|
|
#ifdef HAVE_RF_TUNNEL
|
|
(void)interface_id;
|
|
(void)scan_list;
|
|
(void)passed_fptr;
|
|
(void)scan_level;
|
|
#else
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
|
|
if (cur) {
|
|
cur->scan_cb = passed_fptr;
|
|
if (cur->mac_parameters) {
|
|
nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
|
ret_val = -1;
|
|
} else if (arm_channel_list_validation(scan_list)) {
|
|
tr_debug("Given channel mask is empty!");
|
|
ret_val = -2;
|
|
} else {
|
|
nwk_scan_params_t *scan_params = &cur->mac_parameters->nwk_scan_params;
|
|
scan_params->stack_chan_list = *scan_list;
|
|
|
|
mlme_scan_t req;
|
|
mac_create_scan_request(MAC_ACTIVE_SCAN, &scan_params->stack_chan_list, 5, &req);
|
|
if (cur->mac_api) {
|
|
cur->scan_cb = passed_fptr;
|
|
scan_params->active_scan_active = true;
|
|
cur->mac_api->mlme_req(cur->mac_api, MLME_SCAN, &req);
|
|
}
|
|
filter->nwk_active_scan_level = scan_level;
|
|
mac_helper_nwk_id_filter_set(0, filter);
|
|
mac_helper_mac16_address_set(cur, 0xffff);
|
|
protocol_6lowpan_register_handlers(cur);
|
|
ret_val = 0;
|
|
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return ret_val;
|
|
}
|
|
|
|
nwk_pan_descriptor_t *arm_net_get_scanned_nwk_list(int8_t interface_id)
|
|
{
|
|
nwk_pan_descriptor_t *ret_val = 0;
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
if (cur->mac_parameters) {
|
|
ret_val = cur->mac_parameters->nwk_scan_params.nwk_response_info;
|
|
}
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
/**
|
|
* \brief A function to read pan ID filter.
|
|
* \return 16-bit value indicating a pan ID filter.
|
|
*/
|
|
uint16_t arm_net_get_nwk_pan_id_filter(int8_t interface_id)
|
|
{
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
if (cur->mac_parameters) {
|
|
nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
|
|
return filter->net_pan_id_filter;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief A function to read network layer configurations.
|
|
* \param network_params is a pointer to the structure to where the network layer configs are written to.
|
|
* \return 0 on success.
|
|
* \return Negative value if interface id or PAN coordinator is not known.
|
|
*/
|
|
int8_t arm_nwk_param_read(int8_t interface_id, link_layer_setups_s *network_params)
|
|
{
|
|
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
addrtype_t addrType = mac_helper_coordinator_address_get(cur, network_params->address);
|
|
if (addrType == ADDR_NONE) {
|
|
return -2;
|
|
}
|
|
network_params->PANId = mac_helper_panid_get(cur);
|
|
if (addrType == ADDR_802_15_4_SHORT) {
|
|
network_params->addr_mode = ADDR_MAC_SHORT16;
|
|
} else {
|
|
network_params->addr_mode = ADDR_MAC_LONG64;
|
|
}
|
|
|
|
network_params->LogicalChannel = cur->mac_parameters->mac_channel;
|
|
network_params->sf = 0xff;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief A function to read MAC PAN-ID, Short address & EUID64
|
|
* \param mac_params is a pointer to the structure to where the mac address are written to.
|
|
* \return 0 on success.
|
|
* \return Negative value if interface id is not known.
|
|
*/
|
|
int8_t arm_nwk_mac_address_read(int8_t interface_id, link_layer_address_s *mac_params)
|
|
{
|
|
int8_t ret_val = -2;
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
ret_val = 0;
|
|
memcpy(mac_params->mac_long, cur->mac, 8);
|
|
memcpy(mac_params->iid_eui64, cur->iid_eui64, 8);
|
|
if (cur->mac_parameters) {
|
|
mac_params->PANId = cur->mac_parameters->pan_id;
|
|
mac_params->mac_short = cur->mac_parameters->mac_short_address;
|
|
} else {
|
|
mac_params->PANId = 0xffff;
|
|
mac_params->mac_short = 0xffff;
|
|
}
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
/**
|
|
* \brief A function to read 6LoWPAN ND border router address and NWK prefix
|
|
* \param mac_params is a pointer to the structure to where the mac address are written to.
|
|
* \return 0 on success.
|
|
* \return -1 .
|
|
*/
|
|
int8_t arm_nwk_nd_address_read(int8_t interface_id, network_layer_address_s *nd_addr_info)
|
|
{
|
|
(void)interface_id;
|
|
(void)nd_addr_info;
|
|
int8_t ret_val = -2;
|
|
#ifdef HAVE_6LOWPAN_ND
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
if ((cur->lowpan_info & (INTERFACE_NWK_ACTIVE | INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) == (INTERFACE_NWK_ACTIVE | INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY)) {
|
|
uint8_t *adr_ptr = protocol_6lowpan_nd_border_router_address_get(cur->nwk_id);
|
|
if (adr_ptr) {
|
|
ret_val = 0;
|
|
memcpy(nd_addr_info->border_router, adr_ptr, 16);
|
|
memcpy(nd_addr_info->prefix, adr_ptr, 8);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
(void)interface_id;
|
|
(void)nd_addr_info;
|
|
#endif
|
|
return ret_val;
|
|
}
|
|
|
|
/**
|
|
* \brief Get current used channel.
|
|
*
|
|
* \return Active channel
|
|
* \return -1 if invalid network interface ID is given
|
|
*/
|
|
int16_t arm_net_get_current_channel(int8_t interface_id)
|
|
{
|
|
int16_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
|
ret_val = cur->mac_parameters->mac_channel;
|
|
}
|
|
}
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
/**
|
|
* \brief A function to set sleep mode of a host.
|
|
* \param state equals to 1 if the sleep mode is to be enabled, 0 if the sleep mode is to be disabled.
|
|
*/
|
|
void arm_net_host_enter_sleep_state_set(int8_t interface_id, uint8_t state)
|
|
{
|
|
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur && cur->rfd_poll_info) {
|
|
|
|
if (state) {
|
|
cur->rfd_poll_info->macDeepSleepEnabled = true;
|
|
} else {
|
|
cur->rfd_poll_info->macDeepSleepEnabled = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief A function to read library version information.
|
|
* \param ptr is a pointer to an array to where the version information is read to.
|
|
*/
|
|
void net_get_version_information(uint8_t *ptr)
|
|
{
|
|
(void)ptr;
|
|
}
|
|
|
|
/**
|
|
* \brief Set configured network interface Global address mode (Border router bootstrap mode can't set this).
|
|
*
|
|
* \param interface_id Network interface ID
|
|
* \param mode efine 6LoWPAN Global Address register mode::
|
|
* * NET_6LOWPAN_GP64_ADDRESS, Interface register only GP64
|
|
* * NET_6LOWPAN_GP16_ADDRESS, Interface register only GP16
|
|
* * NET_6LOWPAN_MULTI_GP_ADDRESS, Interface register GP16 and GP64 addresses. GP16 is primary address and GP64 is secondary.
|
|
*
|
|
* \param short_address_base Short address base. If application defines value 0-0xfffd 6LoWPAN try to register GP16 address using that address. 0xfffe and 0xffff will generate random 16-bit short address.
|
|
*
|
|
* \param define_new_short_address_at_DAD This parameter is only checked when mode is not NET_6LOWPAN_GP64_ADDRESS and short_address_base is 0-0xfffd. Recommend value is 1 that will enable automatic new address definition at Duplicate Address Detection(DAD). Value 0 will generate Duplicate Adreress Detection error for interface bootstrap.
|
|
Border Router Device will not check that part.
|
|
*
|
|
* \return >=0 Bootstrap mode set OK.
|
|
* \return -1 Unknown network ID.
|
|
* \return -2 Illegal for Border Router
|
|
* \return -3 Bootsrap not defined yet.
|
|
*/
|
|
int8_t arm_nwk_6lowpan_gp_address_mode(int8_t interface_id, net_6lowpan_gp_address_mode_e mode, uint16_t short_address_base, uint8_t define_new_short_address_at_DAD)
|
|
{
|
|
#ifdef HAVE_6LOWPAN_ND
|
|
protocol_interface_info_entry_t *cur;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur) {
|
|
return -1;
|
|
}
|
|
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
|
return -2;
|
|
}
|
|
if (!(cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED)) {
|
|
return -3;
|
|
}
|
|
|
|
if (thread_info(cur)) {
|
|
return -2;
|
|
}
|
|
|
|
if (short_address_base < 0xfffe) {
|
|
cur->lowpan_desired_short_address = short_address_base;
|
|
} else {
|
|
protocol_6lowpan_allocate_mac16(cur); //Allocate Random init value
|
|
}
|
|
cur->reallocate_short_address_if_duplicate = define_new_short_address_at_DAD;
|
|
cur->lowpan_address_mode = mode;
|
|
|
|
return 0;
|
|
#else
|
|
(void) interface_id;
|
|
(void) mode;
|
|
(void) short_address_base;
|
|
(void) define_new_short_address_at_DAD;
|
|
return -2;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* \brief A function to read networking address informations.
|
|
* \param addr_id identifies the address information type to be read.
|
|
* \param address is a pointer to a buffer to where the address information is written to.
|
|
* \return zero on success, -1 on errors.
|
|
*/
|
|
int8_t arm_net_address_get(int8_t interface_id, net_address_t addr_id, uint8_t *address)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur;
|
|
const uint8_t *addr;
|
|
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur) {
|
|
return -1;
|
|
}
|
|
|
|
if (!cur->global_address_available && addr_id != ADDR_IPV6_LL) {
|
|
//Should also check Check Bootstrap state
|
|
return -1;
|
|
}
|
|
|
|
switch (addr_id) {
|
|
case ADDR_IPV6_LL:
|
|
ret_val = addr_interface_get_ll_address(cur, address, 0);
|
|
break;
|
|
|
|
case ADDR_IPV6_GP:
|
|
addr = addr_select_with_prefix(cur, NULL, 0, SOCKET_IPV6_PREFER_SRC_PUBLIC | SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT);
|
|
if (addr) {
|
|
memcpy(address, addr, 16);
|
|
ret_val = 0;
|
|
}
|
|
break;
|
|
|
|
case ADDR_IPV6_GP_SEC:
|
|
addr = addr_select_with_prefix(cur, NULL, 0, SOCKET_IPV6_PREFER_SRC_PUBLIC | SOCKET_IPV6_PREFER_SRC_6LOWPAN_LONG);
|
|
/* Return if the "prefer long" gives a different answer to the default "prefer short". Pointer comparison is
|
|
* sufficient as addr_select returns a pointer into the address list. */
|
|
if (addr && addr != addr_select_with_prefix(cur, NULL, 0, SOCKET_IPV6_PREFER_SRC_PUBLIC | SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT)) {
|
|
memcpy(address, addr, 16);
|
|
ret_val = 0;
|
|
}
|
|
break;
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
/**
|
|
* \brief A function to read network Interface address count.
|
|
* \param interface_id Id to interface.
|
|
* \param address_count Pointer where address count will be saved.
|
|
* \return zero on success, -1 on errors.
|
|
*/
|
|
int8_t arm_net_interface_address_list_size(int8_t interface_id, uint16_t *address_count)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur;
|
|
*address_count = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
ns_list_foreach(if_address_entry_t, addr, &cur->ip_addresses) {
|
|
if (!addr->tentative) {
|
|
(*address_count)++;
|
|
}
|
|
}
|
|
|
|
ret_val = 0;
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
/**
|
|
* \brief A function to set interface metric.
|
|
* \param interface_id Network interface ID.
|
|
* \param metric Used to rank otherwise-equivalent routes. Lower is preferred and default is 0. The metric value is added to metric provided by the arm_net_route_add() function.
|
|
* \return 0 On success, -1 on errors.
|
|
*/
|
|
int8_t arm_net_interface_set_metric(int8_t interface_id, uint16_t metric)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
|
|
if (cur) {
|
|
cur->ipv6_neighbour_cache.route_if_info.metric = metric;
|
|
ret_val = 0;
|
|
}
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
/**
|
|
* \brief A function to read the interface metric value on an interface.
|
|
* \param interface_id Network interface ID.
|
|
* \param metric A pointer to the variable where the interface metric value is saved.
|
|
* \return 0 On success, -1 on errors.
|
|
*/
|
|
int8_t arm_net_interface_get_metric(int8_t interface_id, uint16_t *metric)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
|
|
if (cur) {
|
|
*metric = cur->ipv6_neighbour_cache.route_if_info.metric;
|
|
ret_val = 0;
|
|
}
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
/**
|
|
* \brief A function to read network Interface.
|
|
* \param interface_id Id to interface.
|
|
* \param address_buf_size Indicate buffer size in bytes minimal is 16 bytes.
|
|
* \param address_buffer pointer where stack save address one by one.
|
|
* \param writed_address_count pointer where stack save how many address is writed behind address_buffer.
|
|
*
|
|
* \return zero on success, -1 on errors.
|
|
*/
|
|
int8_t arm_net_address_list_get(int8_t interface_id, uint8_t address_buf_size, uint8_t *address_buffer, int *writed_address_count)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur;
|
|
int address_count = 0;
|
|
|
|
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur) {
|
|
return -1;
|
|
}
|
|
|
|
if (address_buf_size >= 16) {
|
|
int loop_counter = 0;
|
|
bool save_address;
|
|
while (loop_counter < 2) {
|
|
ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
|
|
if (e->tentative) {
|
|
continue;
|
|
}
|
|
|
|
save_address = false;
|
|
if (loop_counter) {
|
|
if (!addr_is_ipv6_link_local(e->address)) {
|
|
save_address = true;
|
|
}
|
|
} else {
|
|
if (addr_is_ipv6_link_local(e->address)) {
|
|
save_address = true;
|
|
}
|
|
}
|
|
if (save_address) {
|
|
memcpy(address_buffer, e->address, 16);
|
|
address_buf_size -= 16;
|
|
ret_val = 0;
|
|
address_count++;
|
|
if (address_buf_size >= 16) {
|
|
address_buffer += 16;
|
|
} else {
|
|
*writed_address_count = address_count;
|
|
return ret_val;
|
|
}
|
|
}
|
|
}
|
|
loop_counter++;
|
|
}
|
|
//Save writed address count to Pointer
|
|
*writed_address_count = address_count;
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
int8_t arm_net_address_list_get_next(int8_t interface_id, int *n, uint8_t address_buffer[16])
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur;
|
|
int address_count = 0;
|
|
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur) {
|
|
return -1;
|
|
}
|
|
|
|
int loop_counter = 0;
|
|
bool save_address;
|
|
while (loop_counter < 2) {
|
|
ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
|
|
if (e->tentative) {
|
|
continue;
|
|
}
|
|
|
|
save_address = false;
|
|
if (loop_counter) {
|
|
if (!addr_is_ipv6_link_local(e->address)) {
|
|
save_address = true;
|
|
}
|
|
} else {
|
|
if (addr_is_ipv6_link_local(e->address)) {
|
|
save_address = true;
|
|
}
|
|
}
|
|
if (save_address) {
|
|
if (*n == address_count) {
|
|
memcpy(address_buffer, e->address, 16);
|
|
*n = *n + 1;
|
|
return 0;
|
|
}
|
|
address_count++;
|
|
}
|
|
}
|
|
loop_counter++;
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
int8_t arm_net_address_add_to_interface(int8_t interface_id, const uint8_t address[16], uint8_t prefix_len, uint32_t valid_lifetime, uint32_t preferred_lifetime)
|
|
{
|
|
protocol_interface_info_entry_t *cur;
|
|
if_address_entry_t *entry;
|
|
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
|
|
if (!cur) {
|
|
return -1;
|
|
}
|
|
|
|
entry = addr_add(cur, address, prefix_len, ADDR_SOURCE_STATIC, valid_lifetime, preferred_lifetime, false);
|
|
|
|
if (!entry) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t arm_net_address_delete_from_interface(int8_t interface_id, const uint8_t address[16])
|
|
{
|
|
protocol_interface_info_entry_t *cur;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
|
|
if (!cur) {
|
|
return -1;
|
|
}
|
|
|
|
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;
|
|
|
|
if (prefix_len > 128 || (prefix == NULL && prefix_len != 0)) {
|
|
return -2;
|
|
}
|
|
|
|
entry = ipv6_route_add_metric(prefix, prefix_len, interface_id, next_hop, ROUTE_USER, NULL, 0, lifetime, metric);
|
|
|
|
if (!entry) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t arm_net_route_delete(const uint8_t *prefix, uint8_t prefix_len, const uint8_t *next_hop, int8_t interface_id)
|
|
{
|
|
if (prefix_len > 128 || (prefix == NULL && prefix_len != 0)) {
|
|
return -2;
|
|
}
|
|
|
|
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
|
|
if (!api) {
|
|
return -1;
|
|
}
|
|
|
|
protocol_interface_info_entry_t *cur = protocol_stack_interface_generate_ethernet(api);
|
|
if (!cur) {
|
|
return -3;
|
|
}
|
|
|
|
cur->if_up = ipv6_interface_up;
|
|
cur->if_down = ipv6_interface_down;
|
|
cur->interface_name = interface_name_ptr;
|
|
return cur->id;
|
|
#else
|
|
(void)api;
|
|
(void)interface_name_ptr;
|
|
return -2;
|
|
#endif
|
|
}
|
|
|
|
extern int8_t arm_nwk_interface_ppp_init(struct eth_mac_api_s *api, const char *interface_name_ptr)
|
|
{
|
|
#ifdef HAVE_ETHERNET
|
|
if (!api) {
|
|
return -1;
|
|
}
|
|
|
|
protocol_interface_info_entry_t *cur = protocol_stack_interface_generate_ppp(api);
|
|
if (!cur) {
|
|
return -3;
|
|
}
|
|
|
|
cur->if_up = ipv6_interface_up;
|
|
cur->if_down = ipv6_interface_down;
|
|
cur->interface_name = interface_name_ptr;
|
|
return cur->id;
|
|
#else
|
|
(void)api;
|
|
(void)interface_name_ptr;
|
|
return -2;
|
|
#endif
|
|
}
|
|
|
|
int8_t arm_nwk_interface_lowpan_init(mac_api_t *api, char *interface_name_ptr)
|
|
{
|
|
if (!api) {
|
|
return -1;
|
|
}
|
|
|
|
protocol_interface_info_entry_t *cur = protocol_stack_interface_generate_lowpan(api);
|
|
if (!cur) {
|
|
return -3;
|
|
}
|
|
protocol_6lowpan_configure_core(cur);
|
|
cur->interface_name = interface_name_ptr;
|
|
return cur->id;
|
|
}
|
|
|
|
static int arm_net_channel_bit_mask_to_number(const uint32_t *channel_mask)
|
|
{
|
|
int i, j;
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
for (i = 0; i < 32; i++) {
|
|
if (channel_mask[j] & (1U << i)) {
|
|
break;
|
|
}
|
|
}
|
|
if (i < 32) {
|
|
break;
|
|
}
|
|
}
|
|
if (j > 7) {
|
|
return -1;
|
|
}
|
|
return i + (j * 32);
|
|
}
|
|
|
|
/**
|
|
* \brief Set network interface link layer parameters.
|
|
*
|
|
* \param interface_id Network interface ID
|
|
* \param tun_driver_id Driver id FOR PHY data IN & OUT
|
|
* \param channel define network link channel
|
|
* \param link_setup Link layer parameters for NET_6LOWPAN_NETWORK_DRIVER defines NetworkID, PAN-ID Short Address
|
|
*
|
|
|
|
* \return >=0 Config set OK.
|
|
* \return -1 Unknown network ID or tun driver.
|
|
* \return -2 Interface is active, Bootsrap mode not selected or is not NET_6LOWPAN_NETWORK_DRIVER or NET_6LOWPAN_SNIFFER.
|
|
* \return -3 No Memory for 6LoWPAN stack.
|
|
* \return -4 Null pointer parameter
|
|
* \return -5 Channel list empty
|
|
*/
|
|
int8_t arm_nwk_interface_network_driver_set(int8_t interface_id, const channel_list_s *nwk_channel_list, network_driver_setup_s *link_setup)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
|
|
if (arm_channel_list_validation(nwk_channel_list)) {
|
|
tr_debug("Given channel mask is empty!");
|
|
return -5;
|
|
}
|
|
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur || !cur->mac_api) {
|
|
return -1;
|
|
}
|
|
|
|
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
|
ret_val = -2;
|
|
} else if ((cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED) == 0) {
|
|
ret_val = -2;
|
|
} else if (link_setup && (link_setup->beacon_payload_tlv_length && link_setup->beacon_payload_tlv_ptr == NULL)) {
|
|
ret_val = -4;
|
|
} else if (link_setup && (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_ACCESPOINT || cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_SNIFFER)) {
|
|
|
|
ret_val = 0;
|
|
|
|
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_RF_ACCESPOINT) {
|
|
//Configure setup
|
|
uint8_t *beaon_payload = mac_helper_beacon_payload_reallocate(cur, 18);
|
|
if (beaon_payload) {
|
|
*beaon_payload++ = link_setup->beacon_protocol_id;
|
|
*beaon_payload++ = 7; //Accept Join / Host & Router
|
|
memcpy(beaon_payload, link_setup->network_id, 16);
|
|
ret_val = mac_helper_beacon_payload_register(cur);
|
|
} else {
|
|
ret_val = -3;
|
|
}
|
|
cur->mac_parameters->mac_channel_list = *nwk_channel_list;
|
|
} else {
|
|
|
|
}
|
|
|
|
if (ret_val == 0) {
|
|
if (link_setup->mac_short_adr < 0xfffe) {
|
|
cur->lowpan_address_mode = NET_6LOWPAN_GP16_ADDRESS;
|
|
} else {
|
|
cur->lowpan_address_mode = NET_6LOWPAN_GP64_ADDRESS;
|
|
}
|
|
mac_helper_panid_set(cur, link_setup->mac_panid);
|
|
mac_helper_mac16_address_set(cur, link_setup->mac_short_adr);
|
|
|
|
int channel_number = arm_net_channel_bit_mask_to_number(nwk_channel_list->channel_mask);
|
|
|
|
if (channel_number >= 0) {
|
|
// copy the channel list information, which is needed by FHSS
|
|
//Set Channel
|
|
mac_helper_mac_channel_set(cur, channel_number);
|
|
cur->configure_flags |= INTERFACE_NETWORK_DRIVER_SETUP_DEFINED;
|
|
}
|
|
} else {
|
|
mac_helper_beacon_payload_reallocate(cur, 0);
|
|
}
|
|
} else {
|
|
ret_val = -2;
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
int8_t arm_nwk_interface_up(int8_t interface_id)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur) {
|
|
return -1;
|
|
}
|
|
|
|
if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) && cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
|
return -4;
|
|
}
|
|
|
|
if (!cur->if_up || !cur->if_down) {
|
|
return -5;
|
|
}
|
|
|
|
cur->net_start_tasklet = eventOS_scheduler_get_active_tasklet();
|
|
ret_val = cur->if_up(cur);
|
|
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
int8_t arm_nwk_interface_down(int8_t interface_id)
|
|
{
|
|
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
|
|
if (!(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
|
|
ret_val = -4;
|
|
} else if (!cur->if_up || !cur->if_down) {
|
|
return -5;
|
|
} else {
|
|
ret_val = cur->if_down(cur);
|
|
}
|
|
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
int8_t arm_pana_client_key_pull(int8_t interface_id)
|
|
{
|
|
#ifndef PANA
|
|
(void)interface_id;
|
|
#endif
|
|
return pana_client_key_pull(interface_id);
|
|
}
|
|
|
|
int8_t arm_nwk_link_layer_security_mode(int8_t interface_id, net_6lowpan_link_layer_sec_mode_e mode, uint8_t sec_level, const net_link_layer_psk_security_info_s *psk_key_info)
|
|
{
|
|
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur || thread_info(cur) || !cur->mac_parameters || (cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
#ifndef HAVE_6LOWPAN_ND
|
|
(void) mode;
|
|
(void) sec_level;
|
|
(void) psk_key_info;
|
|
return -1;
|
|
#else
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
|
return -4;
|
|
}
|
|
|
|
//Verify MLE Service
|
|
if (arm_6lowpan_mle_service_ready_for_security_init(cur) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
cur->if_lowpan_security_params->nwk_security_mode = mode;
|
|
mac_helper_link_frame_counter_set(cur->id, 0); //This is maybe mistake
|
|
|
|
if (mode == NET_SEC_MODE_NO_LINK_SECURITY) {
|
|
cur->mac_parameters->mac_configured_sec_level = 0;
|
|
cur->if_lowpan_security_params->security_level = 0;
|
|
cur->configure_flags |= INTERFACE_SECURITY_DEFINED;
|
|
cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION;
|
|
} else {
|
|
if (sec_level == 0 || sec_level > 7) {
|
|
return -2;
|
|
}
|
|
|
|
cur->mac_parameters->mac_configured_sec_level = sec_level;
|
|
cur->if_lowpan_security_params->security_level = sec_level;
|
|
|
|
if (mode == NET_SEC_MODE_PSK_LINK_SECURITY) {
|
|
if (!psk_key_info) {
|
|
return -2;
|
|
}
|
|
//SET PSK KEY
|
|
cur->if_lowpan_security_params->psk_key_info = *psk_key_info;
|
|
cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION;
|
|
cur->configure_flags |= INTERFACE_SECURITY_DEFINED;
|
|
} else {
|
|
if (!cur->if_lowpan_security_params->pana_params) {
|
|
cur->if_lowpan_security_params->pana_params = pana_client_parameter_allocate();
|
|
}
|
|
|
|
if (!cur->if_lowpan_security_params->pana_params) {
|
|
return -2;
|
|
}
|
|
cur->lowpan_info |= (INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION);
|
|
}
|
|
}
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int8_t arm_network_certificate_chain_set(const arm_certificate_chain_entry_s *chain_info)
|
|
{
|
|
int8_t ret = -2;
|
|
|
|
#if !defined(PANA) && !defined(HAVE_WS)
|
|
(void)chain_info;
|
|
#endif
|
|
|
|
#ifdef HAVE_WS
|
|
ret = ws_pae_controller_certificate_chain_set(chain_info);
|
|
#endif
|
|
|
|
#ifdef PANA
|
|
ret = pana_interface_certificate_chain_set(chain_info);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
int8_t arm_network_trusted_certificate_add(const arm_certificate_entry_s *cert)
|
|
{
|
|
#ifdef HAVE_WS
|
|
return ws_pae_controller_trusted_certificate_add(cert);
|
|
#else
|
|
(void) cert;
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
int8_t arm_network_trusted_certificate_remove(const arm_certificate_entry_s *cert)
|
|
{
|
|
#ifdef HAVE_WS
|
|
return ws_pae_controller_trusted_certificate_remove(cert);
|
|
#else
|
|
(void) cert;
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
int8_t arm_network_trusted_certificates_remove(void)
|
|
{
|
|
#ifdef HAVE_WS
|
|
return ws_pae_controller_trusted_certificates_remove();
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
int8_t arm_network_own_certificate_add(const arm_certificate_entry_s *cert)
|
|
{
|
|
#ifdef HAVE_WS
|
|
return ws_pae_controller_own_certificate_add(cert);
|
|
#else
|
|
(void) cert;
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
extern int8_t arm_network_own_certificates_remove(void)
|
|
{
|
|
#ifdef HAVE_WS
|
|
return ws_pae_controller_own_certificates_remove();
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
int8_t arm_network_certificate_revocation_list_add(const arm_cert_revocation_list_entry_s *crl)
|
|
{
|
|
#ifdef HAVE_WS
|
|
return ws_pae_controller_certificate_revocation_list_add(crl);
|
|
#else
|
|
(void) crl;
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
int8_t arm_network_certificate_revocation_list_remove(const arm_cert_revocation_list_entry_s *crl)
|
|
{
|
|
#ifdef HAVE_WS
|
|
return ws_pae_controller_certificate_revocation_list_remove(crl);
|
|
#else
|
|
(void) crl;
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* \brief Read Pana server security key material
|
|
*
|
|
* previous_active_network_key is information is only valid when current_active_key_index is bigger than 1.
|
|
*
|
|
*\param key pointer for store keymaterial information.
|
|
*
|
|
* \return 0 Key Read OK
|
|
* \return -1 Pana server key material not available
|
|
*/
|
|
int8_t arm_network_key_get(int8_t interface_id, ns_keys_t *key)
|
|
{
|
|
#ifndef PANA_SERVER
|
|
(void)interface_id;
|
|
(void)key;
|
|
#endif
|
|
return pana_network_key_get(interface_id, key);
|
|
}
|
|
|
|
int8_t arm_pana_server_library_init(int8_t interface_id, net_tls_cipher_e cipher_mode, const uint8_t *key_material, uint32_t time_period_before_activate_key)
|
|
{
|
|
#ifndef PANA_SERVER
|
|
(void)interface_id;
|
|
(void)cipher_mode;
|
|
(void)key_material;
|
|
(void)time_period_before_activate_key;
|
|
#endif
|
|
return pana_server_interface_init(interface_id, cipher_mode, key_material, time_period_before_activate_key);
|
|
}
|
|
|
|
int8_t arm_pana_activate_new_key(int8_t interface_id)
|
|
{
|
|
#ifndef PANA_SERVER
|
|
(void)interface_id;
|
|
#endif
|
|
return pana_server_trig_new_key(interface_id);
|
|
}
|
|
|
|
int8_t arm_pana_server_key_update(int8_t interface_id, const uint8_t *network_key_material)
|
|
{
|
|
#ifndef PANA_SERVER
|
|
(void)interface_id;
|
|
(void)network_key_material;
|
|
#endif
|
|
return pana_server_key_update(interface_id, network_key_material);
|
|
}
|
|
|
|
int8_t net_pana_parameter_set(const pana_lib_parameters_s *parameter_ptr)
|
|
{
|
|
#ifndef PANA
|
|
(void)parameter_ptr;
|
|
#endif
|
|
return pana_set_params(parameter_ptr);
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief API to read PANA library parameters.
|
|
*
|
|
* \param parameter_ptr Output pointer for Pana parameters
|
|
*
|
|
*/
|
|
int8_t net_pana_parameter_read(pana_lib_parameters_s *parameter_ptr)
|
|
{
|
|
#ifndef PANA
|
|
(void)parameter_ptr;
|
|
#endif
|
|
return pana_get_params(parameter_ptr);
|
|
}
|
|
|
|
int8_t arm_pana_client_library_init(int8_t interface_id, net_tls_cipher_e cipher_mode, uint32_t psk_key_id)
|
|
{
|
|
#ifndef PANA
|
|
(void)interface_id;
|
|
(void)cipher_mode;
|
|
(void)psk_key_id;
|
|
#endif
|
|
return pana_client_interface_init(interface_id, cipher_mode, psk_key_id);
|
|
}
|
|
|
|
int8_t arm_nwk_interface_configure_ipv6_bootstrap_set(int8_t interface_id, net_ipv6_mode_e bootstrap_mode, const uint8_t *ipv6_prefix_pointer)
|
|
{
|
|
#ifndef HAVE_ETHERNET
|
|
(void)interface_id;
|
|
(void)bootstrap_mode;
|
|
(void)ipv6_prefix_pointer;
|
|
#endif
|
|
return ipv6_interface_configure_ipv6_bootstrap_set(interface_id, bootstrap_mode, ipv6_prefix_pointer);
|
|
}
|
|
|
|
int8_t arm_nwk_interface_accept_ipv6_ra(int8_t interface_id, net_ipv6_accept_ra_e accept_ra)
|
|
{
|
|
#ifndef HAVE_ETHERNET
|
|
(void)interface_id;
|
|
(void)accept_ra;
|
|
#endif
|
|
return ipv6_interface_accept_ra(interface_id, accept_ra);
|
|
}
|
|
|
|
int8_t arm_6lowpan_bootsrap_set_for_selected_interface(int8_t interface_id)
|
|
{
|
|
protocol_interface_info_entry_t *cur;
|
|
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur) {
|
|
return -1;
|
|
}
|
|
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE || cur->interface_mode == INTERFACE_UP) {
|
|
return -4;
|
|
}
|
|
|
|
if (cur->nwk_id != IF_6LoWPAN) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Set network interface bootstrap setup.
|
|
*
|
|
* \param interface_id Network interface ID
|
|
* \param bootstrap_mode Selected Bootstrap mode:
|
|
* * NET_6LOWPAN_BORDER_ROUTER, Initialise Border router basic setup
|
|
* * NET_6LOWPAN_ROUTER, Enable normal 6LoWPAN ND and RPL to bootstrap
|
|
* * NET_6LOWPAN_HOST, Enable normal 6LoWPAN ND only to bootstrap
|
|
* * NET_6LOWPAN_SLEEPY_HOST, Enable normal 6LoWPAN ND only to bootstrap
|
|
*
|
|
* \param net_6lowpan_mode_extension Define MLE protocol use and 6LoWPAN mode
|
|
*
|
|
* \return >=0 Bootstrap mode set OK.
|
|
* \return -1 Unknown network ID.
|
|
* \return -2 Unsupported bootstrap type or extension in this library.
|
|
* \return -3 No Memory for 6LoWPAN stack.
|
|
* \return -4 Null pointer parameter
|
|
*/
|
|
int8_t arm_nwk_interface_configure_6lowpan_bootstrap_set(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode, net_6lowpan_mode_extension_e net_6lowpan_mode_extension)
|
|
{
|
|
int8_t ret_val;
|
|
(void)bootstrap_mode;
|
|
ret_val = arm_6lowpan_bootsrap_set_for_selected_interface(interface_id);
|
|
|
|
if (ret_val == 0) {
|
|
|
|
if (net_6lowpan_mode_extension == NET_6LOWPAN_THREAD) {
|
|
ret_val = thread_node_bootstrap_init(interface_id, bootstrap_mode);
|
|
} else if (net_6lowpan_mode_extension == NET_6LOWPAN_WS) {
|
|
ret_val = ws_common_init(interface_id, bootstrap_mode);
|
|
} else {
|
|
ret_val = arm_6lowpan_bootstarp_bootstrap_set(interface_id, bootstrap_mode, net_6lowpan_mode_extension);
|
|
}
|
|
}
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
int8_t arm_nwk_set_channel_list(int8_t interface_id, const channel_list_s *nwk_channel_list)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
|
|
if (!cur || !cur->mac_parameters) {
|
|
return -1;
|
|
}
|
|
|
|
if (arm_channel_list_validation(nwk_channel_list)) {
|
|
tr_debug("Given channel mask is empty!");
|
|
return -2;
|
|
}
|
|
|
|
//CHECK Value
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
|
return -4;
|
|
}
|
|
|
|
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
|
if (!cur->border_router_setup) {
|
|
return -2;
|
|
}
|
|
|
|
const int channel_number = arm_net_channel_bit_mask_to_number(nwk_channel_list->channel_mask);
|
|
if (channel_number < 0) {
|
|
return -3;
|
|
}
|
|
cur->mac_parameters->mac_channel_list = *nwk_channel_list;
|
|
cur->mac_parameters->mac_channel = channel_number;
|
|
cur->border_router_setup->chanlist = &cur->mac_parameters->mac_channel_list;
|
|
ret_val = 0;
|
|
} else {
|
|
// copy the channel information and store one internal pointer to it
|
|
cur->mac_parameters->mac_channel_list = *nwk_channel_list;
|
|
ret_val = 0;
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
int8_t arm_nwk_6lowpan_link_scan_parameter_set(int8_t interface_id, uint8_t scan_time)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
|
return -4;
|
|
}
|
|
|
|
if (cur->mac_parameters) {
|
|
if (scan_time > 14) {
|
|
ret_val = -5;
|
|
} else {
|
|
nwk_scan_params_t *scan_params = 0;
|
|
scan_params = &cur->mac_parameters->nwk_scan_params;
|
|
scan_params->scan_duration = scan_time;
|
|
ret_val = 0;
|
|
}
|
|
}
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
int8_t arm_nwk_6lowpan_link_panid_filter_for_nwk_scan(int8_t interface_id, uint16_t pan_id_filter)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
|
ret_val = -2;
|
|
} else if (cur->mac_parameters) {
|
|
nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
|
|
filter->net_pan_id_filter = pan_id_filter;
|
|
ret_val = 0;
|
|
}
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
int8_t arm_nwk_6lowpan_link_nwk_id_filter_for_nwk_scan(int8_t interface_id, const uint8_t *nwk_id_filter)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
|
ret_val = -2;
|
|
} else if (cur->mac_parameters) {
|
|
nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
|
|
ret_val = mac_helper_nwk_id_filter_set(nwk_id_filter, filter);
|
|
}
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
int8_t arm_nwk_6lowpan_link_protocol_id_filter_for_nwk_scan(int8_t interface_id, uint8_t protocol_ID)
|
|
{
|
|
int8_t ret_val = -1;
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
|
|
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
|
ret_val = -4;
|
|
} else if (cur->mac_parameters) {
|
|
nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
|
|
filter->beacon_protocol_id_filter = protocol_ID;
|
|
ret_val = 0;
|
|
}
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
/* Don't have a loopback interface we can optimise for, but we do still need a route so we
|
|
* can talk to ourself at all, in case our address isn't in an on-link prefix.
|
|
*/
|
|
static void net_automatic_loopback_route_update(protocol_interface_info_entry_t *interface, const if_address_entry_t *addr, if_address_callback_t reason)
|
|
{
|
|
/* Don't care about link-local addresses - we know they're on-link */
|
|
if (addr_is_ipv6_link_local(addr->address)) {
|
|
return;
|
|
}
|
|
|
|
/* TODO: When/if we have a real loopback interface, these routes would use it instead of interface->id */
|
|
switch (reason) {
|
|
case ADDR_CALLBACK_DAD_COMPLETE:
|
|
ipv6_route_add(addr->address, 128, interface->id, NULL, ROUTE_LOOPBACK, 0xFFFFFFFF, 0);
|
|
break;
|
|
case ADDR_CALLBACK_DELETED:
|
|
ipv6_route_delete(addr->address, 128, interface->id, NULL, ROUTE_LOOPBACK);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int8_t arm_nwk_6lowpan_beacon_join_priority_tx_callback_set(int8_t interface_id,
|
|
beacon_join_priority_tx_cb *beacon_join_priority_tx_cb_ptr)
|
|
{
|
|
return (mac_beacon_link_beacon_join_priority_tx_callback_set(interface_id, beacon_join_priority_tx_cb_ptr));
|
|
}
|
|
|
|
int8_t arm_nwk_6lowpan_beacon_compare_rx_callback_set(int8_t interface_id,
|
|
beacon_compare_rx_cb *beacon_compare_rx_cb_ptr)
|
|
{
|
|
return (mac_beacon_link_beacon_compare_rx_callback_set(interface_id, beacon_compare_rx_cb_ptr));
|
|
}
|
|
|
|
/**
|
|
* \brief A function to initialize core elements of NanoStack library.
|
|
*
|
|
* \param core_idle is a function pointer to a function that is called whenever NanoStack is idle.
|
|
* \return 0 on success.
|
|
* \return -1 if a null pointer is given.
|
|
*/
|
|
int8_t net_init_core(void)
|
|
{
|
|
/* Reset Protocol_stats */
|
|
protocol_stats_init();
|
|
protocol_core_init();
|
|
#ifdef HAVE_RPL
|
|
rpl_data_init();
|
|
// XXX application should call these!
|
|
rpl_of0_init();
|
|
rpl_mrhof_init();
|
|
#endif
|
|
network_library_init();
|
|
addr_notification_register(net_automatic_loopback_route_update);
|
|
return 0;
|
|
}
|
|
|
|
static int8_t mac_data_poll_host_polling_state_change_check(protocol_interface_info_entry_t *cur)
|
|
{
|
|
int8_t ret_val = 0;
|
|
if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) {
|
|
tr_warn("Host Control not accepted for Router");
|
|
ret_val = -1;
|
|
} else if (nwk_bootsrap_ready(cur) == 0) {
|
|
tr_debug("Bootsrap Active");
|
|
ret_val = -2;
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Set new Host state.
|
|
*
|
|
* \param mode new host state
|
|
* \param poll_time poll time in seconds only handled when NET_HOST_SLOW_POLL_MODE is enabled
|
|
*
|
|
* Valid poll time for NET_HOST_SLOW_POLL_MODE is 0 < poll_time poll_time < 864001 (1 Day)
|
|
*
|
|
* \return 0, State update OK
|
|
* \return -1, unknown state
|
|
* \return -2, invalid time
|
|
* \return -3 MLE handshake trig Fail
|
|
*
|
|
*/
|
|
int8_t arm_nwk_host_mode_set(int8_t interface_id, net_host_mode_t mode, uint32_t poll_time)
|
|
{
|
|
protocol_interface_info_entry_t *cur;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur) {
|
|
return -1;
|
|
}
|
|
|
|
if (mac_data_poll_host_polling_state_change_check(cur) != 0) {
|
|
return -3;
|
|
}
|
|
|
|
net_host_mode_t old_mode;
|
|
|
|
if (mac_data_poll_host_mode_get(cur, &old_mode) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (thread_info(cur)) {
|
|
//save polltime for later use, polltime is zero for fast poll mode
|
|
thread_info(cur)->sleepy_host_poll_time = 0;
|
|
if (mode == NET_HOST_SLOW_POLL_MODE) {
|
|
thread_info(cur)->sleepy_host_poll_time = poll_time;
|
|
}
|
|
if (old_mode == NET_HOST_RX_ON_IDLE && mode != old_mode
|
|
&& thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE) {
|
|
tr_debug("End device changing to SED");
|
|
thread_management_device_type_set(cur->id, THREAD_DEVICE_SED);
|
|
return 0;
|
|
}
|
|
}
|
|
return mac_data_poll_host_mode_set(cur, mode, poll_time);
|
|
}
|
|
|
|
/**
|
|
* \brief Read Current Host State.
|
|
*
|
|
* \param mode pointer where host state will be saved
|
|
|
|
* \return 0, State Read update OK
|
|
* \return -1, Net Role is Router or stack is idle
|
|
*
|
|
*/
|
|
int8_t arm_nwk_host_mode_get(int8_t interface_id, net_host_mode_t *mode)
|
|
{
|
|
protocol_interface_info_entry_t *cur;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
|
|
return -1;
|
|
}
|
|
|
|
return mac_data_poll_host_mode_get(cur, mode);
|
|
}
|
|
|
|
|
|
int8_t net_nvm_data_clean(int8_t interface_id)
|
|
{
|
|
int8_t ret_val = -2; // Not ative
|
|
protocol_interface_info_entry_t *cur = 0;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
if (cur->mac_parameters) {
|
|
nwk_filter_params_s *filter = &(cur->mac_parameters->nwk_filter_params);
|
|
|
|
if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) == 0) {
|
|
mac_helper_nwk_id_filter_set(0, filter);
|
|
mac_helper_panid_set(cur, 0xffff);
|
|
mac_helper_mac16_address_set(cur, 0xffff);
|
|
pana_reset_client_session();
|
|
ret_val = 0;
|
|
} else {
|
|
ret_val = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
static void trace_cmd_print(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
vtracef(TRACE_LEVEL_CMD, TRACE_GROUP, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
void arm_print_routing_table(void)
|
|
{
|
|
arm_print_routing_table2(trace_cmd_print);
|
|
}
|
|
|
|
void arm_print_routing_table2(void (*print_fn)(const char *fmt, ...))
|
|
{
|
|
ipv6_destination_cache_print(print_fn);
|
|
ipv6_route_table_print(print_fn);
|
|
#ifdef HAVE_RPL
|
|
rpl_control_print(print_fn);
|
|
#endif
|
|
}
|
|
|
|
void arm_print_neigh_cache(void)
|
|
{
|
|
arm_print_neigh_cache2(trace_cmd_print);
|
|
}
|
|
|
|
void arm_print_neigh_cache2(void (*print_fn)(const char *fmt, ...))
|
|
{
|
|
nwk_interface_print_neigh_cache(print_fn);
|
|
}
|
|
|
|
void arm_print_protocols(void)
|
|
{
|
|
arm_print_protocols2(trace_cmd_print, ' ');
|
|
}
|
|
|
|
void arm_print_protocols2(void (*print_fn)(const char *fmt, ...), char sep)
|
|
{
|
|
socket_list_print(print_fn, sep);
|
|
}
|
|
|
|
void arm_ncache_flush(void)
|
|
{
|
|
nwk_interface_flush_neigh_cache();
|
|
}
|
|
|
|
int arm_nwk_sleepy_device_parent_buffer_size_set(int8_t interface_id, uint16_t big_packet_threshold, uint16_t small_packets_per_child_count, uint16_t big_packets_total_count)
|
|
{
|
|
protocol_interface_info_entry_t *cur;
|
|
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (cur) {
|
|
return lowpan_adaptation_indirect_queue_params_set(cur, big_packet_threshold,
|
|
big_packets_total_count, small_packets_per_child_count);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int8_t arm_nwk_set_cca_threshold(int8_t interface_id, uint8_t cca_threshold)
|
|
{
|
|
protocol_interface_info_entry_t *cur;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur || !cur->mac_api || (cca_threshold > 100)) {
|
|
return -1;
|
|
}
|
|
mlme_set_t set_req;
|
|
set_req.attr = macCCAThreshold;
|
|
set_req.attr_index = 0;
|
|
set_req.value_pointer = &cca_threshold;
|
|
set_req.value_size = sizeof(cca_threshold);
|
|
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
|
return 0;
|
|
}
|
|
|
|
int8_t arm_nwk_set_tx_output_power(int8_t interface_id, uint8_t tx_power)
|
|
{
|
|
protocol_interface_info_entry_t *cur;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
if (!cur || !cur->mac_api || (tx_power > 100)) {
|
|
return -1;
|
|
}
|
|
mlme_set_t set_req;
|
|
set_req.attr = macTXPower;
|
|
set_req.attr_index = 0;
|
|
set_req.value_pointer = &tx_power;
|
|
set_req.value_size = sizeof(tx_power);
|
|
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
|
return 0;
|
|
}
|
|
|
|
const cca_threshold_table_s *arm_nwk_get_cca_threshold_table(int8_t interface_id)
|
|
{
|
|
protocol_interface_info_entry_t *cur;
|
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
|
// Interface or MAC parameters not initialized
|
|
if (!cur || !cur->mac_parameters) {
|
|
return NULL;
|
|
}
|
|
// Automatic CCA threshold not initialized
|
|
if (!cur->mac_parameters->cca_thr_table.cca_threshold_table || !cur->mac_parameters->cca_thr_table.number_of_channels) {
|
|
return NULL;
|
|
}
|
|
return &cur->mac_parameters->cca_thr_table;
|
|
}
|