mirror of https://github.com/ARMmbed/mbed-os.git
Merge commit '780e9afb8f3b8f09e66573e7d4ba096dd9a87dd7'
Nanostack v10.1.0 for Mbed OS 5.12 * commit '780e9afb8f3b8f09e66573e7d4ba096dd9a87dd7': Squashed 'features/nanostack/sal-stack-nanostack/' changes from 513a38e..c5ee9e4pull/9838/head
commit
b68e5edbc7
|
@ -1,5 +1,4 @@
|
|||
.settings/
|
||||
.yotta.json
|
||||
*.dep
|
||||
*.htm
|
||||
*.crf
|
||||
|
@ -66,8 +65,7 @@ cscope.files
|
|||
!debugger.ini
|
||||
*Log.txt
|
||||
*.mpw
|
||||
yotta_modules
|
||||
yotta_targets
|
||||
build
|
||||
html
|
||||
site
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ clean-extra: $(CLEANTESTDIRS)
|
|||
# 3. TBD: importing to mbed OS
|
||||
|
||||
TARGET_DIR:=release
|
||||
CONFIGURATIONS_TO_BUILD:=lowpan_border_router lowpan_host lowpan_router nanostack_full thread_border_router thread_router thread_end_device ethernet_host
|
||||
CONFIGURATIONS_TO_BUILD:=lowpan_border_router lowpan_host lowpan_router nanostack_full thread_border_router thread_router thread_end_device ethernet_host ws_border_router ws_router
|
||||
TOOLCHAINS_TO_BUILD:=GCC ARM ARMC6 IAR
|
||||
CORES_TO_BUILD:=Cortex-M0 Cortex-M3
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2013-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -264,6 +264,7 @@ typedef enum {
|
|||
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
|
||||
macDefaultKeySource = 0x7c, /*<Default key source*/
|
||||
//NON standard extension
|
||||
macRfConfiguration = 0xfb, /*<RF channel configuration parameters*/
|
||||
macAcceptByPassUnknowDevice = 0xfc, /*< Accept data trough MAC if packet is data can be authenticated by group key nad MIC. Security enforsment point must be handled carefully these packets */
|
||||
macLoadBalancingBeaconTx = 0xfd, /*< Trig Beacon from load balance module periodic */
|
||||
macLoadBalancingAcceptAnyBeacon = 0xfe, /*<Beacon accept state control from other network. Value size bool, data true=Enable, false=disable .*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2012-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2013-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -235,6 +235,18 @@ typedef struct {
|
|||
const uint8_t *key_chain[4]; /**< Certificate private key. */
|
||||
} arm_certificate_chain_entry_s;
|
||||
|
||||
/** Certificate structure. */
|
||||
typedef struct {
|
||||
const uint8_t *cert; /**< Certificate pointer. */
|
||||
uint16_t cert_len; /**< Certificate length. */
|
||||
} arm_certificate_entry_s;
|
||||
|
||||
/** Certificate Revocation List structure. */
|
||||
typedef struct {
|
||||
const uint8_t *crl; /**< Certificate Revocation List pointer. */
|
||||
uint16_t crl_len; /**< Certificate Revocation List length. */
|
||||
} arm_cert_revocation_list_entry_s;
|
||||
|
||||
/** Structure for the network keys used by net_network_key_get */
|
||||
typedef struct ns_keys_t
|
||||
|
||||
|
@ -880,12 +892,56 @@ extern int8_t arm_net_route_delete(const uint8_t *prefix, uint8_t prefix_len, co
|
|||
extern int8_t arm_nwk_6lowpan_border_router_nd_context_load(int8_t interface_id, uint8_t *contex_data); //NVM
|
||||
|
||||
/**
|
||||
* Set certificate chain for PANA
|
||||
* Set certificate chain
|
||||
*
|
||||
* \param chain_info Certificate chain.
|
||||
* \return 0 on success, negative on failure.
|
||||
*/
|
||||
extern int8_t arm_network_certificate_chain_set(const arm_certificate_chain_entry_s *chain_info);
|
||||
|
||||
/**
|
||||
* Add trusted certificate
|
||||
*
|
||||
* This is used to add trusted root or intermediate certificate in addition to those
|
||||
* added using certificate chain set call. Function can be called several times to add
|
||||
* more than one certificate.
|
||||
*
|
||||
* \param cert Certificate.
|
||||
* \return 0 on success, negative on failure.
|
||||
*/
|
||||
extern int8_t arm_network_trusted_certificate_add(const arm_certificate_entry_s *cert);
|
||||
|
||||
/**
|
||||
* Remove trusted certificate
|
||||
*
|
||||
* This is used to remove trusted root or intermediate certificate.
|
||||
*
|
||||
* \param cert Certificate.
|
||||
* \return 0 on success, negative on failure.
|
||||
*/
|
||||
extern int8_t arm_network_trusted_certificate_remove(const arm_certificate_entry_s *cert);
|
||||
|
||||
/**
|
||||
* Add Certificate Revocation List
|
||||
*
|
||||
* This is used to add Certificate Revocation List (CRL). Function can be called several
|
||||
* times to add more than one Certificate Revocation List.
|
||||
*
|
||||
* \param crl Certificate revocation list
|
||||
* \return 0 on success, negative on failure.
|
||||
*/
|
||||
extern int8_t arm_network_certificate_revocation_list_add(const arm_cert_revocation_list_entry_s *crl);
|
||||
|
||||
/**
|
||||
* Remove Certificate Revocation List
|
||||
*
|
||||
* This is used to remove Certificate Revocation List.
|
||||
*
|
||||
* \param crl Certificate revocation list
|
||||
* \return 0 on success, negative on failure.
|
||||
*/
|
||||
extern int8_t arm_network_certificate_revocation_list_remove(const arm_cert_revocation_list_entry_s *crl);
|
||||
|
||||
/**
|
||||
* \brief Add PSK key to TLS library.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2013-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -530,6 +530,30 @@ int thread_test_mle_message_send(int8_t interface_id, uint8_t *dst_address, uint
|
|||
* \return <0 Failure
|
||||
*/
|
||||
int thread_test_extension_name_set(int8_t interface_id, char extension_name[16]);
|
||||
|
||||
/**
|
||||
* \brief Set multicast addresses per message.
|
||||
*
|
||||
* \param value Number of addresses per message (valid range 1-15)
|
||||
*
|
||||
* \return 0 OK
|
||||
* \return <0 Failure
|
||||
*/
|
||||
int8_t thread_test_mcast_address_per_message_set(uint8_t value);
|
||||
|
||||
/**
|
||||
* Thread router parent priority set.
|
||||
*
|
||||
* This function is used to set parent priority in connectivity TLV.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param parent_priority value to be set (0x40 High, 0x00 Medium, 0xC0 Low, 0x80 Do not use) .
|
||||
*
|
||||
* \return 0, Set OK.
|
||||
* \return <0 Set Fail.
|
||||
*/
|
||||
int thread_test_parent_priority_set(int8_t interface_id, uint8_t parent_priority);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef NET_WS_TEST_H_
|
||||
#define NET_WS_TEST_H_
|
||||
|
||||
/* Prevent this file being inserted in public Doxygen generated file
|
||||
* this is not part of our external API. */
|
||||
#ifndef DOXYGEN
|
||||
|
||||
/**
|
||||
* \file net_ws_test.h
|
||||
* \brief Wi-SUN Library Test API.
|
||||
*
|
||||
* \warning NOTICE! This is test API must not be used externally.
|
||||
*
|
||||
* \warning This file is not part of the version number control and can change any time.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ns_types.h"
|
||||
|
||||
/**
|
||||
* \brief Set Pan size.
|
||||
*
|
||||
* Pan size is reported to advertisement. Using this function
|
||||
* actual value can be overridden.
|
||||
*
|
||||
* Set pan_size to 0xffff to stop override
|
||||
*
|
||||
* \param interface_id Network Interface
|
||||
* \param pan_size Pan size reported in advertisements
|
||||
*
|
||||
* \return 0 OK
|
||||
* \return <0 Failure
|
||||
*/
|
||||
int ws_test_pan_size_set(int8_t interface_id, uint16_t pan_size);
|
||||
|
||||
/**
|
||||
* \brief Set maximum child count.
|
||||
*
|
||||
* Maximum amount of children allowed for this device
|
||||
*
|
||||
* Values above MAC neighbor table - RPL parents - temporary entries will cause undefined behaviour
|
||||
*
|
||||
* Set child count to 0xffff to stop override
|
||||
*
|
||||
* \param interface_id Network Interface
|
||||
* \param child_count Pan size reported in advertisements
|
||||
*
|
||||
* \return 0 OK
|
||||
* \return <0 Failure
|
||||
*/
|
||||
int ws_test_max_child_count_set(int8_t interface_id, uint16_t child_count);
|
||||
|
||||
/**
|
||||
* Sets Group Transient Keys.
|
||||
*
|
||||
* Sets Group Transient Keys (GTKs). Up to four GTKs can be set (GTKs from index
|
||||
* 0 to 3). At least one GTK must be set. GTKs provided in this function call are
|
||||
* compared to current GTKs on node or border router GTK storage. If GTK is new
|
||||
* or modified it is updated to GTK storage. If GTK is same as previous one, no
|
||||
* changes are made. If GTK is NULL then it is removed from GTK storage. When a
|
||||
* new GTK is inserted or GTK is modified, GTK lifetime is set to default. If GTKs
|
||||
* are set to border router after bootstrap, border router initiates GTK update
|
||||
* to network.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param gtk GTK array, if GTK is not set, pointer for the index shall be NULL.
|
||||
*
|
||||
* \return 0 GTKs are set
|
||||
* \return <0 GTK set has failed
|
||||
*/
|
||||
int ws_test_gtk_set(int8_t interface_id, uint8_t *gtk[4]);
|
||||
|
||||
/**
|
||||
* Sets index of active key.
|
||||
*
|
||||
* Sets index of active Group Transient Key (GTK) to border router. If index is
|
||||
* set after bootstrap, initiates dissemination of new key index to network.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param index Key index
|
||||
*
|
||||
* \return 0 Active key index has been set
|
||||
* \return <0 Active key index set has failed
|
||||
*/
|
||||
int ws_test_active_key_set(int8_t interface_id, uint8_t index);
|
||||
|
||||
/**
|
||||
* Sets lifetime for keys
|
||||
*
|
||||
* Sets Group Transient Key (GTK), Pairwise Master Key (PMK) and
|
||||
* Pairwise Transient Key (PTK) lifetimes.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param gtk_lifetime GTK lifetime in minutes
|
||||
* \param pmk_lifetime PMK lifetime in minutes
|
||||
* \param ptk_lifetime PTK lifetime in minutes
|
||||
*
|
||||
* \return 0 Lifetimes are set
|
||||
* \return <0 Lifetime set has failed
|
||||
*/
|
||||
int ws_test_key_lifetime_set(
|
||||
int8_t interface_id,
|
||||
uint32_t gtk_lifetime,
|
||||
uint32_t pmk_lifetime,
|
||||
uint32_t ptk_lifetime
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets time configurations for GTK keys
|
||||
*
|
||||
* Sets GTK Revocation Lifetime Reduction and GTK New Activation Time values
|
||||
* as parts of the GTK lifetime (e.g. value 3 is 1/3 * lifetime). Sets GTK
|
||||
* maximum mismatch time in minutes.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param revocat_lifetime_reduct GTK Revocation Lifetime Reduction (1 / value * GTK lifetime)
|
||||
* \param new_activation_time GTK New Activation Time (1 / value * GTK lifetime)
|
||||
* \param max_mismatch GTK maximum mismatch in minutes
|
||||
*
|
||||
* \return 0 Lifetimes are set
|
||||
* \return <0 Lifetime set has failed.
|
||||
*/
|
||||
int ws_test_gtk_time_settings_set(
|
||||
int8_t interface_id,
|
||||
uint8_t revocat_lifetime_reduct,
|
||||
uint8_t new_activation_time,
|
||||
uint32_t max_mismatch
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DOXYGEN */
|
||||
#endif /* NET_THREAD_TEST_H_ */
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2017-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2006-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -64,6 +64,7 @@ typedef enum {
|
|||
PHY_EXTENSION_GET_TIMESTAMP, /**< Read 32-bit constant monotonic time stamp in us */
|
||||
PHY_EXTENSION_SET_CSMA_PARAMETERS, /**< CSMA parameter's are given by phy_csma_params_t structure remember type cast uint8_t pointer to structure type*/
|
||||
PHY_EXTENSION_GET_SYMBOLS_PER_SECOND, /**< Read Symbols per seconds which will help to convert symbol time to real time */
|
||||
PHY_EXTENSION_SET_RF_CONFIGURATION /**< Set RF configuration using phy_rf_channel_parameters_s structure */
|
||||
} phy_extension_type_e;
|
||||
|
||||
/** Address types */
|
||||
|
@ -130,6 +131,7 @@ typedef enum phy_modulation_e {
|
|||
M_OQPSK, ///< OQPSK
|
||||
M_BPSK, ///< BPSK
|
||||
M_GFSK, ///< GFSK
|
||||
M_2FSK, ///< 2FSK
|
||||
M_UNDEFINED ///< UNDEFINED
|
||||
} phy_modulation_e;
|
||||
|
||||
|
@ -146,6 +148,13 @@ typedef enum {
|
|||
CHANNEL_PAGE_10 = 10 ///< Page 10
|
||||
} channel_page_e;
|
||||
|
||||
/** Modulation index */
|
||||
typedef enum {
|
||||
MODULATION_INDEX_0_5 = 0, ///< Modulation index 0.5
|
||||
MODULATION_INDEX_1_0 = 1, ///< Modulation index 1.0
|
||||
MODULATION_INDEX_UNDEFINED ///< Modulation index undefined
|
||||
} phy_modulation_index_e;
|
||||
|
||||
/** Channel configuration */
|
||||
typedef struct phy_rf_channel_configuration_s {
|
||||
uint32_t channel_0_center_frequency; ///< Center frequency
|
||||
|
@ -153,6 +162,7 @@ typedef struct phy_rf_channel_configuration_s {
|
|||
uint32_t datarate; ///< Data rate
|
||||
uint16_t number_of_channels; ///< Number of channels
|
||||
phy_modulation_e modulation; ///< Modulation scheme
|
||||
phy_modulation_index_e modulation_index; ///< Modulation index
|
||||
} phy_rf_channel_configuration_s;
|
||||
|
||||
/** Channel page configuration */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2010-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file ws_bbr_api.h
|
||||
* \brief Wi-SUN backbone border router (BBR) application interface.
|
||||
*
|
||||
* This is Wi-SUN backbone Border router service.
|
||||
* When started the module takes care of starting the
|
||||
* components that enables default border router functionality in Wi-SUN network.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WS_BBR_API_H_
|
||||
#define WS_BBR_API_H_
|
||||
|
||||
#include "ns_types.h"
|
||||
|
||||
/**
|
||||
* Start backbone border router service.
|
||||
*
|
||||
* if backbone interface is enabled and allows routing.
|
||||
* Enables ND proxy for address found from backbone
|
||||
*
|
||||
* \param interface_id Wi-SUN network interface id.
|
||||
* \param backbone_interface_id backbone interface id.
|
||||
*
|
||||
* \return 0 on success
|
||||
* \return <0 in case of errors
|
||||
*
|
||||
*/
|
||||
int ws_bbr_start(int8_t interface_id, int8_t backbone_interface_id);
|
||||
|
||||
/**
|
||||
* Stop backbone Border router.
|
||||
*
|
||||
* \param interface_id interface ID of the Wi-SUN network
|
||||
*
|
||||
* \return 0 on success
|
||||
* \return <0 in case of errors
|
||||
*
|
||||
*/
|
||||
void ws_bbr_stop(int8_t interface_id);
|
||||
|
||||
/**
|
||||
* Remove node's keys from border router
|
||||
*
|
||||
* Removes node's keys from border router i.e. Pairwise Master Key (PMK)
|
||||
* and Pairwise Transient Key (PTK). This function is used on revocation of
|
||||
* node's access procedure after authentication service is configured
|
||||
* to reject authentication attempts of the node (e.g. node's certificate is
|
||||
* revoked). Sub sequential calls to function can be used to remove several
|
||||
* nodes from border router.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param eui64 EUI-64 of revoked node
|
||||
*
|
||||
* \return 0, Node's keys has been removed
|
||||
* \return <0 Node's key remove has failed (e.g. unknown address)
|
||||
*/
|
||||
int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64);
|
||||
|
||||
/**
|
||||
* Start revocation of node's access
|
||||
*
|
||||
* Starts revocation of node's access procedure on border router. Before
|
||||
* the call to this function, authentication service must be configured to
|
||||
* reject authentication attempts of the removed nodes (e.g. certificates
|
||||
* of the nodes are revoked). Also the keys for the nodes must be removed
|
||||
* from the border router.
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
*
|
||||
* \return 0, Revocation started OK.
|
||||
* \return <0 Revocation start failed.
|
||||
*/
|
||||
int ws_bbr_node_access_revoke_start(int8_t interface_id);
|
||||
|
||||
#endif /* WS_BBR_API_H_ */
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -75,6 +75,10 @@ extern "C" {
|
|||
#define CHANNEL_SPACING_100 0x03 // 100 khz
|
||||
#define CHANNEL_SPACING_250 0x04 // 250 khz
|
||||
|
||||
#define NETWORK_SIZE_AUTOMATIC 0x00
|
||||
#define NETWORK_SIZE_SMALL 0x01
|
||||
#define NETWORK_SIZE_LARGE 0x10
|
||||
|
||||
|
||||
/** Temporary API change flag. this will be removed when new version of API is implemented on applications
|
||||
*
|
||||
|
@ -126,6 +130,27 @@ int ws_management_regulatory_domain_set(
|
|||
uint8_t operating_class,
|
||||
uint8_t operating_mode);
|
||||
|
||||
/**
|
||||
* Set timing parameters related to network size.
|
||||
*
|
||||
* timing parameters follows the specification example from Wi-SUN specification
|
||||
*
|
||||
* Default value: automatic
|
||||
* small network size: hundreds of devices
|
||||
* Large network size: thousands of devices
|
||||
* automatic: when discovering the network network size is learned
|
||||
* from advertisements and timings adjusted accordingly
|
||||
*
|
||||
* \param interface_id Network interface ID.
|
||||
* \param network_size define from NETWORK_SIZE_*.
|
||||
*
|
||||
* \return 0, Init OK.
|
||||
* \return <0 Init fail.
|
||||
*/
|
||||
int ws_management_network_size_set(
|
||||
int8_t interface_id,
|
||||
uint8_t network_size);
|
||||
|
||||
/**
|
||||
* Set channel mask for FHSS operation.
|
||||
*
|
||||
|
@ -230,4 +255,7 @@ int ws_management_fhss_broadcast_channel_function_configure(
|
|||
uint8_t dwell_interval,
|
||||
uint32_t broadcast_interval);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* WS_MANAGEMENT_API_H_ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2013-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -18,7 +18,7 @@
|
|||
#include "nsconfig.h"
|
||||
#include "ns_types.h"
|
||||
#include <string.h>
|
||||
#include "Core/include/socket.h"
|
||||
#include "Core/include/ns_socket.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "ns_trace.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2013-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -22,7 +22,7 @@
|
|||
#include "eventOS_scheduler.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "Core/include/socket.h"
|
||||
#include "Core/include/ns_socket.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "Common_Protocols/udp.h"
|
||||
#include "Common_Protocols/ipv6.h"
|
||||
|
@ -373,6 +373,7 @@ void protocol_6lowpan_configure_core(protocol_interface_info_entry_t *cur)
|
|||
cur->ipv6_neighbour_cache.link_mtu = LOWPAN_MTU;
|
||||
#ifdef HAVE_6LOWPAN_ND
|
||||
cur->ipv6_neighbour_cache.send_nud_probes = nd_params.send_nud_probes;
|
||||
cur->ipv6_neighbour_cache.probe_avoided_routers = nd_params.send_nud_probes;
|
||||
cur->iids_map_to_mac = nd_params.iids_map_to_mac;
|
||||
#endif
|
||||
cur->ip_multicast_as_mac_unicast_to_parent = false;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1408,6 +1408,8 @@ static void lowpan_mle_receive_security_bypass_cb(int8_t interface_id, mle_messa
|
|||
pana_reset_client_session();
|
||||
bootsrap_next_state_kick(ER_PANA_AUTH_ERROR, interface);
|
||||
}
|
||||
#else
|
||||
(void)mle_msg;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2013-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -26,7 +26,7 @@
|
|||
#include "string.h"
|
||||
#include "ns_trace.h"
|
||||
#include "randLIB.h"
|
||||
#include "Core/include/socket.h"
|
||||
#include "Core/include/ns_socket.h"
|
||||
#include "6LoWPAN/IPHC_Decode/cipv6.h"
|
||||
#include "6LoWPAN/Fragmentation/cipv6_fragmenter.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -19,7 +19,7 @@
|
|||
#define MAC_HELPER_H
|
||||
|
||||
#include "mlme.h"
|
||||
#include "Core/include/address.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
|
||||
struct channel_list_s;
|
||||
struct nwk_scan_params;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -22,8 +22,8 @@
|
|||
#include "NWK_INTERFACE/Include/protocol_abstract.h"
|
||||
#include "NWK_INTERFACE/Include/protocol_timer.h"
|
||||
#include "Service_Libs/mle_service/mle_service_api.h"
|
||||
#include "Core/include/address.h"
|
||||
#include "Core/include/socket.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
#include "Core/include/ns_socket.h"
|
||||
#include "6LoWPAN/Thread/thread_common.h"
|
||||
#include "6LoWPAN/Thread/thread_management_internal.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2017, 2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -29,7 +29,7 @@
|
|||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "NWK_INTERFACE/Include/protocol_stats.h"
|
||||
#include "6LoWPAN/IPHC_Decode/cipv6.h"
|
||||
#include "Core/include/socket.h"
|
||||
#include "Core/include/ns_socket.h"
|
||||
#include "6LoWPAN/Mesh/mesh.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2017, 2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -18,7 +18,7 @@
|
|||
#ifndef ND_DEFINES_H_
|
||||
#define ND_DEFINES_H_
|
||||
|
||||
#include "Core/include/address.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
#include "ns_list.h"
|
||||
#include "6LoWPAN/IPHC_Decode/lowpan_context.h"
|
||||
#include "Common_Protocols/icmpv6_prefix.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2013-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -831,6 +831,8 @@ buffer_t *nd_dar_parse(buffer_t *buf, protocol_interface_info_entry_t *cur_inter
|
|||
}
|
||||
|
||||
drop:
|
||||
#else
|
||||
(void)cur_interface;
|
||||
#endif
|
||||
|
||||
return buffer_free(buf);
|
||||
|
@ -845,7 +847,7 @@ static void nd_update_registration(protocol_interface_info_entry_t *cur_interfac
|
|||
neigh->lifetime = aro->lifetime * UINT32_C(60);
|
||||
ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE);
|
||||
/* Register with 2 seconds off the lifetime - don't want the NCE to expire before the route */
|
||||
ipv6_route_add(neigh->ip_address, 128, cur_interface->id, NULL, ROUTE_ARO, neigh->lifetime - 2, 0);
|
||||
ipv6_route_add_metric(neigh->ip_address, 128, cur_interface->id, neigh->ip_address, ROUTE_ARO, NULL, 0, neigh->lifetime - 2, 32);
|
||||
|
||||
/* We need to know peer is a host before publishing - this needs MLE. Not yet established
|
||||
* what to do without MLE - might need special external/non-external prioritisation at root.
|
||||
|
@ -864,19 +866,19 @@ static void nd_update_registration(protocol_interface_info_entry_t *cur_interfac
|
|||
neigh->type = IP_NEIGHBOUR_TENTATIVE;
|
||||
neigh->lifetime = 2;
|
||||
ipv6_neighbour_set_state(&cur_interface->ipv6_neighbour_cache, neigh, IP_NEIGHBOUR_STALE);
|
||||
ipv6_route_add(neigh->ip_address, 128, cur_interface->id, NULL, ROUTE_ARO, 4, 0);
|
||||
ipv6_route_add_metric(neigh->ip_address, 128, cur_interface->id, neigh->ip_address, ROUTE_ARO, NULL, 0, 4, 32);
|
||||
rpl_control_unpublish_address(protocol_6lowpan_rpl_domain, neigh->ip_address);
|
||||
}
|
||||
}
|
||||
|
||||
void nd_remove_registration(protocol_interface_info_entry_t *cur_interface, addrtype_t ll_type, const uint8_t *ll_address)
|
||||
{
|
||||
|
||||
ns_list_foreach_safe(ipv6_neighbour_t, cur, &cur_interface->ipv6_neighbour_cache.list) {
|
||||
if ((cur->type == IP_NEIGHBOUR_REGISTERED
|
||||
|| cur->type == IP_NEIGHBOUR_TENTATIVE)
|
||||
&& ipv6_neighbour_ll_addr_match(cur, ll_type, ll_address)) {
|
||||
ipv6_route_delete(cur->ip_address, 128, cur_interface->id, NULL,
|
||||
|
||||
ipv6_route_delete(cur->ip_address, 128, cur_interface->id, cur->ip_address,
|
||||
ROUTE_ARO);
|
||||
ipv6_neighbour_entry_remove(&cur_interface->ipv6_neighbour_cache,
|
||||
cur);
|
||||
|
@ -923,6 +925,12 @@ bool nd_ns_aro_handler(protocol_interface_info_entry_t *cur_interface, const uin
|
|||
}
|
||||
|
||||
/* TODO - check hard upper limit on registrations? */
|
||||
if (ws_info(cur_interface) &&
|
||||
!ws_common_allow_child_registration(cur_interface)) {
|
||||
aro_out->present = true;
|
||||
aro_out->status = ARO_FULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We need to have entry in the Neighbour Cache */
|
||||
ipv6_neighbour_t *neigh = ipv6_neighbour_lookup_or_create(&cur_interface->ipv6_neighbour_cache, src_addr);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -22,7 +22,7 @@
|
|||
#include "string.h"
|
||||
#include "randLIB.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "Core/include/socket.h"
|
||||
#include "Core/include/ns_socket.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "6LoWPAN/NVM/nwk_nvm.h"
|
||||
|
|
|
@ -757,6 +757,7 @@ bool thread_bbr_routing_enabled(protocol_interface_info_entry_t *cur)
|
|||
|
||||
void thread_bbr_network_data_update_notify(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
(void)cur;
|
||||
thread_mdns_network_data_update_notify();
|
||||
thread_extension_bbr_route_update(cur);
|
||||
}
|
||||
|
@ -1000,6 +1001,7 @@ int thread_bbr_dua_entry_add(int8_t interface_id, const uint8_t *addr_data_ptr,
|
|||
// Route info autofreed
|
||||
route->info_autofree = true;
|
||||
}
|
||||
route->lifetime = lifetime; // update lifetime also from old route
|
||||
map = route->info.info;
|
||||
memcpy(map->mleid_ptr, mleid_ptr, 8);
|
||||
map->last_contact_time = protocol_core_monotonic_time;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -902,6 +902,7 @@ void thread_interface_init(protocol_interface_info_entry_t *cur)
|
|||
cur->if_snoop = thread_nd_snoop;
|
||||
cur->if_icmp_handler = thread_nd_icmp_handler;
|
||||
cur->ipv6_neighbour_cache.send_nud_probes = false;
|
||||
cur->ipv6_neighbour_cache.probe_avoided_routers = false;
|
||||
cur->ipv6_neighbour_cache.recv_addr_reg = true;
|
||||
cur->send_mld = false;
|
||||
cur->ip_multicast_as_mac_unicast_to_parent = true;
|
||||
|
@ -1514,6 +1515,7 @@ int thread_bootstrap_reset(protocol_interface_info_entry_t *cur)
|
|||
cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER;
|
||||
}
|
||||
cur->ipv6_neighbour_cache.send_nud_probes = false; //Disable NUD probing
|
||||
cur->ipv6_neighbour_cache.probe_avoided_routers = false;
|
||||
cur->ip_multicast_as_mac_unicast_to_parent = true;
|
||||
//Define Default Contexts
|
||||
if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
|
||||
|
@ -2726,7 +2728,7 @@ int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur)
|
|||
thread_border_router_network_data_update_notify(cur);
|
||||
thread_bbr_network_data_update_notify(cur);
|
||||
|
||||
thread_maintenance_timer_set(cur, THREAD_MAINTENANCE_TIMER_INTERVAL);
|
||||
thread_maintenance_timer_set(cur);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2846,7 +2848,7 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
|
|||
thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info);
|
||||
/* Do not allow multiple DHCP solicits from one prefix => delete previous */
|
||||
dhcp_client_global_address_delete(cur->id, NULL, curPrefix->servicesPrefix);
|
||||
if (dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) {
|
||||
if (dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, DHCPV6_DUID_HARDWARE_EUI64_TYPE, thread_dhcp_client_gua_error_cb) == 0) {
|
||||
tr_debug("GP Address Requested");
|
||||
}
|
||||
}
|
||||
|
@ -2856,8 +2858,8 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
|
|||
if ((cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST ||
|
||||
cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) &&
|
||||
cur->thread_info->requestFullNetworkData == false) {
|
||||
tr_debug("Invalidate router ID: %04x", curBorderRouter->routerID);
|
||||
curBorderRouter->routerID = 0xfffe;
|
||||
tr_debug("Invalidated router ID: %04x", curBorderRouter->routerID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2868,8 +2870,10 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
|
|||
}
|
||||
// generate address based on res1 bit
|
||||
if (curBorderRouter->P_res1) {
|
||||
if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) {
|
||||
thread_extension_dua_address_generate(cur, curPrefix->servicesPrefix, 64);
|
||||
}
|
||||
}
|
||||
|
||||
} // for each borderRouterList
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015, 2017-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2015, 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -88,7 +88,7 @@
|
|||
#include "6LoWPAN/MAC/mac_pairwise_key.h"
|
||||
#include "6LoWPAN/MAC/mac_data_poll.h"
|
||||
#include "Service_Libs/etx/etx.h"
|
||||
#include "Core/include/address.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
#include "6LoWPAN/Thread/thread_nvm_store.h"
|
||||
|
||||
#define TRACE_GROUP "thrd"
|
||||
|
@ -484,7 +484,9 @@ int thread_info_allocate_and_init(protocol_interface_info_entry_t *cur)
|
|||
cur->thread_info->version = thread_version; // Default implementation version
|
||||
cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_END_DEVICE;
|
||||
cur->thread_info->childUpdateReqTimer = -1;
|
||||
cur->thread_info->parent_priority = CONNECTIVITY_PP_INVALID; // default invalid - calculated using child count
|
||||
|
||||
thread_maintenance_timer_set(cur);
|
||||
thread_routing_init(&cur->thread_info->routing);
|
||||
thread_network_local_server_data_base_init(&cur->thread_info->localServerDataBase);
|
||||
memset(&cur->thread_info->registered_commissioner, 0, sizeof(thread_commissioner_t));
|
||||
|
@ -961,7 +963,9 @@ static void thread_maintenance_timer(protocol_interface_info_entry_t *cur, uint3
|
|||
}
|
||||
}
|
||||
|
||||
thread_info(cur)->thread_maintenance_timer = THREAD_MAINTENANCE_TIMER_INTERVAL ;
|
||||
thread_maintenance_timer_set(cur);
|
||||
|
||||
tr_debug("NWK data maintenance scan");
|
||||
|
||||
thread_bootstrap_network_data_activate(cur);
|
||||
}
|
||||
|
@ -1245,7 +1249,9 @@ uint8_t *thread_connectivity_tlv_write(uint8_t *ptr, protocol_interface_info_ent
|
|||
*ptr++ = 10;
|
||||
|
||||
// determine parent priority
|
||||
if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV && (3 * mle_class_rfd_entry_count_get(cur) > 2 * THREAD_MAX_MTD_CHILDREN)) {
|
||||
if ((thread->parent_priority & CONNECTIVITY_PP_MASK) != CONNECTIVITY_PP_INVALID) {
|
||||
*ptr++ = thread->parent_priority & CONNECTIVITY_PP_MASK;
|
||||
} else if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV && (3 * mle_class_rfd_entry_count_get(cur) > 2 * THREAD_MAX_MTD_CHILDREN)) {
|
||||
*ptr++ = CONNECTIVITY_PP_LOW;
|
||||
} else if (!(mode & MLE_RX_ON_IDLE) && (3 * mle_class_sleepy_entry_count_get(cur) > 2 * THREAD_MAX_SED_CHILDREN)) {
|
||||
*ptr++ = CONNECTIVITY_PP_LOW;
|
||||
|
@ -2155,9 +2161,9 @@ void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur,
|
|||
thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, neighbor_attribute_index);
|
||||
}
|
||||
|
||||
void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay)
|
||||
void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
thread_info(cur)->thread_maintenance_timer = delay;
|
||||
thread_info(cur)->thread_maintenance_timer = THREAD_MAINTENANCE_TIMER_INTERVAL + randLIB_get_random_in_range(0, THREAD_MAINTENANCE_TIMER_INTERVAL / 10);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -68,6 +68,7 @@ struct mac_neighbor_table_entry;
|
|||
#define THREAD_KEY_INDEX(seq) ((uint8_t) (((seq) & 0x0000007f) + 1))
|
||||
|
||||
extern uint8_t thread_version;
|
||||
extern uint8_t thread_max_mcast_addr;
|
||||
extern uint32_t thread_delay_timer_default;
|
||||
extern uint32_t thread_router_selection_jitter;
|
||||
extern uint16_t thread_joiner_port;
|
||||
|
@ -316,6 +317,7 @@ typedef struct thread_info_s {
|
|||
//uint8_t lastValidRouteMask[8];
|
||||
int8_t interface_id; //Thread Interface ID
|
||||
uint8_t version;
|
||||
uint8_t parent_priority;
|
||||
uint8_t testMaxActiveRouterIdLimit; //Default for this is 32
|
||||
uint8_t maxChildCount; //Default for this is 24
|
||||
uint8_t partition_weighting;
|
||||
|
@ -448,7 +450,7 @@ bool thread_partition_match(protocol_interface_info_entry_t *cur, thread_leader_
|
|||
void thread_partition_info_update(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData);
|
||||
void thread_neighbor_communication_update(protocol_interface_info_entry_t *cur, uint8_t neighbor_attribute_index);
|
||||
bool thread_stable_context_check(protocol_interface_info_entry_t *cur, buffer_t *buf);
|
||||
void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur, uint16_t delay);
|
||||
void thread_maintenance_timer_set(protocol_interface_info_entry_t *cur);
|
||||
#else // HAVE_THREAD
|
||||
|
||||
NS_DUMMY_DEFINITIONS_OK
|
||||
|
|
|
@ -247,7 +247,7 @@
|
|||
* value for better performance.
|
||||
*/
|
||||
#define THREAD_INDIRECT_BIG_PACKETS_TOTAL 10
|
||||
#define THREAD_INDIRECT_SMALL_PACKETS_PER_CHILD 2
|
||||
#define THREAD_INDIRECT_SMALL_PACKETS_PER_CHILD 3
|
||||
|
||||
/**
|
||||
* Maximum number of MTD children, default 16
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -186,4 +186,6 @@
|
|||
/** Thread prefix minimum lifetime in seconds */
|
||||
#define THREAD_MIN_PREFIX_LIFETIME 3600
|
||||
|
||||
#define THREAD_MCAST_ADDR_PER_MSG 4 // One multicast registration message fits 4 addresses by default
|
||||
|
||||
#endif /* THREAD_CONSTANTS_H_ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015, 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -73,7 +73,7 @@
|
|||
#include "Service_Libs/blacklist/blacklist.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "6LoWPAN/MAC/mac_data_poll.h"
|
||||
#include "Core/include/address.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
||||
|
||||
#define TRACE_GROUP "tebs"
|
||||
|
@ -470,8 +470,9 @@ static bool thread_host_prefer_parent_response(protocol_interface_info_entry_t *
|
|||
{
|
||||
(void) connectivity;
|
||||
(void) cur;
|
||||
bool cur_version = thread_extension_version_check(thread_info(cur)->version);
|
||||
|
||||
if (!thread_extension_version_check(thread_info(cur)->version)) {
|
||||
if (!cur_version) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -393,11 +393,6 @@ static int thread_leader_service_active_set_cb(int8_t service_id, uint8_t source
|
|||
|
||||
response_ptr = payload;
|
||||
|
||||
if (!thread_management_server_source_address_check(this->interface_id, source_address)) {
|
||||
response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
|
||||
goto send_error_response;
|
||||
}
|
||||
|
||||
if (3 <= thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_CHANNEL, &ptr) &&
|
||||
(linkConfiguration->rfChannel != common_read_16_bit(&ptr[1]) || linkConfiguration->channel_page != *ptr)) {
|
||||
tr_debug("Channel changed");
|
||||
|
@ -559,11 +554,6 @@ static int thread_leader_service_pending_set_cb(int8_t service_id, uint8_t sourc
|
|||
|
||||
tr_info("thread management Pending set");
|
||||
|
||||
if (!thread_management_server_source_address_check(this->interface_id, source_address)) {
|
||||
response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
|
||||
goto send_error_response;
|
||||
}
|
||||
|
||||
if (2 <= thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id)) {
|
||||
// Session id present must be valid
|
||||
if (cur->thread_info->registered_commissioner.session_id != session_id) {
|
||||
|
@ -660,7 +650,6 @@ send_error_response:
|
|||
static int thread_leader_service_commissioner_set_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
|
||||
{
|
||||
thread_leader_service_t *this = thread_leader_service_find_by_service(service_id);
|
||||
sn_coap_msg_code_e response_code = COAP_MSG_CODE_RESPONSE_CHANGED;
|
||||
uint16_t session_id;
|
||||
uint16_t br_locator;
|
||||
uint8_t payload[5]; // 4 + 1
|
||||
|
@ -682,10 +671,6 @@ static int thread_leader_service_commissioner_set_cb(int8_t service_id, uint8_t
|
|||
|
||||
tr_info("thread management commissioner set");
|
||||
|
||||
if (!thread_management_server_source_address_check(this->interface_id, source_address)) {
|
||||
response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
|
||||
goto send_error_response;
|
||||
}
|
||||
//Check if the CoAp payload is greater than maximum commissioner data size and reject
|
||||
if (request_ptr->payload_len > THREAD_MAX_COMMISSIONER_DATA_SIZE) {
|
||||
tr_error("Payload length greater than maximum commissioner data size");
|
||||
|
@ -725,9 +710,7 @@ static int thread_leader_service_commissioner_set_cb(int8_t service_id, uint8_t
|
|||
send_response:
|
||||
// build response
|
||||
ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, ret == 0 ? 1 : 0xff);
|
||||
|
||||
send_error_response:
|
||||
coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, response_code, COAP_CT_OCTET_STREAM, payload, ptr - payload);
|
||||
coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, payload, ptr - payload);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1050,7 +1033,6 @@ static int thread_leader_service_release_cb(int8_t service_id, uint8_t source_ad
|
|||
static int thread_leader_service_petition_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
|
||||
{
|
||||
thread_leader_service_t *this = thread_leader_service_find_by_service(service_id);
|
||||
sn_coap_msg_code_e response_code = COAP_MSG_CODE_RESPONSE_CHANGED;
|
||||
uint8_t payload[79];// max length for commissioner id is 64 + 4 byte header + 4 + 1 + 4 + 2
|
||||
uint8_t *ptr;
|
||||
uint16_t session_id = 0;
|
||||
|
@ -1067,11 +1049,6 @@ static int thread_leader_service_petition_cb(int8_t service_id, uint8_t source_a
|
|||
|
||||
tr_debug("Thread management commissioner petition");
|
||||
|
||||
if (!thread_management_server_source_address_check(this->interface_id, source_address)) {
|
||||
response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
|
||||
goto send_error_response;
|
||||
}
|
||||
|
||||
// save values from message
|
||||
tlv_length = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_ID, &tlv_data_ptr);
|
||||
|
||||
|
@ -1098,8 +1075,7 @@ static int thread_leader_service_petition_cb(int8_t service_id, uint8_t source_a
|
|||
|
||||
tr_debug("Petition req recv id %s, RESP session id: %d ret %d", commissioner_id_ptr ? commissioner_id_ptr : "(none)", session_id, ret);
|
||||
|
||||
send_error_response:
|
||||
coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, response_code, COAP_CT_OCTET_STREAM, payload, ptr - payload);
|
||||
coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, payload, ptr - payload);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1110,7 +1086,6 @@ send_error_response:
|
|||
static int thread_leader_service_petition_ka_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
|
||||
{
|
||||
thread_leader_service_t *this = thread_leader_service_find_by_service(service_id);
|
||||
sn_coap_msg_code_e response_code = COAP_MSG_CODE_RESPONSE_CHANGED;
|
||||
uint8_t payload[5]; //status 4 + 1
|
||||
uint8_t *ptr;
|
||||
uint16_t session_id = 0;
|
||||
|
@ -1125,12 +1100,6 @@ static int thread_leader_service_petition_ka_cb(int8_t service_id, uint8_t sourc
|
|||
|
||||
tr_debug("Thread management commissioner keep alive");
|
||||
|
||||
if (!thread_management_server_source_address_check(this->interface_id, source_address)) {
|
||||
response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
|
||||
ptr = payload;
|
||||
goto send_error_response;
|
||||
}
|
||||
|
||||
if (2 <= thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &ptr)) {
|
||||
session_id = common_read_16_bit(ptr);
|
||||
}
|
||||
|
@ -1149,8 +1118,7 @@ static int thread_leader_service_petition_ka_cb(int8_t service_id, uint8_t sourc
|
|||
ptr = payload;
|
||||
ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, state == true ? 1 : 0xff);
|
||||
|
||||
send_error_response:
|
||||
coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, response_code, COAP_CT_OCTET_STREAM, payload, ptr - payload);
|
||||
coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, payload, ptr - payload);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -94,6 +94,7 @@ static const uint8_t thread_discovery_extented_address[8] = {0x35, 0x06, 0xfe, 0
|
|||
uint32_t thread_delay_timer_default = THREAD_DELAY_TIMER_DEFAULT_SECONDS;
|
||||
uint32_t thread_router_selection_jitter = THREAD_ROUTER_SELECTION_JITTER;
|
||||
uint16_t thread_joiner_port = THREAD_DEFAULT_JOINER_PORT;
|
||||
uint8_t thread_max_mcast_addr = THREAD_MCAST_ADDR_PER_MSG;
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
|
@ -1345,6 +1346,11 @@ int8_t thread_management_get_request_full_nwk_data(int8_t interface_id, bool *fu
|
|||
|
||||
int thread_management_device_certificate_set(int8_t interface_id, const unsigned char *device_certificate_ptr, uint16_t device_certificate_len, const unsigned char *priv_key_ptr, uint16_t priv_key_len)
|
||||
{
|
||||
(void) device_certificate_ptr;
|
||||
(void) device_certificate_len;
|
||||
(void) priv_key_ptr;
|
||||
(void) priv_key_len;
|
||||
|
||||
#ifdef HAVE_THREAD
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
|
@ -1358,17 +1364,19 @@ int thread_management_device_certificate_set(int8_t interface_id, const unsigned
|
|||
|
||||
#else
|
||||
(void) interface_id;
|
||||
(void) device_certificate_ptr;
|
||||
(void) device_certificate_len;
|
||||
(void) priv_key_ptr;
|
||||
(void) priv_key_len;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
int thread_management_network_certificate_set(int8_t interface_id, const unsigned char *network_certificate_ptr, uint16_t network_certificate_len, const unsigned char *priv_key_ptr, uint16_t priv_key_len)
|
||||
{
|
||||
(void) network_certificate_ptr;
|
||||
(void) network_certificate_len;
|
||||
(void) priv_key_ptr;
|
||||
(void) priv_key_len;
|
||||
|
||||
#ifdef HAVE_THREAD
|
||||
protocol_interface_info_entry_t *cur;
|
||||
int ret_val;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur) {
|
||||
|
@ -1376,17 +1384,14 @@ int thread_management_network_certificate_set(int8_t interface_id, const unsigne
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (0 > thread_extension_bootstrap_network_certificate_set(cur, network_certificate_ptr, network_certificate_len)) {
|
||||
ret_val = thread_extension_bootstrap_network_certificate_set(cur, network_certificate_ptr, network_certificate_len);
|
||||
if (0 > ret_val) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return thread_extension_bootstrap_network_private_key_set(cur, priv_key_ptr, priv_key_len);
|
||||
#else
|
||||
(void) interface_id;
|
||||
(void) network_certificate_ptr;
|
||||
(void) network_certificate_len;
|
||||
(void) priv_key_ptr;
|
||||
(void) priv_key_len;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -66,10 +66,19 @@
|
|||
#include "thread_management_server.h"
|
||||
#include "mac_api.h"
|
||||
#include "6LoWPAN/MAC/mac_data_poll.h"
|
||||
#include "Common_Protocols/ipv6_constants.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
#include "mlme.h"
|
||||
|
||||
#ifdef HAVE_THREAD
|
||||
|
||||
//#define TRACE_DEEP
|
||||
#ifdef TRACE_DEEP
|
||||
#define tr_deep tr_debug
|
||||
#else
|
||||
#define tr_deep(...)
|
||||
#endif
|
||||
|
||||
typedef struct scan_query {
|
||||
int8_t coap_service_id;
|
||||
uint8_t channel_mask[6]; //<!** first byte is channel page
|
||||
|
@ -393,6 +402,7 @@ send_response:
|
|||
static int thread_management_server_get_command_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
|
||||
{
|
||||
(void) source_port;
|
||||
(void) source_address;
|
||||
|
||||
thread_management_server_t *this = thread_management_find_by_service(service_id);
|
||||
|
||||
|
@ -400,12 +410,6 @@ static int thread_management_server_get_command_cb(int8_t service_id, uint8_t so
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!thread_management_server_source_address_check(this->interface_id, source_address)) {
|
||||
// request is coming from illegal address, return error immediately
|
||||
coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_BAD_REQUEST, COAP_CT_OCTET_STREAM, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return thread_management_server_tmf_get_request_handler(this->interface_id, service_id, request_ptr);
|
||||
|
||||
}
|
||||
|
@ -416,7 +420,6 @@ static int thread_management_server_commissioner_get_cb(int8_t service_id, uint8
|
|||
(void) source_port;
|
||||
protocol_interface_info_entry_t *cur;
|
||||
thread_management_server_t *this = thread_management_find_by_service(service_id);
|
||||
sn_coap_msg_code_e return_code = COAP_MSG_CODE_RESPONSE_CHANGED;
|
||||
uint8_t response_msg[2 + 2 + 2 + 2 + 2 + 16 + 2 + 2];
|
||||
uint8_t *request_tlv_ptr = NULL;
|
||||
uint16_t request_tlv_len;
|
||||
|
@ -432,11 +435,6 @@ static int thread_management_server_commissioner_get_cb(int8_t service_id, uint8
|
|||
}
|
||||
payload_ptr = ptr = response_msg;
|
||||
|
||||
if (!thread_management_server_source_address_check(this->interface_id, source_address)) {
|
||||
return_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
|
||||
goto send_response;
|
||||
}
|
||||
|
||||
if (!cur->thread_info->registered_commissioner.commissioner_valid) {
|
||||
//Error in message is responded with Thread status or if we have access rights problem
|
||||
tr_warn("No registered commissioner");
|
||||
|
@ -464,7 +462,7 @@ static int thread_management_server_commissioner_get_cb(int8_t service_id, uint8
|
|||
goto send_response;
|
||||
}
|
||||
send_response:
|
||||
coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, return_code, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr);
|
||||
coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1118,6 +1116,58 @@ error_exit:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int coap_msg_prevalidate_cb(int8_t local_interface_id, uint8_t local_address[static 16], uint16_t local_port, int8_t recv_interface_id, uint8_t source_address[static 16], uint16_t source_port, char *coap_uri)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur_local, *cur_source;
|
||||
uint_fast8_t addr_scope;
|
||||
|
||||
(void) source_address;
|
||||
(void) source_port;
|
||||
(void) coap_uri;
|
||||
|
||||
cur_local = protocol_stack_interface_info_get_by_id(local_interface_id);
|
||||
|
||||
if (!cur_local) {
|
||||
tr_error("No interface for %d", local_interface_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (local_port != THREAD_MANAGEMENT_PORT) {
|
||||
// Message not sent to THREAD_MANAGEMENT_PORT, let it come through
|
||||
tr_deep("Message %s port %d is not mgmt port", coap_uri, local_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check message source address
|
||||
if (!thread_management_server_source_address_check(local_interface_id, source_address)) {
|
||||
tr_deep("Drop CoAP msg %s from %s", coap_uri, trace_ipv6(source_address));
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* check our local address scope */
|
||||
addr_scope = addr_ipv6_scope(local_address, cur_local);
|
||||
if (addr_scope > IPV6_SCOPE_REALM_LOCAL) {
|
||||
tr_deep("Drop CoAP msg %s to %s due %d", coap_uri, trace_ipv6(local_address), addr_scope);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (local_interface_id != recv_interface_id) {
|
||||
// message received from different interface
|
||||
cur_source = protocol_stack_interface_info_get_by_id(recv_interface_id);
|
||||
if (!cur_source) {
|
||||
tr_deep("No cur for if %d", recv_interface_id);
|
||||
return -1;
|
||||
}
|
||||
addr_scope = addr_ipv6_scope(source_address, cur_source);
|
||||
if (addr_scope < IPV6_SCOPE_REALM_LOCAL) {
|
||||
tr_deep("Drop CoAP msg %s from %s to %s due %d", coap_uri, trace_ipv6(source_address), trace_ipv6(local_address), addr_scope);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public interface functions
|
||||
*/
|
||||
|
@ -1162,6 +1212,7 @@ int thread_management_server_init(int8_t interface_id)
|
|||
ns_dyn_mem_free(this);
|
||||
return -3;
|
||||
}
|
||||
coap_service_msg_prevalidate_callback_set(THREAD_MANAGEMENT_PORT, coap_msg_prevalidate_cb);
|
||||
#ifdef HAVE_THREAD_ROUTER
|
||||
if (thread_leader_service_init(interface_id, this->coap_service_id) != 0) {
|
||||
tr_error("Thread leader service init failed");
|
||||
|
@ -1554,10 +1605,15 @@ int thread_management_server_commisoner_data_get(int8_t interface_id, thread_man
|
|||
bool thread_management_server_source_address_check(int8_t interface_id, uint8_t source_address[16])
|
||||
{
|
||||
link_configuration_s *linkConfiguration;
|
||||
linkConfiguration = thread_joiner_application_get_config(interface_id);
|
||||
|
||||
if (memcmp(ADDR_LINK_LOCAL_PREFIX, source_address, 8) == 0) {
|
||||
// Source address is from Link local address
|
||||
return true;
|
||||
}
|
||||
|
||||
linkConfiguration = thread_joiner_application_get_config(interface_id);
|
||||
if (!linkConfiguration) {
|
||||
tr_error("No link configuration.");
|
||||
tr_error("No link cfg for if %d", interface_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1566,15 +1622,12 @@ bool thread_management_server_source_address_check(int8_t interface_id, uint8_t
|
|||
// Source address is RLOC or ALOC
|
||||
} else if (memcmp(source_address, linkConfiguration->mesh_local_ula_prefix, 8) == 0) {
|
||||
// Source address is ML64 TODO this should check that destination address is ALOC or RLOC CoaP Service does not support
|
||||
} else if (memcmp(ADDR_LINK_LOCAL_PREFIX, source_address, 8)) {
|
||||
// Source address is from Link local address
|
||||
} else {
|
||||
tr_error("Message out of thread network; ML prefix: %s, src addr: %s",
|
||||
tr_deep("Message out of thread network; ML prefix: %s, src addr: %s",
|
||||
trace_ipv6_prefix(linkConfiguration->mesh_local_ula_prefix, 64),
|
||||
trace_ipv6(source_address));
|
||||
return false;
|
||||
}
|
||||
// TODO: Add other (security) related checks here
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -42,7 +42,7 @@
|
|||
#include "eventOS_event.h"
|
||||
#include "common_functions.h"
|
||||
#include "socket_api.h"
|
||||
#include "Core/include/socket.h"
|
||||
#include "Core/include/ns_socket.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "Common_Protocols/ipv6.h"
|
||||
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
|
||||
|
@ -213,6 +213,7 @@ static mac_neighbor_table_entry_t *thread_nd_child_mleid_get(protocol_interface_
|
|||
|
||||
static int thread_nd_address_query_lookup(int8_t interface_id, const uint8_t target_addr[static 16], uint16_t *rloc, uint16_t *addr_out, bool *proxy, uint32_t *last_transaction_time, uint8_t *mleid_ptr)
|
||||
{
|
||||
(void) rloc;
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur) {
|
||||
return -1;
|
||||
|
|
|
@ -1565,14 +1565,12 @@ int thread_nd_local_list_add_service(thread_network_data_cache_entry_t *networkD
|
|||
*/
|
||||
int thread_nd_local_list_add_on_mesh_prefix(thread_network_data_cache_entry_t *networkDataList, thread_prefix_tlv_t *prefixTlv, thread_border_router_tlv_entry_t *service)
|
||||
{
|
||||
bool trigDataPropagate = false;
|
||||
thread_network_data_prefix_cache_entry_t *prefix_entry;
|
||||
thread_network_server_data_entry_t *server_entry;
|
||||
if (service->P_dhcp) {
|
||||
tr_debug("Add DHCPv6 prefix:%s server: %04x", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen), service->routerID);
|
||||
} else {
|
||||
tr_debug("Add SLAAC prefix:%s server: %04x", trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen), service->routerID);
|
||||
}
|
||||
bool trigDataPropagate = false;
|
||||
|
||||
tr_debug("Add %s%s%s prefix:%s server: %04x", service->P_dhcp ? "DHCPv6" : "", service->P_slaac ? "SLAAC " : "", service->P_res1 ? "P_res1 " : "",
|
||||
trace_ipv6_prefix(prefixTlv->Prefix, prefixTlv->PrefixLen), service->routerID);
|
||||
|
||||
if (!networkDataList) {
|
||||
return -1;
|
||||
|
@ -1634,6 +1632,10 @@ int thread_nd_local_list_add_on_mesh_prefix(thread_network_data_cache_entry_t *n
|
|||
trigDataPropagate = true;
|
||||
}
|
||||
|
||||
if (server_entry->P_res1 != service->P_res1) {
|
||||
server_entry->P_res1 = service->P_res1;
|
||||
trigDataPropagate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (trigDataPropagate) {
|
||||
|
@ -1647,7 +1649,6 @@ int thread_nd_local_list_add_on_mesh_prefix(thread_network_data_cache_entry_t *n
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Del DHCPv6 Server information to route List
|
||||
*
|
||||
|
@ -1671,13 +1672,8 @@ int thread_nd_local_list_del_on_mesh_server(thread_network_data_cache_entry_t *n
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (service->P_dhcp) {
|
||||
tr_debug("Del DHCPv6 server: %s",
|
||||
tr_debug("Del %s%s%s prefix: %s", service->P_dhcp ? "DHCPv6" : "", service->P_slaac ? "SLAAC " : "", service->P_res1 ? "P_res1 " : "",
|
||||
trace_array(prefixTlv->Prefix, prefixBits_to_bytes(prefixTlv->PrefixLen)));
|
||||
} else {
|
||||
tr_debug("Del SLAAC server: %s",
|
||||
trace_array(prefixTlv->Prefix, prefixBits_to_bytes(prefixTlv->PrefixLen)));
|
||||
}
|
||||
|
||||
main_list = thread_prefix_entry_get(&networkDataList->localPrefixList, prefixTlv);
|
||||
if (!main_list) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2017-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -35,7 +35,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "Core/include/address.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
#include "ns_file_system.h"
|
||||
#include "thread_config.h"
|
||||
#include "thread_common.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2017, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -33,7 +33,7 @@
|
|||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "Core/include/address.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
#include "thread_tmfcop_lib.h"
|
||||
|
||||
#include "coap_service_api.h"
|
||||
|
@ -293,9 +293,14 @@ void thread_resolution_client_init(int8_t interface_id)
|
|||
this->interface_id = interface_id;
|
||||
this->notification_cb_ptr = NULL;
|
||||
this->error_cb_ptr = NULL;
|
||||
ns_list_init(&this->queries);
|
||||
//TODO: Check if to use ephemeral port here
|
||||
this->coap_service_id = thread_management_server_service_id_get(interface_id);
|
||||
if (this->coap_service_id < 0) {
|
||||
tr_err("Thread resolution client init failed");
|
||||
ns_dyn_mem_free(this);
|
||||
return;
|
||||
}
|
||||
ns_list_init(&this->queries);
|
||||
ns_list_add_to_start(&instance_list, this);
|
||||
|
||||
coap_service_register_uri(this->coap_service_id, THREAD_URI_ADDRESS_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_resolution_client_notification_post_cb);
|
||||
|
|
|
@ -173,7 +173,7 @@ int thread_resolution_server_init(int8_t interface_id, thread_resolution_server_
|
|||
this->interface_id = interface_id;
|
||||
this->coap_service_id = thread_management_server_service_id_get(interface_id);
|
||||
if (this->coap_service_id < 0) {
|
||||
tr_warn("Thread resolution srv init failed");
|
||||
tr_err("Thread resolution srv init failed");
|
||||
ns_dyn_mem_free(this);
|
||||
return -3;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2015-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -83,7 +83,7 @@
|
|||
#include "mac_api.h"
|
||||
#include "6LoWPAN/MAC/mac_data_poll.h"
|
||||
#include "thread_border_router_api.h"
|
||||
#include "Core/include/address.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
||||
|
||||
#ifdef HAVE_THREAD_ROUTER
|
||||
|
@ -1407,6 +1407,7 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le
|
|||
//Register GP --> 16
|
||||
int retVal = thread_nd_address_registration(cur, tempIPv6Address, mac16, cur->mac_parameters->pan_id, mac64, &new_neighbour_created);
|
||||
thread_extension_address_registration(cur, tempIPv6Address, mac64, new_neighbour_created, retVal == -2);
|
||||
(void) retVal;
|
||||
} else {
|
||||
tr_debug("No Context %u", ctxId);
|
||||
}
|
||||
|
@ -1427,6 +1428,7 @@ static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_le
|
|||
//Register GP --> 16
|
||||
int retVal = thread_nd_address_registration(cur, ptr, mac16, cur->mac_parameters->pan_id, mac64, &new_neighbour_created);
|
||||
thread_extension_address_registration(cur, ptr, mac64, new_neighbour_created, retVal == -2);
|
||||
(void) retVal;
|
||||
}
|
||||
|
||||
ptr += 16;
|
||||
|
@ -1809,6 +1811,11 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
|
|||
update_mac_mib = true;
|
||||
entry_temp->mac16 = shortAddress; // short address refreshed
|
||||
|
||||
if (thread_is_router_addr(shortAddress)) {
|
||||
// Set full data as REED/Router needs full data (SED will not make links)
|
||||
thread_neighbor_class_request_full_data_setup_set(&cur->thread_info->neighbor_class, entry_temp->index, true);
|
||||
}
|
||||
|
||||
if (entry_temp->connected_device) {
|
||||
if (mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisteredTlv)) {
|
||||
if (!entry_temp->ffd_device) {
|
||||
|
@ -1942,9 +1949,9 @@ void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *
|
|||
uint32_t timeout = 0;
|
||||
uint64_t active_timestamp = 0;
|
||||
uint64_t pending_timestamp = 0;
|
||||
mle_tlv_info_t addressRegisterTlv = {0};
|
||||
mle_tlv_info_t challengeTlv = {0};
|
||||
mle_tlv_info_t tlv_req = {0};
|
||||
mle_tlv_info_t addressRegisterTlv = {MLE_TYPE_SRC_ADDRESS, 0, 0};
|
||||
mle_tlv_info_t challengeTlv = {MLE_TYPE_SRC_ADDRESS, 0, 0};
|
||||
mle_tlv_info_t tlv_req = {MLE_TYPE_SRC_ADDRESS, 0, 0};
|
||||
entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
|
||||
|
||||
if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status)) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2014-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -634,6 +634,7 @@ int thread_test_version_set(int8_t interface_id, uint8_t version)
|
|||
return 0;
|
||||
|
||||
#else
|
||||
(void)version;
|
||||
(void)interface_id;
|
||||
return -1;
|
||||
#endif
|
||||
|
@ -1269,6 +1270,23 @@ int8_t thread_test_joiner_router_joiner_port_set(uint16_t port)
|
|||
|
||||
}
|
||||
|
||||
int8_t thread_test_mcast_address_per_message_set(uint8_t value)
|
||||
{
|
||||
#ifdef HAVE_THREAD
|
||||
if (value == 0 || value > 15) {
|
||||
tr_err("Value not in range. Valid range 1-15");
|
||||
return -1;
|
||||
}
|
||||
|
||||
thread_max_mcast_addr = value;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
(void)value;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int thread_test_mle_message_send(int8_t interface_id, uint8_t *dst_address, uint8_t msg_id, bool write_src_addr, bool write_leader_data, bool write_network_data, bool write_timestamp, bool write_operational_set, bool write_challenge, uint8_t *msg_ptr, uint8_t msg_len)
|
||||
{
|
||||
#ifdef HAVE_THREAD
|
||||
|
@ -1341,6 +1359,8 @@ int thread_test_mle_message_send(int8_t interface_id, uint8_t *dst_address, uint
|
|||
(void)msg_id;
|
||||
(void)write_src_addr;
|
||||
(void)write_leader_data;
|
||||
(void)write_network_data;
|
||||
(void)write_timestamp;
|
||||
(void)write_operational_set;
|
||||
(void)write_challenge;
|
||||
(void)msg_ptr;
|
||||
|
@ -1367,3 +1387,27 @@ int thread_test_extension_name_set(int8_t interface_id, char extension_name[16])
|
|||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int thread_test_parent_priority_set(int8_t interface_id, uint8_t parent_priority)
|
||||
{
|
||||
#ifdef HAVE_THREAD
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur) {
|
||||
tr_warn("Invalid interface id");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!cur->thread_info) {
|
||||
tr_warn("Not Thread specific interface");
|
||||
return -2;
|
||||
}
|
||||
cur->thread_info->parent_priority = parent_priority;
|
||||
return 0;
|
||||
#else
|
||||
(void) interface_id;
|
||||
(void) parent_priority;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -23,8 +23,8 @@
|
|||
#include "ns_list.h"
|
||||
#include "randLIB.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "Core/include/address.h"
|
||||
#include "Core/include/socket.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
#include "Core/include/ns_socket.h"
|
||||
#include "mac_api.h"
|
||||
#include "mac_mcps.h"
|
||||
#include "mac_common_defines.h"
|
||||
|
@ -40,6 +40,8 @@
|
|||
#include "6LoWPAN/IPHC_Decode/iphc_decompress.h"
|
||||
#include "lowpan_adaptation_interface.h"
|
||||
#include "MLE/mle.h"
|
||||
#include "Service_Libs/mle_service/mle_service_api.h"
|
||||
#include "Common_Protocols/icmpv6.h"
|
||||
#ifdef HAVE_RPL
|
||||
#include "RPL/rpl_data.h"
|
||||
#endif
|
||||
|
@ -787,49 +789,112 @@ static fragmenter_tx_entry_t *lowpan_adaptation_indirect_first_cached_request_ge
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void lowpan_adaptation_make_room_for_small_packet(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, mac_neighbor_table_entry_t *neighbour_to_count)
|
||||
static bool lowpan_adaptation_is_priority_message(buffer_t *buf)
|
||||
{
|
||||
// Mle messages
|
||||
if (buf->dst_sa.port == MLE_ALLOCATED_PORT || buf->src_sa.port == MLE_ALLOCATED_PORT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Management messages: address solicit, response, query, notification
|
||||
if (buf->dst_sa.port == THREAD_MANAGEMENT_PORT || buf->src_sa.port == THREAD_MANAGEMENT_PORT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// dhcp messages
|
||||
if (buf->dst_sa.port == DHCPV6_SERVER_PORT || buf->src_sa.port == DHCPV6_SERVER_PORT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (buf->dst_sa.port == DHCPV6_CLIENT_PORT || buf->src_sa.port == DHCPV6_CLIENT_PORT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ICMPv6 messages
|
||||
if (buf->options.type == ICMPV6_TYPE_ERROR_DESTINATION_UNREACH ||
|
||||
buf->options.type == ICMPV6_TYPE_ERROR_PACKET_TOO_BIG ||
|
||||
buf->options.type == ICMPV6_TYPE_ERROR_TIME_EXCEEDED ||
|
||||
buf->options.type == ICMPV6_TYPE_ERROR_PARAMETER_PROBLEM) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool lowpan_adaptation_make_room_for_small_packet(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, mac_neighbor_table_entry_t *neighbour_to_count, fragmenter_tx_entry_t *new_entry)
|
||||
{
|
||||
if (interface_ptr->max_indirect_small_packets_per_child == 0) {
|
||||
return;
|
||||
// this means there is always space for small packets - no need to check further
|
||||
return true;
|
||||
}
|
||||
|
||||
uint_fast16_t count = 0;
|
||||
fragmenter_tx_entry_t *low_priority_msg_ptr = NULL;
|
||||
|
||||
ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) {
|
||||
mac_neighbor_table_entry_t *tx_neighbour = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tx_entry->buf->dst_sa.address + 2, tx_entry->buf->dst_sa.addr_type);
|
||||
if (tx_neighbour == neighbour_to_count && buffer_data_length(tx_entry->buf) <= interface_ptr->indirect_big_packet_threshold) {
|
||||
if (!lowpan_adaptation_is_priority_message(tx_entry->buf)) {
|
||||
// if there is sub priorities inside message example age here you could compare
|
||||
low_priority_msg_ptr = tx_entry;
|
||||
}
|
||||
if (++count >= interface_ptr->max_indirect_small_packets_per_child) {
|
||||
tr_debug_extra("Purge seq: %d", tx_entry->buf->seq);
|
||||
if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry) == false) {
|
||||
if (!low_priority_msg_ptr) {
|
||||
// take last entry if no low priority entry found
|
||||
if (lowpan_adaptation_is_priority_message(new_entry->buf)) {
|
||||
low_priority_msg_ptr = tx_entry;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
tr_debug_extra("Purge seq: %d", low_priority_msg_ptr->buf->seq);
|
||||
if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, low_priority_msg_ptr) == false) {
|
||||
/* entry could not be purged from mac, try next entry */
|
||||
tr_debug_extra("Purge failed, try next");
|
||||
count--;
|
||||
}
|
||||
low_priority_msg_ptr = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lowpan_adaptation_make_room_for_big_packet(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr)
|
||||
static bool lowpan_adaptation_make_room_for_big_packet(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *new_entry)
|
||||
{
|
||||
if (interface_ptr->max_indirect_big_packets_total == 0) {
|
||||
return;
|
||||
// this means there is always space for big packets - no need to check further
|
||||
return true;
|
||||
}
|
||||
|
||||
uint_fast16_t count = 0;
|
||||
fragmenter_tx_entry_t *low_priority_msg_ptr = NULL;
|
||||
|
||||
ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) {
|
||||
if (buffer_data_length(tx_entry->buf) > interface_ptr->indirect_big_packet_threshold) {
|
||||
if (!lowpan_adaptation_is_priority_message(tx_entry->buf)) {
|
||||
// if there is sub priorities inside message example age here you could compare
|
||||
low_priority_msg_ptr = tx_entry;
|
||||
}
|
||||
if (++count >= interface_ptr->max_indirect_big_packets_total) {
|
||||
tr_debug_extra("Purge seq: %d", tx_entry->buf->seq);
|
||||
if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry) == false) {
|
||||
tr_debug("Purge failed, try next entry");
|
||||
if (!low_priority_msg_ptr) {
|
||||
// take last entry if no low priority entry found
|
||||
if (lowpan_adaptation_is_priority_message(new_entry->buf)) {
|
||||
low_priority_msg_ptr = tx_entry;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
tr_debug_extra("Purge seq: %d", low_priority_msg_ptr->buf->seq);
|
||||
if (lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, low_priority_msg_ptr) == false) {
|
||||
tr_debug_extra("Purge failed, try next entry");
|
||||
/* entry could not be purged from mac, try next entry */
|
||||
count--;
|
||||
}
|
||||
low_priority_msg_ptr = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_tx_entry_t *tx_ptr, fragmenter_interface_t *interface_ptr)
|
||||
|
@ -868,6 +933,7 @@ static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buf
|
|||
|
||||
int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buffer_t *buf)
|
||||
{
|
||||
bool is_room_for_new_message;
|
||||
if (!buf) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -940,9 +1006,9 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
|
|||
|
||||
// Make room for new message if needed */
|
||||
if (buffer_data_length(buf) <= interface_ptr->indirect_big_packet_threshold) {
|
||||
lowpan_adaptation_make_room_for_small_packet(cur, interface_ptr, neigh_entry_ptr);
|
||||
is_room_for_new_message = lowpan_adaptation_make_room_for_small_packet(cur, interface_ptr, neigh_entry_ptr, tx_ptr);
|
||||
} else {
|
||||
lowpan_adaptation_make_room_for_big_packet(cur, interface_ptr);
|
||||
is_room_for_new_message = lowpan_adaptation_make_room_for_big_packet(cur, interface_ptr, tx_ptr);
|
||||
}
|
||||
|
||||
if (lowpan_adaptation_indirect_mac_data_request_active(interface_ptr, tx_ptr)) {
|
||||
|
@ -951,7 +1017,15 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
|
|||
tx_ptr->indirect_data_cached = true;
|
||||
}
|
||||
|
||||
if (is_room_for_new_message) {
|
||||
ns_list_add_to_end(&interface_ptr->indirect_tx_queue, tx_ptr);
|
||||
} else {
|
||||
if (tx_ptr->fragmenter_buf) {
|
||||
ns_dyn_mem_free(tx_ptr->fragmenter_buf);
|
||||
}
|
||||
ns_dyn_mem_free(tx_ptr);
|
||||
goto tx_error_handler;
|
||||
}
|
||||
|
||||
// Check if current message can be delivered to MAC or should some cached message be delivered first
|
||||
tx_ptr_cached = lowpan_adaptation_indirect_first_cached_request_get(interface_ptr, tx_ptr);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2016-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -17,7 +17,7 @@
|
|||
|
||||
#ifndef LOWPAN_ADAPTATION_INTERFACE_H_
|
||||
#define LOWPAN_ADAPTATION_INTERFACE_H_
|
||||
#include "Core/include/address.h"
|
||||
#include "Core/include/ns_address_internal.h"
|
||||
|
||||
struct protocol_interface_info_entry;
|
||||
struct mcps_data_conf_s;
|
||||
|
|
|
@ -0,0 +1,488 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "nsconfig.h"
|
||||
#include "ns_types.h"
|
||||
#include "ns_trace.h"
|
||||
#include "net_interface.h"
|
||||
#include "eventOS_event.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
|
||||
#include "6LoWPAN/Bootstraps/protocol_6lowpan_interface.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_common.h"
|
||||
#include "6LoWPAN/ws/ws_bootstrap.h"
|
||||
#include "RPL/rpl_control.h"
|
||||
#include "RPL/rpl_data.h"
|
||||
#include "Common_Protocols/icmpv6.h"
|
||||
#include "Common_Protocols/icmpv6_radv.h"
|
||||
#include "ws_management_api.h"
|
||||
#include "net_rpl.h"
|
||||
#include "Service_Libs/nd_proxy/nd_proxy.h"
|
||||
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
|
||||
#include "DHCPv6_Server/DHCPv6_server_service.h"
|
||||
|
||||
#define TRACE_GROUP "wsbs"
|
||||
|
||||
#define RPL_INSTANCE_ID 1
|
||||
|
||||
#ifdef HAVE_WS_BORDER_ROUTER
|
||||
|
||||
|
||||
/* when creating BBR make ULA dodag ID always and when network becomes available add prefix to DHCP
|
||||
*
|
||||
*
|
||||
*/
|
||||
static int8_t backbone_interface_id = -1; // BBR backbone information
|
||||
|
||||
static uint8_t static_dodag_prefix[8] = {0xfd, 0x00, 0x61, 0x72, 0x6d};
|
||||
static uint8_t static_ula_address[16] = {0};
|
||||
static uint8_t static_dodag_id[16] = {0};
|
||||
static uint8_t global_dodag_id[16] = {0};
|
||||
static uint32_t bbr_delay_timer = 20; // initial delay.
|
||||
|
||||
static rpl_dodag_conf_t rpl_conf = {
|
||||
// Lifetime values
|
||||
.default_lifetime = 120,
|
||||
.lifetime_unit = 60,
|
||||
.objective_code_point = 1, // MRHOF algorithm used
|
||||
.authentication = 0,
|
||||
.path_control_size = 7,
|
||||
.dag_max_rank_increase = 2048,
|
||||
.min_hop_rank_increase = 256,
|
||||
// DIO configuration
|
||||
.dio_interval_min = WS_RPL_DIO_IMIN,
|
||||
.dio_interval_doublings = WS_RPL_DIO_DOUBLING,
|
||||
.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY
|
||||
};
|
||||
|
||||
void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy)
|
||||
{
|
||||
if (imin == 0 || doubling == 0) {
|
||||
// use default values
|
||||
imin = WS_RPL_DIO_IMIN;
|
||||
doubling = WS_RPL_DIO_DOUBLING;
|
||||
redundancy = WS_RPL_DIO_REDUNDANCY;
|
||||
}
|
||||
if (rpl_conf.dio_interval_min == imin &&
|
||||
rpl_conf.dio_interval_doublings == doubling &&
|
||||
rpl_conf.dio_redundancy_constant == redundancy) {
|
||||
// Same values no update needed
|
||||
return;
|
||||
}
|
||||
rpl_conf.dio_interval_min = imin;
|
||||
rpl_conf.dio_interval_doublings = doubling;
|
||||
rpl_conf.dio_redundancy_constant = redundancy;
|
||||
if (protocol_6lowpan_rpl_root_dodag) {
|
||||
rpl_control_update_dodag_config(protocol_6lowpan_rpl_root_dodag, &rpl_conf);
|
||||
rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_bbr_rpl_root_start(uint8_t *dodag_id)
|
||||
{
|
||||
tr_info("RPL root start");
|
||||
rpl_data_init_root();
|
||||
|
||||
if (protocol_6lowpan_rpl_root_dodag) {
|
||||
rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
|
||||
protocol_6lowpan_rpl_root_dodag = NULL;
|
||||
}
|
||||
|
||||
protocol_6lowpan_rpl_root_dodag = rpl_control_create_dodag_root(protocol_6lowpan_rpl_domain, RPL_INSTANCE_ID, dodag_id, &rpl_conf, rpl_conf.min_hop_rank_increase, RPL_GROUNDED | RPL_MODE_NON_STORING | RPL_DODAG_PREF(0));
|
||||
if (!protocol_6lowpan_rpl_root_dodag) {
|
||||
tr_err("RPL dodag init failed");
|
||||
return;
|
||||
}
|
||||
memcpy(static_dodag_id, dodag_id, 16);
|
||||
|
||||
// RPL memory limits set larger for Border router
|
||||
rpl_control_set_memory_limits(64 * 1024, 0);
|
||||
|
||||
uint8_t t_flags = PIO_A;
|
||||
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, dodag_id, 64, t_flags, 7200, 7200, false);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, dodag_id, 64, 0x18, 7200, false);
|
||||
}
|
||||
|
||||
static void ws_bbr_rpl_root_stop(void)
|
||||
{
|
||||
tr_info("RPL root stop");
|
||||
rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
|
||||
protocol_6lowpan_rpl_root_dodag = NULL;
|
||||
memset(static_ula_address, 0, 16);
|
||||
memset(static_dodag_id, 0, 16);
|
||||
memset(global_dodag_id, 0, 16);
|
||||
}
|
||||
|
||||
static int ws_border_router_proxy_validate(int8_t interface_id, uint8_t *address)
|
||||
{
|
||||
|
||||
/* Could also check route type, but I don't think it really matters */
|
||||
ipv6_route_t *route;
|
||||
route = ipv6_route_choose_next_hop(address, interface_id, NULL);
|
||||
if (!route || route->prefix_len < 128) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_border_router_proxy_state_update(int8_t caller_interface_id, int8_t handler_interface_id, bool status)
|
||||
{
|
||||
(void)caller_interface_id;
|
||||
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(handler_interface_id);
|
||||
if (!cur) {
|
||||
tr_error("No Interface");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
tr_debug("Border router Backhaul link ready");
|
||||
} else {
|
||||
tr_debug("Border router Backhaul link down");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ws_bbr_static_ula_create(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
if (memcmp(static_ula_address, ADDR_UNSPECIFIED, 16) != 0) {
|
||||
// address generated
|
||||
return 0;
|
||||
}
|
||||
tr_info("BBR generate ula prefix");
|
||||
|
||||
// This address is only used if no other address available.
|
||||
if_address_entry_t *add_entry = icmpv6_slaac_address_add(cur, static_dodag_prefix, 64, 0xffffffff, 0, true, SLAAC_IID_FIXED);
|
||||
if (!add_entry) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(static_ula_address, add_entry->address, 16);
|
||||
tr_info("BBR generate ula prefix addr %s", trace_ipv6(static_ula_address));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 0 static non rooted self generated own address
|
||||
* 1 static address with backbone connectivity
|
||||
*/
|
||||
static int ws_bbr_static_dodag_get(protocol_interface_info_entry_t *cur, uint8_t *dodag_id_ptr)
|
||||
{
|
||||
|
||||
protocol_interface_info_entry_t *bb_interface = protocol_stack_interface_info_get_by_id(backbone_interface_id);
|
||||
|
||||
if (bb_interface && bb_interface->ipv6_configure->ipv6_stack_mode == NET_IPV6_BOOTSTRAP_STATIC) {
|
||||
// static configuration for ethernet available
|
||||
ns_list_foreach(if_address_entry_t, add_entry, &cur->ip_addresses) {
|
||||
if (memcmp(add_entry->address, bb_interface->ipv6_configure->static_prefix64, 8) == 0) {
|
||||
//tr_info("BBR static config available");
|
||||
if (dodag_id_ptr) {
|
||||
memcpy(dodag_id_ptr, add_entry->address, 16);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ws_bbr_static_ula_create(cur);
|
||||
|
||||
// only own generated prefix available
|
||||
if (dodag_id_ptr) {
|
||||
memcpy(dodag_id_ptr, static_ula_address, 16);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ws_bbr_dodag_get(protocol_interface_info_entry_t *cur, uint8_t *static_dodag_id_ptr, uint8_t *dodag_id_ptr)
|
||||
{
|
||||
uint8_t global_address[16];
|
||||
|
||||
if (static_dodag_id_ptr) {
|
||||
memset(static_dodag_id_ptr, 0, 16);
|
||||
}
|
||||
|
||||
if (dodag_id_ptr) {
|
||||
memset(dodag_id_ptr, 0, 16);
|
||||
}
|
||||
|
||||
if (ws_bbr_static_dodag_get(cur, static_dodag_id_ptr) < 0) {
|
||||
// no static configuration available
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (arm_net_address_get(backbone_interface_id, ADDR_IPV6_GP, global_address) != 0) {
|
||||
// No global prefix available
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(global_address, dodag_id_ptr, 8) == 0) {
|
||||
// static address is same
|
||||
return 0;
|
||||
}
|
||||
memcpy(dodag_id_ptr, global_address, 16);
|
||||
return 0;
|
||||
}
|
||||
static void wisun_bbr_na_send(int8_t interface_id, const uint8_t target[static 16])
|
||||
{
|
||||
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_t *buffer = icmpv6_build_na(cur, false, true, true, target, NULL, ADDR_UNSPECIFIED);
|
||||
protocol_push(buffer);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static bool wisun_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_update_t *address_info, void *route_src)
|
||||
{
|
||||
(void)route_src;
|
||||
protocol_interface_info_entry_t *curPtr = protocol_stack_interface_info_get_by_id(interfaceId);
|
||||
if (!curPtr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// When address is allocated we send NA to backbone to notify the new address and flush from other BBRs
|
||||
wisun_bbr_na_send(backbone_interface_id, address_info->allocatedAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
||||
uint8_t static_id[16] = {0};
|
||||
uint8_t global_id[16] = {0};
|
||||
|
||||
//tr_info("BBR status check");
|
||||
|
||||
ws_bbr_dodag_get(cur, static_id, global_id);
|
||||
|
||||
if (memcmp(static_dodag_id, static_id, 16) != 0) {
|
||||
// Static id updated or first setup
|
||||
ws_bbr_rpl_root_start(static_id);
|
||||
}
|
||||
if (memcmp(global_dodag_id, global_id, 16) != 0) {
|
||||
// Global prefix changed
|
||||
if (memcmp(global_dodag_id, ADDR_UNSPECIFIED, 16) != 0) {
|
||||
// TODO remove old global prefix
|
||||
tr_info("RPL GUA deactivate %s", trace_ipv6(global_dodag_id));
|
||||
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, static_dodag_id, 64, PIO_A, 7200, 7200, false);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, static_dodag_id, 64, 0x18, 7200, false);
|
||||
|
||||
// Old backbone information is deleted after 120 seconds
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, 120, true);
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_dodag_id, 64, 0, 120, 0, true);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, global_dodag_id, 64, 0, 120, true);
|
||||
ipv6_route_add_with_info(global_dodag_id, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 120, 0);
|
||||
DHCPv6_server_service_delete(cur->id, global_dodag_id, false);
|
||||
|
||||
// Set old addresses to deferred and timeout
|
||||
ws_dhcp_client_address_delete(cur, global_dodag_id);
|
||||
}
|
||||
// TODO add global prefix
|
||||
if (memcmp(global_id, ADDR_UNSPECIFIED, 16) != 0) {
|
||||
//DHCPv6 Server set here
|
||||
//Interface LL64 address
|
||||
uint8_t ll[16];
|
||||
memcpy(ll, ADDR_LINK_LOCAL_PREFIX, 8);
|
||||
memcpy(&ll[8], cur->mac, 8);
|
||||
ll[8] ^= 2;
|
||||
|
||||
if (DHCPv6_server_service_init(cur->id, global_id, cur->mac, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE) != 0) {
|
||||
tr_error("DHCPv6 Server create fail");
|
||||
return;
|
||||
}
|
||||
DHCPv6_server_service_callback_set(cur->id, global_id, NULL, wisun_dhcp_address_add_cb);
|
||||
|
||||
DHCPv6_server_service_set_address_autonous_flag(cur->id, global_id, true);
|
||||
DHCPv6_server_service_set_address_validlifetime(cur->id, global_id, 7200);
|
||||
|
||||
tr_info("RPL GUA activate %s", trace_ipv6(global_id));
|
||||
ws_dhcp_client_address_request(cur, global_id, ll);
|
||||
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, NULL, 0, 0, 7200, false);
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, static_dodag_id, 64, PIO_A, 7200, 0, false);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, static_dodag_id, 64, 0x18, 7200, false);
|
||||
rpl_control_update_dodag_prefix(protocol_6lowpan_rpl_root_dodag, global_id, 64, 0, 7200, 7200, false);
|
||||
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, global_id, 64, 0, 7200, false);
|
||||
ipv6_route_add_with_info(global_id, 64, backbone_interface_id, NULL, ROUTE_THREAD_BBR, NULL, 0, 0xffffffff, 0);
|
||||
}
|
||||
memcpy(global_dodag_id, global_id, 16);
|
||||
rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
|
||||
nd_proxy_downstream_interface_register(cur->id, ws_border_router_proxy_validate, ws_border_router_proxy_state_update);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
|
||||
{
|
||||
(void)seconds;
|
||||
|
||||
if (!ws_info(cur)) {
|
||||
return;
|
||||
}
|
||||
if (cur->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
||||
// Not a border router
|
||||
return;
|
||||
}
|
||||
if (!cur->rpl_domain) {
|
||||
// RPL not started
|
||||
return;
|
||||
}
|
||||
|
||||
if (bbr_delay_timer > seconds) {
|
||||
bbr_delay_timer -= seconds;
|
||||
} else {
|
||||
bbr_delay_timer = 20; // 20 second interval between status checks
|
||||
|
||||
// prequisists
|
||||
// Wi-SUN network configuration started without RPL
|
||||
|
||||
// RPL configured simple
|
||||
// 1. Wait for backend connection
|
||||
// 2. When address becomes available in backend start RPL dodag
|
||||
// 3. if address removed remove dodag
|
||||
|
||||
// RPL configured Advanced
|
||||
// 1. Add ULA DODAG and and start ROOT even without backend
|
||||
// a. If static prefix configured use it.
|
||||
// b. generate random ULA and publish it to backend
|
||||
// 2. if GUA prefix becomes available in backend add new prefix to DODAG
|
||||
// 3. if GUA prefix is removed remove the prefix.
|
||||
|
||||
if (protocol_6lowpan_rpl_root_dodag) {
|
||||
// Border router is active
|
||||
if (0 != protocol_interface_address_compare(static_dodag_id)) {
|
||||
// Dodag has become invalid need to delete
|
||||
tr_info("RPL static dodag not valid anymore %s", trace_ipv6(static_dodag_id));
|
||||
ws_bbr_rpl_root_stop();
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
ws_bbr_rpl_status_check(cur);
|
||||
|
||||
}
|
||||
// Normal BBR operation
|
||||
if (protocol_6lowpan_rpl_root_dodag) {
|
||||
if (cur->ws_info->pan_version_timer > seconds) {
|
||||
cur->ws_info->pan_version_timer -= seconds;
|
||||
} else {
|
||||
// Border router has timed out
|
||||
tr_debug("Border router version number update");
|
||||
cur->ws_info->pan_version_timer = PAN_VERSION_LIFETIME;
|
||||
cur->ws_info->pan_information.pan_version++;
|
||||
// Inconsistent for border router to make information distribute faster
|
||||
ws_bootstrap_configuration_trickle_reset(cur);
|
||||
|
||||
if (cur->ws_info->network_size_config == NETWORK_SIZE_AUTOMATIC) {
|
||||
ws_common_network_size_configure(cur, cur->ws_info->pan_information.pan_size);
|
||||
}
|
||||
// We update the RPL version in same time to allow nodes to reselect parent
|
||||
// As configuration is made so that devices cant move downward in dodag this allows it
|
||||
// TODO think the correct rate for this
|
||||
if (cur->ws_info->pan_information.pan_version && cur->ws_info->pan_information.pan_version % RPL_VERSION_LIFETIME / PAN_VERSION_LIFETIME == 0) {
|
||||
// Third the rate of configuration version change at default 5 hours
|
||||
rpl_control_increment_dodag_version(protocol_6lowpan_rpl_root_dodag);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint16_t test_pan_size_override = 0xffff;
|
||||
|
||||
uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
uint16_t result = 0;
|
||||
if (test_pan_size_override != 0xffff) {
|
||||
return test_pan_size_override;
|
||||
}
|
||||
|
||||
rpl_control_get_instance_dao_target_count(cur->rpl_domain, RPL_INSTANCE_ID, NULL, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#endif //HAVE_WS_BORDER_ROUTER
|
||||
|
||||
/* Public APIs
|
||||
*
|
||||
*/
|
||||
|
||||
int ws_bbr_start(int8_t interface_id, int8_t bb_interface_id)
|
||||
{
|
||||
#ifdef HAVE_WS_BORDER_ROUTER
|
||||
|
||||
(void)interface_id;
|
||||
protocol_interface_info_entry_t *bb_interface = protocol_stack_interface_info_get_by_id(bb_interface_id);
|
||||
|
||||
if (!bb_interface) {
|
||||
return -1;
|
||||
}
|
||||
// TODO make bb configurations
|
||||
|
||||
backbone_interface_id = bb_interface_id;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
(void)interface_id;
|
||||
(void)bb_interface_id;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
void ws_bbr_stop(int8_t interface_id)
|
||||
{
|
||||
#ifdef HAVE_WS_BORDER_ROUTER
|
||||
|
||||
(void)interface_id;
|
||||
backbone_interface_id = -1;
|
||||
|
||||
if (!protocol_6lowpan_rpl_domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
rpl_control_delete_dodag_root(protocol_6lowpan_rpl_domain, protocol_6lowpan_rpl_root_dodag);
|
||||
protocol_6lowpan_rpl_root_dodag = NULL;
|
||||
|
||||
#else
|
||||
(void)interface_id;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64)
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) eui64;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_bbr_node_access_revoke_start(int8_t interface_id)
|
||||
{
|
||||
(void) interface_id;
|
||||
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_BBR_API_PRIVATE_H_
|
||||
#define WS_BBR_API_PRIVATE_H_
|
||||
|
||||
|
||||
#ifdef HAVE_WS_BORDER_ROUTER
|
||||
|
||||
extern uint16_t test_pan_size_override;
|
||||
|
||||
void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds);
|
||||
|
||||
uint16_t ws_bbr_pan_size(protocol_interface_info_entry_t *cur);
|
||||
|
||||
void ws_bbr_rpl_config(uint8_t imin, uint8_t doubling, uint8_t redundancy);
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define ws_bbr_seconds_timer( cur, seconds)
|
||||
#define ws_bbr_pan_size(cur) 0
|
||||
#define ws_bbr_rpl_config( imin, doubling, redundancy);
|
||||
|
||||
#endif //HAVE_WS_BORDER_ROUTER
|
||||
|
||||
#endif /* WS_BBR_API_PRIVATE_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -37,6 +37,10 @@ void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur);
|
|||
|
||||
int ws_bootstrap_restart(int8_t interface_id);
|
||||
|
||||
int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_rf_channel_configuration_s rf_configs);
|
||||
|
||||
int ws_bootstrap_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
/*State machine transactions*/
|
||||
void ws_bootstrap_event_discovery_start(protocol_interface_info_entry_t *cur);
|
||||
|
||||
|
@ -66,11 +70,14 @@ void ws_dhcp_client_address_request(protocol_interface_info_entry_t *cur, uint8_
|
|||
|
||||
void ws_dhcp_client_address_delete(protocol_interface_info_entry_t *cur, uint8_t *prefix);
|
||||
|
||||
bool ws_eapol_relay_state_active(protocol_interface_info_entry_t *cur);
|
||||
|
||||
#else
|
||||
|
||||
#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)
|
||||
#define ws_bootstrap_state_machine(cur)
|
||||
#define ws_bootstrap_restart(cur)
|
||||
#define ws_bootstrap_neighbor_remove(cur, ll_address)
|
||||
#define ws_primary_parent_update(interface, neighbor)
|
||||
#define ws_secondary_parent_update(interface)
|
||||
|
||||
|
|
|
@ -0,0 +1,381 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "nsconfig.h"
|
||||
#include "ns_types.h"
|
||||
#include "ns_trace.h"
|
||||
#include "randLIB.h"
|
||||
#include <ns_list.h>
|
||||
#include <nsdynmemLIB.h>
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_common_defines.h"
|
||||
#include "6LoWPAN/ws/ws_common.h"
|
||||
#include "6LoWPAN/ws/ws_bootstrap.h"
|
||||
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
|
||||
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
||||
#include "Service_Libs/blacklist/blacklist.h"
|
||||
#include "ws_management_api.h"
|
||||
#include "mac_api.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
#define TRACE_GROUP "wscm"
|
||||
|
||||
int8_t DEVICE_MIN_SENS = -93;
|
||||
|
||||
#define TRICKLE_IMIN_60_SECS (60 * 10)
|
||||
#define TRICKLE_IMIN_30_SECS (30 * 10)
|
||||
#define TRICKLE_IMIN_15_SECS (15 * 10)
|
||||
|
||||
static const trickle_params_t trickle_params_pan_discovery_large = {
|
||||
.Imin = TRICKLE_IMIN_60_SECS, /* 60 second; ticks are 1s */
|
||||
.Imax = TRICKLE_IMIN_60_SECS << 4, /* 960 seconds 16 min*/
|
||||
.k = 1, /* 1 */
|
||||
.TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE
|
||||
};
|
||||
|
||||
static const trickle_params_t trickle_params_pan_discovery_medium = {
|
||||
.Imin = TRICKLE_IMIN_30_SECS, /* 30 second; ticks are 1s */
|
||||
.Imax = TRICKLE_IMIN_30_SECS << 3, /* 240 seconds 4 min*/
|
||||
.k = 1, /* 1 */
|
||||
.TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE
|
||||
};
|
||||
|
||||
static const trickle_params_t trickle_params_pan_discovery_small = {
|
||||
.Imin = TRICKLE_IMIN_15_SECS, /* 15 second; ticks are 1s */
|
||||
.Imax = TRICKLE_IMIN_15_SECS << 2, /* 60 seconds 1 min*/
|
||||
.k = 1, /* 1 */
|
||||
.TimerExpirations = TRICKLE_EXPIRATIONS_INFINITE
|
||||
};
|
||||
|
||||
uint16_t test_max_child_count_override = 0xffff;
|
||||
|
||||
|
||||
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain)
|
||||
{
|
||||
(void)regulatory_domain;
|
||||
for (uint8_t i = 0; i < number_of_channels; i++) {
|
||||
channel_mask[0 + (i / 32)] |= (1 << (i % 32));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t ws_decode_channel_spacing(uint8_t channel_spacing)
|
||||
{
|
||||
if (CHANNEL_SPACING_100 == channel_spacing) {
|
||||
return 100000;
|
||||
} else if (CHANNEL_SPACING_200 == channel_spacing) {
|
||||
return 200000;
|
||||
} else if (CHANNEL_SPACING_250 == channel_spacing) {
|
||||
return 250000;
|
||||
} else if (CHANNEL_SPACING_400 == channel_spacing) {
|
||||
return 400000;
|
||||
} else if (CHANNEL_SPACING_600 == channel_spacing) {
|
||||
return 600000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode)
|
||||
{
|
||||
if ((OPERATING_MODE_1a == operating_mode) || (OPERATING_MODE_1b == operating_mode)) {
|
||||
return 50000;
|
||||
} else if ((OPERATING_MODE_2a == operating_mode) || (OPERATING_MODE_2b == operating_mode)) {
|
||||
return 100000;
|
||||
} else if (OPERATING_MODE_3 == operating_mode) {
|
||||
return 150000;
|
||||
} else if ((OPERATING_MODE_4a == operating_mode) || (OPERATING_MODE_4b == operating_mode)) {
|
||||
return 200000;
|
||||
} else if (OPERATING_MODE_5 == operating_mode) {
|
||||
return 300000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t operating_mode)
|
||||
{
|
||||
if ((OPERATING_MODE_1b == operating_mode) || (OPERATING_MODE_2b == operating_mode) || (OPERATING_MODE_4b == operating_mode)) {
|
||||
return MODULATION_INDEX_1_0;
|
||||
} else {
|
||||
return MODULATION_INDEX_0_5;
|
||||
}
|
||||
}
|
||||
|
||||
static int ws_set_domain_rf_config(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
phy_rf_channel_configuration_s rf_configs;
|
||||
rf_configs.channel_0_center_frequency = (uint32_t)cur->ws_info->hopping_schdule.ch0_freq * 100000;
|
||||
rf_configs.channel_spacing = ws_decode_channel_spacing(cur->ws_info->hopping_schdule.channel_spacing);
|
||||
rf_configs.datarate = ws_get_datarate_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode);
|
||||
rf_configs.modulation_index = ws_get_modulation_index_using_operating_mode(cur->ws_info->hopping_schdule.operating_mode);
|
||||
rf_configs.modulation = M_2FSK;
|
||||
rf_configs.number_of_channels = cur->ws_info->hopping_schdule.number_of_channels;
|
||||
ws_bootstrap_set_rf_config(cur, rf_configs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
cur->ws_info->hopping_schdule.channel_plan = 0;
|
||||
|
||||
if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_KR) {
|
||||
if (cur->ws_info->hopping_schdule.operating_class == 1) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 9171;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (cur->ws_info->hopping_schdule.operating_class == 2) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 9173;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_EU) {
|
||||
if (cur->ws_info->hopping_schdule.operating_class == 1) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 8631;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_100;
|
||||
} else if (cur->ws_info->hopping_schdule.operating_class == 2) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 8631;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (cur->ws_info->hopping_schdule.operating_class == 3) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 8701;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_100;
|
||||
} else if (cur->ws_info->hopping_schdule.operating_class == 4) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 8702;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_NA) {
|
||||
if (cur->ws_info->hopping_schdule.operating_class == 1) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 9022;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (cur->ws_info->hopping_schdule.operating_class == 2) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 9024;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400;
|
||||
} else if (cur->ws_info->hopping_schdule.operating_class == 3) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 9026;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_600;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_JP) {
|
||||
if (cur->ws_info->hopping_schdule.operating_class == 1) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 9206;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (cur->ws_info->hopping_schdule.operating_class == 2) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 9209;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400;
|
||||
} else if (cur->ws_info->hopping_schdule.operating_class == 3) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 9208;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_600;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if (cur->ws_info->hopping_schdule.regulatory_domain == REG_DOMAIN_WW) {
|
||||
if (cur->ws_info->hopping_schdule.operating_class == 1) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 24002;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_200;
|
||||
} else if (cur->ws_info->hopping_schdule.operating_class == 2) {
|
||||
cur->ws_info->hopping_schdule.ch0_freq = 24004;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = CHANNEL_SPACING_400;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
cur->ws_info->hopping_schdule.number_of_channels = (uint8_t)ws_common_channel_number_calc(cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class);
|
||||
if (!cur->ws_info->hopping_schdule.number_of_channels) {
|
||||
return -1;
|
||||
}
|
||||
// Note: doesn't work for Brazil region
|
||||
ws_generate_channel_list(cur->ws_info->hopping_schdule.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain);
|
||||
ws_set_domain_rf_config(cur);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class)
|
||||
{
|
||||
if (regulatory_domain == REG_DOMAIN_KR) {
|
||||
if (operating_class == 1) {
|
||||
return 32;
|
||||
} else if (operating_class == 2) {
|
||||
return 16;
|
||||
}
|
||||
} else if (regulatory_domain == REG_DOMAIN_EU) {
|
||||
if (operating_class == 1) {
|
||||
return 69;
|
||||
} else if (operating_class == 2) {
|
||||
return 35;
|
||||
} else if (operating_class == 3) {
|
||||
return 55;
|
||||
} else if (operating_class == 4) {
|
||||
return 27;
|
||||
}
|
||||
} else if (regulatory_domain == REG_DOMAIN_NA) {
|
||||
if (operating_class == 1) {
|
||||
return 129;
|
||||
} else if (operating_class == 2) {
|
||||
return 64;
|
||||
} else if (operating_class == 3) {
|
||||
return 42;
|
||||
}
|
||||
} else if (regulatory_domain == REG_DOMAIN_JP) {
|
||||
if (operating_class == 1) {
|
||||
return 38;
|
||||
} else if (operating_class == 2) {
|
||||
return 18;
|
||||
} else if (operating_class == 3) {
|
||||
return 12;
|
||||
}
|
||||
} else if (regulatory_domain == REG_DOMAIN_WW) {
|
||||
if (operating_class == 1) {
|
||||
// TODO we dont support this yet, but it is used as test value
|
||||
return 416;
|
||||
} else if (operating_class == 2) {
|
||||
return 207;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
|
||||
if (!cur->ws_info) {
|
||||
cur->ws_info = ns_dyn_mem_alloc(sizeof(ws_info_t));
|
||||
}
|
||||
if (!cur->ws_info) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(cur->ws_info, 0, sizeof(ws_info_t));
|
||||
ns_list_init(&cur->ws_info->active_nud_process);
|
||||
ns_list_init(&cur->ws_info->free_nud_entries);
|
||||
|
||||
cur->ws_info->pan_information.use_parent_bs = true;
|
||||
cur->ws_info->pan_information.rpl_routing_method = true;
|
||||
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0;
|
||||
|
||||
cur->ws_info->hopping_schdule.regulatory_domain = REG_DOMAIN_EU;
|
||||
cur->ws_info->hopping_schdule.operating_mode = OPERATING_MODE_3;
|
||||
cur->ws_info->hopping_schdule.operating_class = 2;
|
||||
ws_common_regulatory_domain_config(cur);
|
||||
ws_common_network_size_configure(cur, 10); // defaults to small network size
|
||||
|
||||
// Set defaults for the device. user can modify these.
|
||||
cur->ws_info->fhss_uc_fixed_channel = 0xffff;
|
||||
cur->ws_info->fhss_bc_fixed_channel = 0xffff;
|
||||
cur->ws_info->fhss_uc_dwell_interval = WS_FHSS_UC_DWELL_INTERVAL;
|
||||
cur->ws_info->fhss_bc_interval = WS_FHSS_BC_INTERVAL;
|
||||
cur->ws_info->fhss_bc_dwell_interval = WS_FHSS_BC_DWELL_INTERVAL;
|
||||
cur->ws_info->fhss_uc_channel_function = WS_DH1CF;
|
||||
cur->ws_info->fhss_bc_channel_function = WS_DH1CF;
|
||||
for (uint8_t n = 0; n < 8; n++) {
|
||||
cur->ws_info->fhss_channel_mask[n] = 0xffffffff;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size)
|
||||
{
|
||||
// TODO Modify NUD timings based on network size
|
||||
// TODO Modify EAPOLL timings
|
||||
|
||||
if (network_size < 100) {
|
||||
// Configure the Wi-SUN discovery trickle parameters
|
||||
cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_small;
|
||||
// default values are for Wi-SUN small network parameters
|
||||
// imin: 14 (16s)
|
||||
// doublings:3 (128s)
|
||||
// redundancy; 0 Disabled
|
||||
ws_bbr_rpl_config(0, 0, 0);// set the default values
|
||||
} else if (network_size < 300) {
|
||||
// Configure the Wi-SUN discovery trickle parameters
|
||||
cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_medium;
|
||||
// Something in between
|
||||
// imin: 15 (32s)
|
||||
// doublings:3 (262s)
|
||||
// redundancy; 7
|
||||
ws_bbr_rpl_config(15, 3, 7);
|
||||
} else {
|
||||
// Configure the Wi-SUN discovery trickle parameters
|
||||
cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_large;
|
||||
// Wi-SUN Large network parameters
|
||||
// imin: 19 (524s, 9 min)
|
||||
// doublings:1 (1048s, 17 min)
|
||||
// redundancy; 1 Really heavy redundancy
|
||||
ws_bbr_rpl_config(19, 1, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
|
||||
{
|
||||
ws_bbr_seconds_timer(cur, seconds);
|
||||
ws_bootstrap_seconds_timer(cur, seconds);
|
||||
blacklist_ttl_update(seconds);
|
||||
}
|
||||
|
||||
void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks)
|
||||
{
|
||||
ws_bootstrap_trickle_timer(cur, ticks);
|
||||
ws_nud_active_timer(cur, ticks);
|
||||
}
|
||||
|
||||
|
||||
void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
|
||||
{
|
||||
//Neighbor connectected update
|
||||
mac_neighbor_table_entry_t *mac_neighbor = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll_address, false, NULL);
|
||||
if (mac_neighbor) {
|
||||
ws_nud_entry_remove_active(cur, mac_neighbor);
|
||||
}
|
||||
}
|
||||
|
||||
void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address)
|
||||
{
|
||||
//Neighbor connectected update
|
||||
ws_bootstrap_neighbor_remove(cur, ll_address);
|
||||
}
|
||||
|
||||
bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interface)
|
||||
{
|
||||
uint8_t child_count = 0;
|
||||
uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - WS_NON_CHILD_NEIGHBOUR_COUNT;
|
||||
|
||||
// Test API to limit child count
|
||||
if (test_max_child_count_override != 0xffff) {
|
||||
max_child_count = test_max_child_count_override;
|
||||
}
|
||||
|
||||
ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) {
|
||||
|
||||
if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, cur->mac64)) {
|
||||
child_count++;
|
||||
}
|
||||
}
|
||||
if (child_count >= max_child_count) {
|
||||
tr_warn("Child registration not allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size);
|
||||
return false;
|
||||
}
|
||||
tr_info("Child registration allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif // HAVE_WS
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -24,10 +24,14 @@
|
|||
#include "fhss_api.h"
|
||||
#include "fhss_config.h"
|
||||
#include "net_fhss.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "6LoWPAN/ws/ws_common_defines.h"
|
||||
#include "6LoWPAN/ws/ws_neighbor_class.h"
|
||||
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
||||
|
||||
|
||||
extern uint16_t test_max_child_count_override;
|
||||
|
||||
struct ws_pan_information_s;
|
||||
struct ws_neighbor_class_s;
|
||||
|
||||
|
@ -61,6 +65,8 @@ typedef struct ws_info_s {
|
|||
trickle_t trickle_pan_config;
|
||||
trickle_t trickle_pan_advertisement_solicit;
|
||||
trickle_t trickle_pan_advertisement;
|
||||
trickle_params_t trickle_params_pan_discovery;
|
||||
uint8_t network_size_config; // configuration for network size selection of application.
|
||||
uint8_t rpl_state; // state from rpl_event_t
|
||||
uint8_t pas_requests; // Amount of PAN solicits sent
|
||||
parent_info_t parent_info;
|
||||
|
@ -98,20 +104,30 @@ int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_chann
|
|||
|
||||
int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur);
|
||||
|
||||
uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class);
|
||||
|
||||
int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur);
|
||||
|
||||
void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint16_t network_size);
|
||||
|
||||
void ws_common_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds);
|
||||
|
||||
void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks);
|
||||
|
||||
void ws_common_neighbor_update(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
void ws_common_aro_failure(protocol_interface_info_entry_t *cur, const uint8_t *ll_address);
|
||||
|
||||
bool ws_common_allow_child_registration(protocol_interface_info_entry_t *cur);
|
||||
|
||||
#define ws_info(cur) ((cur)->ws_info)
|
||||
#else
|
||||
#define ws_info(cur) ((ws_info_t *) NULL)
|
||||
#define ws_common_seconds_timer(cur, seconds)
|
||||
#define ws_common_neighbor_update(cur, ll_address) ((void) 0)
|
||||
#define ws_common_aro_failure(cur, ll_address)
|
||||
#define ws_common_fast_timer(cur, ticks) ((void) 0)
|
||||
#define ws_common_allow_child_registration(cur) (false)
|
||||
|
||||
|
||||
#endif //HAVE_WS
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -27,6 +27,7 @@
|
|||
#define WH_IE_RSL_TYPE 4 /**< Received Signal Level information */
|
||||
#define WH_IE_MHDS_TYPE 5 /**< MHDS information for mesh routing */
|
||||
#define WH_IE_VH_TYPE 6 /**< Vendor header information */
|
||||
#define WH_IE_EA_TYPE 9 /**< Eapol Auhtenticator EUI-64 header information */
|
||||
|
||||
#define WS_WP_NESTED_IE 4 /**< WS nested Payload IE element'selement could include mltiple sub payload IE */
|
||||
|
||||
|
@ -215,12 +216,28 @@ typedef struct ws_bs_ie {
|
|||
*/
|
||||
#define WS_RPL_DIS_TIMEOUT 1800
|
||||
|
||||
/*
|
||||
* MAC Ack wait duration in symbols. 2-FSK modulation used -> 1 bit per symbol.
|
||||
*/
|
||||
#define WS_ACK_WAIT_SYMBOLS 800
|
||||
|
||||
/*
|
||||
* Tack max time in milliseconds.
|
||||
*/
|
||||
#define WS_TACK_MAX_MS 5
|
||||
|
||||
/* Default FHSS timing information
|
||||
*
|
||||
*/
|
||||
#define WS_FHSS_UC_DWELL_INTERVAL 250;
|
||||
#define WS_FHSS_BC_INTERVAL 800;
|
||||
#define WS_FHSS_BC_DWELL_INTERVAL 200;
|
||||
#define WS_FHSS_UC_DWELL_INTERVAL 255;
|
||||
#define WS_FHSS_BC_INTERVAL 1020;
|
||||
#define WS_FHSS_BC_DWELL_INTERVAL 255;
|
||||
|
||||
/*
|
||||
* EAPOL relay and PAE authenticator socket settings
|
||||
*/
|
||||
#define EAPOL_RELAY_SOCKET_PORT 10253
|
||||
#define BR_EAPOL_RELAY_SOCKET_PORT 10255
|
||||
#define PAE_AUTH_SOCKET_PORT 10254
|
||||
|
||||
#endif /* WS_COMMON_DEFINES_H_ */
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_CONFIG_H_
|
||||
#define WS_CONFIG_H_
|
||||
|
||||
|
||||
/*RPL parameters for DIO messages
|
||||
*
|
||||
* Small scale spec recomendation imin 15, doubling 2, redudancy 0
|
||||
* Small scale values imin 14, doubling 3, redudancy 0
|
||||
* Large scale network imin 19, doubling 1, redudancy 1
|
||||
*
|
||||
*/
|
||||
|
||||
#define WS_RPL_DIO_IMIN 14
|
||||
#define WS_RPL_DIO_DOUBLING 3
|
||||
#define WS_RPL_DIO_REDUNDANCY 0
|
||||
|
||||
|
||||
/* Border router version change interval
|
||||
*
|
||||
* Minimum interval at which a Border Router shall increment its PAN Version value.
|
||||
*/
|
||||
|
||||
#define PAN_VERSION_LIFETIME 240
|
||||
|
||||
#define RPL_VERSION_LIFETIME 5*3600
|
||||
|
||||
/* Border router connection lost timeout
|
||||
*
|
||||
* Interval within which a node expects to detect a change in PAN Version
|
||||
* (delivered via a PAN Configuration frame / PAN-IE).
|
||||
*
|
||||
* the maximum Trickle interval specified for DISC_IMAX (32 minutes).
|
||||
*
|
||||
*/
|
||||
|
||||
#define PAN_VERSION_TIMEOUT 1920
|
||||
|
||||
/* Routing Cost Weighting factor
|
||||
*/
|
||||
#define PRC_WEIGHT_FACTOR 256
|
||||
|
||||
/* Routing Cost Weighting factor
|
||||
*/
|
||||
#define PS_WEIGHT_FACTOR 64
|
||||
|
||||
/* Smoothing factor for RSL calculation 1/8
|
||||
*/
|
||||
#define WS_RSL_SCALING 3
|
||||
|
||||
/* Device min sensitivity. This value is dynamically configured and depends on radio
|
||||
*
|
||||
* Default value for us is -93
|
||||
*/
|
||||
extern int8_t DEVICE_MIN_SENS;
|
||||
|
||||
/* Candidate parent Threshold
|
||||
*/
|
||||
#define CAND_PARENT_THRESHOLD 10
|
||||
|
||||
/* Candidate parent Threshold hysteresis
|
||||
*/
|
||||
#define CAND_PARENT_HYSTERISIS 3
|
||||
|
||||
/* Maximum amount of Pan Configuration Solicits before restarting Discovery.
|
||||
*/
|
||||
#define PCS_MAX 5
|
||||
|
||||
|
||||
/* Multicast MPL data message parameters
|
||||
* IMIN = 10 seconds, IMAX = 3 doublings
|
||||
*/
|
||||
|
||||
#define DATA_MESSAGE_IMIN (10 * 1000)
|
||||
#define DATA_MESSAGE_TIMER_EXPIRATIONS 3
|
||||
#define DATA_MESSAGE_IMAX (DATA_MESSAGE_IMIN)
|
||||
#define MPL_SEED_SET_ENTRY_TIMEOUT (DATA_MESSAGE_IMAX * 24 * 4 / 1000) // 10 seconds per hop making this 240 seconds
|
||||
|
||||
/* DHCP client timeout configuration values
|
||||
*
|
||||
*/
|
||||
#define WS_DHCP_SOLICIT_TIMEOUT 60
|
||||
#define WS_DHCP_SOLICIT_MAX_RT 3600
|
||||
#define WS_DHCP_SOLICIT_MAX_RC 0
|
||||
|
||||
|
||||
/* Neighbour table configuration
|
||||
*
|
||||
* Amount of RPL candidate parents
|
||||
* 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)
|
||||
|
||||
/*
|
||||
* Neighbour blacklist timers
|
||||
*/
|
||||
#define WS_BLACKLIST_ENTRY_LIFETIME 60*30 // initial value for reject
|
||||
#define WS_BLACKLIST_TIMER_MAX_TIMEOUT 60*60 // Can increase to this
|
||||
#define WS_BLACKLIST_TIMER_TIMEOUT 60*30 // Blacklist is valid this time after first accept
|
||||
#define WS_BLACKLIST_ENTRY_MAX_NBR 10
|
||||
#define WS_BLACKLIST_PURGE_NBR 3
|
||||
#define WS_BLACKLIST_PURGE_TIMER_TIMEOUT 60
|
||||
|
||||
|
||||
#endif /* WS_CONFIG_H_ */
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "fhss_config.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "mac_api.h"
|
||||
#include "mac_mcps.h"
|
||||
#include "Common_Protocols/ipv6_constants.h"
|
||||
#include "socket_api.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "6LoWPAN/MAC/mpx_api.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_eapol_pdu.h"
|
||||
#include "6LoWPAN/ws/ws_eapol_relay_lib.h"
|
||||
#include "6LoWPAN/ws/ws_eapol_auth_relay.h"
|
||||
#include "common_functions.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
#ifdef HAVE_PAE_AUTH
|
||||
|
||||
#define TRACE_GROUP "wsar"
|
||||
|
||||
typedef struct {
|
||||
protocol_interface_info_entry_t *interface_ptr; /**< Interface pointer */
|
||||
ns_address_t remote_addr; /**< Remote address and port */
|
||||
ns_address_t relay_addr; /**< Relay address */
|
||||
int8_t socket_id; /**< Socket ID for relay */
|
||||
ns_list_link_t link; /**< Link */
|
||||
} eapol_auth_relay_t;
|
||||
|
||||
static eapol_auth_relay_t *ws_eapol_auth_relay_get(protocol_interface_info_entry_t *interface_ptr);
|
||||
static void ws_eapol_auth_relay_socket_cb(void *cb);
|
||||
static int8_t ws_eapol_auth_relay_send_to_kmp(eapol_auth_relay_t *eapol_auth_relay, const uint8_t *eui_64, const uint8_t *ip_addr, uint16_t port, const void *data, uint16_t data_len);
|
||||
|
||||
static NS_LIST_DEFINE(eapol_auth_relay_list, eapol_auth_relay_t, link);
|
||||
|
||||
int8_t ws_eapol_auth_relay_start(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port)
|
||||
{
|
||||
if (!interface_ptr || !remote_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_eapol_auth_relay_get(interface_ptr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
eapol_auth_relay_t *eapol_auth_relay = ns_dyn_mem_alloc(sizeof(eapol_auth_relay_t));
|
||||
if (!eapol_auth_relay) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_auth_relay->interface_ptr = interface_ptr;
|
||||
|
||||
eapol_auth_relay->remote_addr.type = ADDRESS_IPV6;
|
||||
memcpy(&eapol_auth_relay->relay_addr.address, remote_addr, 16);
|
||||
eapol_auth_relay->relay_addr.identifier = remote_port;
|
||||
|
||||
eapol_auth_relay->socket_id = socket_open(IPV6_NH_UDP, local_port, &ws_eapol_auth_relay_socket_cb);
|
||||
if (eapol_auth_relay->socket_id < 0) {
|
||||
ns_dyn_mem_free(eapol_auth_relay);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ns_list_add_to_end(&eapol_auth_relay_list, eapol_auth_relay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_eapol_auth_relay_delete(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_auth_relay_t *eapol_auth_relay = ws_eapol_auth_relay_get(interface_ptr);
|
||||
if (!eapol_auth_relay) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket_close(eapol_auth_relay->socket_id);
|
||||
|
||||
ns_list_remove(&eapol_auth_relay_list, eapol_auth_relay);
|
||||
ns_dyn_mem_free(eapol_auth_relay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static eapol_auth_relay_t *ws_eapol_auth_relay_get(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
ns_list_foreach(eapol_auth_relay_t, entry, &eapol_auth_relay_list) {
|
||||
if (entry->interface_ptr == interface_ptr) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ws_eapol_auth_relay_socket_cb(void *cb)
|
||||
{
|
||||
socket_callback_t *cb_data = cb;
|
||||
|
||||
if (cb_data->event_type != SOCKET_DATA) {
|
||||
return;
|
||||
}
|
||||
|
||||
eapol_auth_relay_t *eapol_auth_relay = NULL;
|
||||
|
||||
ns_list_foreach(eapol_auth_relay_t, entry, &eapol_auth_relay_list) {
|
||||
if (entry->socket_id == cb_data->socket_id) {
|
||||
eapol_auth_relay = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!eapol_auth_relay) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *socket_pdu = ns_dyn_mem_temporary_alloc(cb_data->d_len);
|
||||
if (!socket_pdu) {
|
||||
return;
|
||||
}
|
||||
|
||||
ns_address_t src_addr;
|
||||
|
||||
if (socket_recvfrom(cb_data->socket_id, socket_pdu, cb_data->d_len, 0, &src_addr) != cb_data->d_len) {
|
||||
ns_dyn_mem_free(socket_pdu);
|
||||
return;
|
||||
}
|
||||
|
||||
// Message from source port 10254 (KMP service) -> to IP relay on node or on authenticator
|
||||
if (src_addr.identifier == eapol_auth_relay->relay_addr.identifier) {
|
||||
uint8_t *ptr = socket_pdu;
|
||||
uint8_t *eui_64;
|
||||
ns_address_t relay_ip_addr;
|
||||
relay_ip_addr.type = ADDRESS_IPV6;
|
||||
memcpy(relay_ip_addr.address, ptr, 16);
|
||||
ptr += 16;
|
||||
relay_ip_addr.identifier = common_read_16_bit(ptr);
|
||||
ptr += 2;
|
||||
eui_64 = ptr;
|
||||
ptr += 8;
|
||||
uint16_t data_len = cb_data->d_len - 26;
|
||||
ws_eapol_relay_lib_send_to_relay(eapol_auth_relay->socket_id, eui_64, &relay_ip_addr,
|
||||
ptr, data_len);
|
||||
ns_dyn_mem_free(socket_pdu);
|
||||
// Other source port (either 10253 or node relay source port) -> to KMP service
|
||||
} else {
|
||||
uint8_t *ptr = socket_pdu;
|
||||
ws_eapol_auth_relay_send_to_kmp(eapol_auth_relay, ptr, src_addr.address, src_addr.identifier,
|
||||
ptr + 8, cb_data->d_len - 8);
|
||||
ns_dyn_mem_free(socket_pdu);
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t ws_eapol_auth_relay_send_to_kmp(eapol_auth_relay_t *eapol_auth_relay, const uint8_t *eui_64, const uint8_t *ip_addr, uint16_t port, const void *data, uint16_t data_len)
|
||||
{
|
||||
ns_address_t dest_addr = eapol_auth_relay->relay_addr;
|
||||
|
||||
uint8_t temp_array[26];
|
||||
ns_iovec_t msg_iov[2];
|
||||
ns_msghdr_t msghdr;
|
||||
//Set messages name buffer
|
||||
msghdr.msg_name = &dest_addr;
|
||||
msghdr.msg_namelen = sizeof(dest_addr);
|
||||
msghdr.msg_iov = &msg_iov[0];
|
||||
msghdr.msg_iovlen = 2;
|
||||
msghdr.msg_control = NULL;
|
||||
msghdr.msg_controllen = 0;
|
||||
uint8_t *ptr = temp_array;
|
||||
memcpy(ptr, ip_addr, 16);
|
||||
ptr += 16;
|
||||
ptr = common_write_16_bit(port, ptr);
|
||||
memcpy(ptr, eui_64, 8);
|
||||
msg_iov[0].iov_base = temp_array;
|
||||
msg_iov[0].iov_len = 26;
|
||||
msg_iov[1].iov_base = (void *)data;
|
||||
msg_iov[1].iov_len = data_len;
|
||||
socket_sendmsg(eapol_auth_relay->socket_id, &msghdr, NS_MSG_LEGACY0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_PAE_AUTH */
|
||||
#endif /* HAVE_WS */
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_EAPOL_AUTH_RELAY_H_
|
||||
#define WS_EAPOL_AUTH_RELAY_H_
|
||||
|
||||
#ifdef HAVE_PAE_AUTH
|
||||
|
||||
/*
|
||||
* EAPOL authenticator relay acts as a proxy between EAPOL UDP relay and
|
||||
* authenticator PAE (KMP service). Relay is bound by default to EAPOL UDP
|
||||
* relay port 10253 (set by local port parameter) and transfers messages
|
||||
* to/from authenticator PAE. As default PAE is bound to UDP port 10254
|
||||
* (set by remote address and port parameters).
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* ws_eapol_auth_relay_start start authenticator relay
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param local_port local port
|
||||
* \param remote_addr remote address
|
||||
* \param remote_port remote port
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_auth_relay_start(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port);
|
||||
|
||||
/**
|
||||
* ws_eapol_auth_relay_delete delete authenticator relay
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_auth_relay_delete(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
#else
|
||||
|
||||
#define ws_eapol_auth_relay_start(interface_ptr, local_port, remote_addr, remote_port)
|
||||
#define ws_eapol_auth_relay_delete(interface_ptr)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WS_EAPOL_AUTH_RELAY_H_ */
|
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "fhss_config.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "mac_api.h"
|
||||
#include "mac_mcps.h"
|
||||
#include "Common_Protocols/ipv6_constants.h"
|
||||
#include "socket_api.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "6LoWPAN/MAC/mpx_api.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_eapol_pdu.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
#define TRACE_GROUP "wsep"
|
||||
|
||||
typedef struct {
|
||||
uint8_t handle;
|
||||
void *data_ptr;
|
||||
void *buffer;
|
||||
ns_list_link_t link;
|
||||
} eapol_pdu_msdu_t;
|
||||
|
||||
typedef NS_LIST_HEAD(eapol_pdu_msdu_t, link) eapol_pdu_msdu_list_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t priority;
|
||||
ws_eapol_pdu_address_check *addr_check;
|
||||
ws_eapol_pdu_receive *receive;
|
||||
ns_list_link_t link;
|
||||
} eapol_pdu_recv_cb_t;
|
||||
|
||||
typedef NS_LIST_HEAD(eapol_pdu_recv_cb_t, link) eapol_pdu_recv_cb_list_t;
|
||||
|
||||
typedef struct {
|
||||
eapol_pdu_recv_cb_list_t recv_cb_list; /**< List of receive callbacks */
|
||||
eapol_pdu_msdu_list_t msdu_list; /**< MSDU list */
|
||||
ws_eapol_pdu_receive *receive; /**< data receive callback */
|
||||
protocol_interface_info_entry_t *interface_ptr; /**< Interface pointer */
|
||||
mpx_api_t *mpx_api; /**< MPX api */
|
||||
uint16_t mpx_user_id; /**< MPX user identifier */
|
||||
uint8_t msdu_handle; /**< MSDU handle */
|
||||
ns_list_link_t link; /**< Link */
|
||||
} eapol_pdu_data_t;
|
||||
|
||||
static void ws_eapol_pdu_mpx_data_confirm(const mpx_api_t *api, const struct mcps_data_conf_s *data);
|
||||
static void ws_eapol_pdu_mpx_data_indication(const mpx_api_t *api, const struct mcps_data_ind_s *data);
|
||||
static void ws_eapol_pdu_data_request_primitiv_set(mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur);
|
||||
static eapol_pdu_data_t *ws_eapol_pdu_data_get(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
static NS_LIST_DEFINE(eapol_pdu_data_list, eapol_pdu_data_t, link);
|
||||
|
||||
int8_t ws_eapol_pdu_init(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_eapol_pdu_data_get(interface_ptr) != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
eapol_pdu_data_t *eapol_pdu_data = ns_dyn_mem_alloc(sizeof(eapol_pdu_data_t));
|
||||
if (!eapol_pdu_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_pdu_data->interface_ptr = interface_ptr;
|
||||
ns_list_init(&eapol_pdu_data->recv_cb_list);
|
||||
ns_list_init(&eapol_pdu_data->msdu_list);
|
||||
eapol_pdu_data->msdu_handle = 0;
|
||||
|
||||
ns_list_add_to_end(&eapol_pdu_data_list, eapol_pdu_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_eapol_pdu_delete(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
||||
|
||||
if (!eapol_pdu_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ns_list_foreach_safe(eapol_pdu_recv_cb_t, cb_entry, &eapol_pdu_data->recv_cb_list) {
|
||||
ns_list_remove(&eapol_pdu_data->recv_cb_list, cb_entry);
|
||||
ns_dyn_mem_free(cb_entry);
|
||||
}
|
||||
|
||||
ns_list_foreach_safe(eapol_pdu_msdu_t, msdu_entry, &eapol_pdu_data->msdu_list) {
|
||||
ns_list_remove(&eapol_pdu_data->msdu_list, msdu_entry);
|
||||
ns_dyn_mem_free(msdu_entry);
|
||||
}
|
||||
|
||||
ns_list_remove(&eapol_pdu_data_list, eapol_pdu_data);
|
||||
ns_dyn_mem_free(eapol_pdu_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_eapol_pdu_cb_register(protocol_interface_info_entry_t *interface_ptr, const eapol_pdu_recv_cb_data_t *cb_data)
|
||||
{
|
||||
if (!interface_ptr || !cb_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
||||
|
||||
if (!eapol_pdu_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_pdu_recv_cb_t *new_cb = ns_dyn_mem_alloc(sizeof(eapol_pdu_recv_cb_t));
|
||||
if (!new_cb) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_cb->priority = cb_data->priority;
|
||||
new_cb->addr_check = cb_data->addr_check;
|
||||
new_cb->receive = cb_data->receive;
|
||||
|
||||
ns_list_foreach(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
|
||||
if (new_cb->priority <= entry->priority) {
|
||||
ns_list_add_before(&eapol_pdu_data->recv_cb_list, entry, new_cb);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ns_list_add_to_end(&eapol_pdu_data->recv_cb_list, new_cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_eapol_pdu_cb_unregister(protocol_interface_info_entry_t *interface_ptr, const eapol_pdu_recv_cb_data_t *cb_data)
|
||||
{
|
||||
if (!interface_ptr || !cb_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
||||
|
||||
if (!eapol_pdu_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ns_list_foreach_safe(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
|
||||
if (entry->receive == cb_data->receive) {
|
||||
ns_list_remove(&eapol_pdu_data->recv_cb_list, entry);
|
||||
ns_dyn_mem_free(entry);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *data, uint16_t size, void *buffer)
|
||||
{
|
||||
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
||||
|
||||
if (!eapol_pdu_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mcps_data_req_t data_request;
|
||||
ws_eapol_pdu_data_request_primitiv_set(&data_request, eapol_pdu_data->interface_ptr);
|
||||
|
||||
eapol_pdu_msdu_t *msdu_entry = ns_dyn_mem_temporary_alloc(sizeof(eapol_pdu_msdu_t));
|
||||
if (!msdu_entry) {
|
||||
return -1;
|
||||
}
|
||||
msdu_entry->data_ptr = data;
|
||||
msdu_entry->buffer = buffer;
|
||||
msdu_entry->handle = eapol_pdu_data->msdu_handle++;
|
||||
ns_list_add_to_start(&eapol_pdu_data->msdu_list, msdu_entry);
|
||||
|
||||
memcpy(data_request.DstAddr, eui_64, 8);
|
||||
data_request.msdu = data;
|
||||
data_request.msduLength = size;
|
||||
|
||||
eapol_pdu_data->mpx_api->mpx_data_request(eapol_pdu_data->mpx_api, &data_request, eapol_pdu_data->mpx_user_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ws_eapol_pdu_data_request_primitiv_set(mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur)
|
||||
{
|
||||
memset(dataReq, 0, sizeof(mcps_data_req_t));
|
||||
|
||||
dataReq->InDirectTx = false;
|
||||
dataReq->TxAckReq = true;
|
||||
dataReq->SrcAddrMode = ADDR_802_15_4_LONG;
|
||||
dataReq->DstAddrMode = ADDR_802_15_4_LONG;
|
||||
dataReq->DstPANId = mac_helper_panid_get(cur);
|
||||
}
|
||||
|
||||
int8_t ws_eapol_pdu_mpx_register(protocol_interface_info_entry_t *interface_ptr, struct mpx_api_s *mpx_api, uint16_t mpx_user_id)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_pdu_data_t *eapol_pdu_data = ws_eapol_pdu_data_get(interface_ptr);
|
||||
|
||||
if (!eapol_pdu_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mpx_api && eapol_pdu_data->mpx_api) {
|
||||
//Disable Data Callbacks from MPX Class
|
||||
eapol_pdu_data->mpx_api->mpx_user_registration(eapol_pdu_data->mpx_api, NULL, NULL, eapol_pdu_data->mpx_user_id);
|
||||
}
|
||||
|
||||
eapol_pdu_data->mpx_api = mpx_api;
|
||||
eapol_pdu_data->mpx_user_id = mpx_user_id;
|
||||
|
||||
if (eapol_pdu_data->mpx_api) {
|
||||
eapol_pdu_data->mpx_api->mpx_user_registration(eapol_pdu_data->mpx_api, ws_eapol_pdu_mpx_data_confirm, ws_eapol_pdu_mpx_data_indication, eapol_pdu_data->mpx_user_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ws_eapol_pdu_mpx_data_confirm(const mpx_api_t *api, const struct mcps_data_conf_s *data)
|
||||
{
|
||||
eapol_pdu_data_t *eapol_pdu_data = NULL;
|
||||
|
||||
ns_list_foreach(eapol_pdu_data_t, entry, &eapol_pdu_data_list) {
|
||||
if (entry->mpx_api == api) {
|
||||
eapol_pdu_data = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!eapol_pdu_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
ns_list_foreach(eapol_pdu_msdu_t, msdu, &eapol_pdu_data->msdu_list) {
|
||||
if (msdu->handle == data->msduHandle) {
|
||||
ns_dyn_mem_free(msdu->buffer);
|
||||
ns_list_remove(&eapol_pdu_data->msdu_list, msdu);
|
||||
ns_dyn_mem_free(msdu);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ws_eapol_pdu_mpx_data_indication(const mpx_api_t *api, const struct mcps_data_ind_s *data)
|
||||
{
|
||||
if (!data || !data->msduLength || !data->msdu_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
eapol_pdu_data_t *eapol_pdu_data = NULL;
|
||||
|
||||
ns_list_foreach(eapol_pdu_data_t, entry, &eapol_pdu_data_list) {
|
||||
if (entry->mpx_api == api) {
|
||||
eapol_pdu_data = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!eapol_pdu_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
ns_list_foreach(eapol_pdu_recv_cb_t, entry, &eapol_pdu_data->recv_cb_list) {
|
||||
if (entry->addr_check(eapol_pdu_data->interface_ptr, data->SrcAddr) >= 0) {
|
||||
entry->receive(eapol_pdu_data->interface_ptr, data->SrcAddr, data->msdu_ptr, data->msduLength);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static eapol_pdu_data_t *ws_eapol_pdu_data_get(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
eapol_pdu_data_t *eapol_pdu_data = NULL;
|
||||
|
||||
ns_list_foreach(eapol_pdu_data_t, entry, &eapol_pdu_data_list) {
|
||||
if (entry->interface_ptr == interface_ptr) {
|
||||
eapol_pdu_data = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return eapol_pdu_data;
|
||||
}
|
||||
|
||||
#endif /* HAVE_WS */
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_EAPOL_PDU_H_
|
||||
#define WS_EAPOL_PDU_H_
|
||||
|
||||
/*
|
||||
* EAPOL PDU module transfers EAPOL PDUs to/from MPX. Several users
|
||||
* (e.g. supplicant PAE and EAPOL relay) can register to incoming
|
||||
* EAPOL PDUs. When registering, users need to define priority that
|
||||
* defines in which order incoming EAPOL PDUs are offered to them.
|
||||
*
|
||||
* Incoming EAPOL PDU user callbacks form a pair on EAPOL PDU module:
|
||||
* address check callback is called first, and if it returns match
|
||||
* then incoming EAPOL PDU callback is called.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_init initialize EAPOL PDU module
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_pdu_init(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_mpx_register register EAPOL PDU module to MPX
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param mpx_api MPX API
|
||||
* \param mpx_user_id MPX user id
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_pdu_mpx_register(protocol_interface_info_entry_t *interface_ptr, struct mpx_api_s *mpx_api, uint16_t mpx_user_id);
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_delete delete EAPOL PDU module
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_pdu_delete(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_address_check check incoming EAPOL PDU address
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param eui_64 source EUI-64
|
||||
*
|
||||
* \return < 0 address does not match
|
||||
* \return >= 0 address matches, call the PDU receive callback
|
||||
*
|
||||
*/
|
||||
typedef int8_t ws_eapol_pdu_address_check(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_receive receive EAPOL PDU
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param eui_64 source EUI-64
|
||||
* \param data EAPOL PDU
|
||||
* \param size PDU size
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
typedef int8_t ws_eapol_pdu_receive(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *data, uint16_t size);
|
||||
|
||||
typedef enum {
|
||||
EAPOL_PDU_RECV_HIGH_PRIORITY = 0,
|
||||
EAPOL_PDU_RECV_MEDIUM_PRIORITY = 100,
|
||||
EAPOL_PDU_RECV_LOW_PRIORITY = 200
|
||||
} eapol_pdu_recv_prior_t;
|
||||
|
||||
typedef struct {
|
||||
eapol_pdu_recv_prior_t priority; /**< Priority: high, medium or low */
|
||||
ws_eapol_pdu_address_check *addr_check; /**< Address check callback */
|
||||
ws_eapol_pdu_receive *receive; /**< PDU receive callback */
|
||||
} eapol_pdu_recv_cb_data_t;
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_cb_register register an incoming EAPOL PDU callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param cb_data callback data
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_pdu_cb_register(protocol_interface_info_entry_t *interface_ptr, const eapol_pdu_recv_cb_data_t *cb_data);
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_cb_unregister unregister an incoming EAPOL PDU callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param cb_data callback data
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_pdu_cb_unregister(protocol_interface_info_entry_t *interface_ptr, const eapol_pdu_recv_cb_data_t *cb_data);
|
||||
|
||||
/**
|
||||
* ws_eapol_pdu_send_to_mpx send EAPOL PDU to MPX
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param eui_64 destination EUI-64
|
||||
* \param data EAPOL PDU
|
||||
* \param size PDU size
|
||||
* \param buffer pointer to allocated buffer
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_pdu_send_to_mpx(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *data, uint16_t size, void *buffer);
|
||||
|
||||
#endif /* WS_EAPOL_PDU_H_ */
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "fhss_config.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "mac_api.h"
|
||||
#include "mac_mcps.h"
|
||||
#include "Common_Protocols/ipv6_constants.h"
|
||||
#include "socket_api.h"
|
||||
#include "6LoWPAN/MAC/mac_helper.h"
|
||||
#include "6LoWPAN/MAC/mpx_api.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_eapol_pdu.h"
|
||||
#include "6LoWPAN/ws/ws_eapol_relay_lib.h"
|
||||
#include "6LoWPAN/ws/ws_eapol_relay.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
#ifdef HAVE_EAPOL_RELAY
|
||||
|
||||
#define TRACE_GROUP "wser"
|
||||
|
||||
typedef struct {
|
||||
protocol_interface_info_entry_t *interface_ptr; /**< Interface pointer */
|
||||
ns_address_t remote_addr; /**< Remote address (border router address) */
|
||||
int8_t socket_id; /**< Socket ID for relay */
|
||||
ns_list_link_t link; /**< Link */
|
||||
} eapol_relay_t;
|
||||
|
||||
static eapol_relay_t *ws_eapol_relay_get(protocol_interface_info_entry_t *interface_ptr);
|
||||
static int8_t ws_eapol_relay_eapol_pdu_address_check(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
|
||||
static int8_t ws_eapol_relay_eapol_pdu_receive(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *pdu, uint16_t size);
|
||||
static void ws_eapol_relay_socket_cb(void *cb);
|
||||
|
||||
static const eapol_pdu_recv_cb_data_t eapol_pdu_recv_cb_data = {
|
||||
.priority = EAPOL_PDU_RECV_LOW_PRIORITY,
|
||||
.addr_check = ws_eapol_relay_eapol_pdu_address_check,
|
||||
.receive = ws_eapol_relay_eapol_pdu_receive
|
||||
};
|
||||
|
||||
static NS_LIST_DEFINE(eapol_relay_list, eapol_relay_t, link);
|
||||
|
||||
int8_t ws_eapol_relay_start(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port)
|
||||
{
|
||||
if (!interface_ptr || !remote_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_eapol_relay_get(interface_ptr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
eapol_relay_t *eapol_relay = ns_dyn_mem_alloc(sizeof(eapol_relay_t));
|
||||
if (!eapol_relay) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_relay->interface_ptr = interface_ptr;
|
||||
|
||||
eapol_relay->remote_addr.type = ADDRESS_IPV6;
|
||||
memcpy(&eapol_relay->remote_addr.address, remote_addr, 16);
|
||||
eapol_relay->remote_addr.identifier = remote_port;
|
||||
|
||||
eapol_relay->socket_id = socket_open(IPV6_NH_UDP, local_port, &ws_eapol_relay_socket_cb);
|
||||
if (eapol_relay->socket_id < 0) {
|
||||
ns_dyn_mem_free(eapol_relay);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_eapol_pdu_cb_register(interface_ptr, &eapol_pdu_recv_cb_data) < 0) {
|
||||
ns_dyn_mem_free(eapol_relay);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ns_list_add_to_end(&eapol_relay_list, eapol_relay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_eapol_relay_delete(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
eapol_relay_t *eapol_relay = ws_eapol_relay_get(interface_ptr);
|
||||
if (!eapol_relay) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket_close(eapol_relay->socket_id);
|
||||
|
||||
ws_eapol_pdu_cb_unregister(interface_ptr, &eapol_pdu_recv_cb_data);
|
||||
|
||||
ns_list_remove(&eapol_relay_list, eapol_relay);
|
||||
ns_dyn_mem_free(eapol_relay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static eapol_relay_t *ws_eapol_relay_get(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
ns_list_foreach(eapol_relay_t, entry, &eapol_relay_list) {
|
||||
if (entry->interface_ptr == interface_ptr) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int8_t ws_eapol_relay_eapol_pdu_address_check(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
|
||||
{
|
||||
(void) eui_64;
|
||||
(void) interface_ptr;
|
||||
|
||||
// Low priority, always route all here if asked
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t ws_eapol_relay_eapol_pdu_receive(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64, void *pdu, uint16_t size)
|
||||
{
|
||||
eapol_relay_t *eapol_relay = ws_eapol_relay_get(interface_ptr);
|
||||
if (!eapol_relay) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_eapol_relay_lib_send_to_relay(eapol_relay->socket_id, eui_64, &eapol_relay->remote_addr, pdu, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ws_eapol_relay_socket_cb(void *cb)
|
||||
{
|
||||
socket_callback_t *cb_data = cb;
|
||||
|
||||
if (cb_data->event_type != SOCKET_DATA) {
|
||||
return;
|
||||
}
|
||||
|
||||
eapol_relay_t *eapol_relay = NULL;
|
||||
|
||||
ns_list_foreach(eapol_relay_t, entry, &eapol_relay_list) {
|
||||
if (entry->socket_id == cb_data->socket_id) {
|
||||
eapol_relay = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!eapol_relay) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *socket_pdu = ns_dyn_mem_temporary_alloc(cb_data->d_len);
|
||||
if (!socket_pdu) {
|
||||
return;
|
||||
}
|
||||
|
||||
ns_address_t src_addr;
|
||||
|
||||
if (socket_recvfrom(cb_data->socket_id, socket_pdu, cb_data->d_len, 0, &src_addr) != cb_data->d_len) {
|
||||
ns_dyn_mem_free(socket_pdu);
|
||||
return;
|
||||
}
|
||||
|
||||
//First 8 byte is EUID64 and rsr payload
|
||||
if (ws_eapol_pdu_send_to_mpx(eapol_relay->interface_ptr, socket_pdu, socket_pdu + 8, cb_data->d_len - 8, socket_pdu) < 0) {
|
||||
ns_dyn_mem_free(socket_pdu);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_EAPOL_RELAY */
|
||||
#endif /* HAVE_WS */
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_EAPOL_RELAY_H_
|
||||
#define WS_EAPOL_RELAY_H_
|
||||
|
||||
#ifdef HAVE_EAPOL_RELAY
|
||||
|
||||
/*
|
||||
* EAPOL relay conveys EAPOL PDUs between authenticator EAPOL relay and local
|
||||
* MPX interface.
|
||||
*
|
||||
* On supplicant (i.e. node) relay should be bound to UDP port 10253 (local
|
||||
* port parameter).
|
||||
*
|
||||
* On authenticator (border router) relay will need to use some other port than
|
||||
* 10253 since authenticator EAPOL relay is bound to port 10253.
|
||||
*
|
||||
* Border router address needs to be set on start (remote address and remote port
|
||||
* parameter).
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* ws_eapol_relay_start start EAPOL relay
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param local_port local port
|
||||
* \param remote_addr remote address (border router relay address)
|
||||
* \param remote_port remote port (border router relay port)
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_relay_start(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port);
|
||||
|
||||
/**
|
||||
* ws_eapol_relay_delete delete EAPOL
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_eapol_relay_delete(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
#else
|
||||
|
||||
#define ws_eapol_relay_start(interface_ptr, local_port, remote_addr, remote_port);
|
||||
#define ws_eapol_relay_delete(interface_ptr);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WS_EAPOL_RELAY_H_ */
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "socket_api.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_eapol_relay_lib.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
#define TRACE_GROUP "wsrl"
|
||||
|
||||
int8_t ws_eapol_relay_lib_send_to_relay(const uint8_t socket_id, const uint8_t *eui_64, const ns_address_t *dest_addr, const void *data, uint16_t data_len)
|
||||
{
|
||||
ns_address_t addr = *dest_addr;
|
||||
|
||||
ns_iovec_t msg_iov[2];
|
||||
ns_msghdr_t msghdr;
|
||||
//Set messages name buffer
|
||||
msghdr.msg_name = &addr;
|
||||
msghdr.msg_namelen = sizeof(addr);
|
||||
msghdr.msg_iov = &msg_iov[0];
|
||||
msghdr.msg_iovlen = 2;
|
||||
msghdr.msg_control = NULL;
|
||||
msghdr.msg_controllen = 0;
|
||||
msg_iov[0].iov_base = (void *)eui_64;
|
||||
msg_iov[0].iov_len = 8;
|
||||
msg_iov[1].iov_base = (void *)data;
|
||||
msg_iov[1].iov_len = data_len;
|
||||
socket_sendmsg(socket_id, &msghdr, NS_MSG_LEGACY0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_WS */
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_EAPOL_RELAY_LIB_H_
|
||||
#define WS_EAPOL_RELAY_LIB_H_
|
||||
|
||||
int8_t ws_eapol_relay_lib_send_to_relay(const uint8_t socket_id, const uint8_t *eui_64, const ns_address_t *dest_addr, const void *data, uint16_t data_len);
|
||||
|
||||
#endif /* WS_EAPOL_RELAY_LIB_H_ */
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -53,6 +53,15 @@ int ws_management_regulatory_domain_set(
|
|||
return -1;
|
||||
}
|
||||
|
||||
int ws_management_network_size_set(
|
||||
int8_t interface_id,
|
||||
uint8_t network_size)
|
||||
{
|
||||
(void)interface_id;
|
||||
(void)network_size;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_management_channel_mask_set(
|
||||
int8_t interface_id,
|
||||
uint32_t channel_mask[8])
|
||||
|
@ -129,6 +138,48 @@ int ws_test_pan_size_set(int8_t interface_id, uint16_t pan_size)
|
|||
(void) pan_size;
|
||||
return -1;
|
||||
}
|
||||
int ws_test_max_child_count_set(int8_t interface_id, uint16_t child_count)
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) child_count;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_test_gtk_set(int8_t interface_id, uint8_t *gtk[4])
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) gtk;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_test_active_key_set(int8_t interface_id, uint8_t index)
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) index;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_test_key_lifetime_set(int8_t interface_id, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime)
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) gtk_lifetime;
|
||||
(void) pmk_lifetime;
|
||||
(void) ptk_lifetime;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ws_test_gtk_time_settings_set(int8_t interface_id, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint32_t max_mismatch)
|
||||
{
|
||||
(void) interface_id;
|
||||
(void) revocat_lifetime_reduct;
|
||||
(void) new_activation_time;
|
||||
(void) max_mismatch;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif // no HAVE_WS
|
||||
|
||||
|
|
|
@ -0,0 +1,557 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "common_functions.h"
|
||||
#include "mac_common_defines.h"
|
||||
#include "6LoWPAN/MAC/mac_ie_lib.h"
|
||||
#include "6LoWPAN/ws/ws_common_defines.h"
|
||||
#include "6LoWPAN/ws/ws_ie_lib.h"
|
||||
|
||||
static uint8_t *ws_wh_header_base_write(uint8_t *ptr, uint16_t length, uint8_t type)
|
||||
{
|
||||
ptr = mac_ie_header_base_write(ptr, MAC_HEADER_ASSIGNED_EXTERNAL_ORG_IE_ID, length + 1);
|
||||
*ptr++ = type;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static uint16_t ws_channel_plan_length(uint8_t channel_plan)
|
||||
{
|
||||
switch (channel_plan) {
|
||||
case 0:
|
||||
//Regulator domain and operationg class inline
|
||||
return 2;
|
||||
case 1:
|
||||
//CHo, Channel spasing and number of channel's inline
|
||||
return 6;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t ws_channel_function_length(uint8_t channel_function, uint16_t hop_channel_count)
|
||||
{
|
||||
switch (channel_function) {
|
||||
case 0:
|
||||
//Fixed channel inline
|
||||
return 2;
|
||||
case 1:
|
||||
case 2:
|
||||
return 0;
|
||||
case 3:
|
||||
//Hop count + channel hop list
|
||||
return (1 + hop_channel_count);
|
||||
default:
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ws_wp_nested_hopping_schedule_length(struct ws_hopping_schedule_s *hopping_schedule, bool unicast_schedule)
|
||||
{
|
||||
uint16_t length;
|
||||
uint8_t channel_function;
|
||||
if (unicast_schedule) {
|
||||
length = 4;
|
||||
channel_function = hopping_schedule->uc_channel_function;
|
||||
} else {
|
||||
length = 10;
|
||||
channel_function = hopping_schedule->bc_channel_function;
|
||||
}
|
||||
|
||||
length += ws_channel_plan_length(hopping_schedule->channel_plan);
|
||||
|
||||
length += ws_channel_function_length(channel_function, 1);
|
||||
|
||||
//Todo Derive some how exluded channel control
|
||||
return length;
|
||||
}
|
||||
|
||||
uint8_t *ws_wh_utt_write(uint8_t *ptr, uint8_t message_type)
|
||||
{
|
||||
ptr = ws_wh_header_base_write(ptr, 4, WH_IE_UTT_TYPE);
|
||||
*ptr++ = message_type;
|
||||
memset(ptr, 0, 3);
|
||||
ptr += 3;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *ws_wh_bt_write(uint8_t *ptr)
|
||||
{
|
||||
ptr = ws_wh_header_base_write(ptr, 5, WH_IE_BT_TYPE);
|
||||
memset(ptr, 0, 5);
|
||||
ptr += 5;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *ws_wh_fc_write(uint8_t *ptr, uint8_t flow_ctrl)
|
||||
{
|
||||
ptr = ws_wh_header_base_write(ptr, 1, WH_IE_FC_TYPE);
|
||||
*ptr++ = flow_ctrl;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *ws_wh_rsl_write(uint8_t *ptr, int8_t rssi)
|
||||
{
|
||||
ptr = ws_wh_header_base_write(ptr, 1, WH_IE_RSL_TYPE);
|
||||
*ptr++ = rssi;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *ws_wh_ea_write(uint8_t *ptr, uint8_t *eui64)
|
||||
{
|
||||
ptr = ws_wh_header_base_write(ptr, 8, WH_IE_EA_TYPE);
|
||||
memcpy(ptr, eui64, 8);
|
||||
ptr += 8;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *ws_wh_vh_write(uint8_t *ptr, uint8_t *vendor_header, uint8_t vendor_header_length)
|
||||
{
|
||||
ptr = ws_wh_header_base_write(ptr, vendor_header_length, WH_IE_VH_TYPE);
|
||||
if (vendor_header_length) {
|
||||
memcpy(ptr, vendor_header, vendor_header_length);
|
||||
ptr += vendor_header_length;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *ws_wp_base_write(uint8_t *ptr, uint16_t length)
|
||||
{
|
||||
return mac_ie_payload_base_write(ptr, WS_WP_NESTED_IE, length);
|
||||
}
|
||||
|
||||
uint8_t *ws_wp_nested_hopping_schedule_write(uint8_t *ptr, struct ws_hopping_schedule_s *hopping_schedule, bool unicast_schedule)
|
||||
{
|
||||
//Calculate length
|
||||
uint16_t length = ws_wp_nested_hopping_schedule_length(hopping_schedule, unicast_schedule);
|
||||
if (!unicast_schedule) {
|
||||
ptr = mac_ie_nested_ie_long_base_write(ptr, WP_PAYLOAD_IE_BS_TYPE, length);
|
||||
ptr = common_write_32_bit_inverse(hopping_schedule->fhss_broadcast_interval, ptr);
|
||||
ptr = common_write_16_bit_inverse(hopping_schedule->fhss_bsi, ptr);
|
||||
*ptr++ = hopping_schedule->fhss_bc_dwell_interval;
|
||||
} else {
|
||||
ptr = mac_ie_nested_ie_long_base_write(ptr, WP_PAYLOAD_IE_US_TYPE, length);
|
||||
*ptr++ = hopping_schedule->fhss_uc_dwell_interval;
|
||||
}
|
||||
|
||||
*ptr++ = hopping_schedule->clock_drift;
|
||||
*ptr++ = hopping_schedule->timing_accurancy;
|
||||
uint8_t channel_info_base = 0;
|
||||
channel_info_base = (hopping_schedule->channel_plan);
|
||||
if (unicast_schedule) {
|
||||
channel_info_base |= (hopping_schedule->uc_channel_function << 3);
|
||||
} else {
|
||||
channel_info_base |= (hopping_schedule->bc_channel_function << 3);
|
||||
}
|
||||
//Todo define excluded channel ctrl
|
||||
|
||||
*ptr++ = channel_info_base;
|
||||
|
||||
switch (hopping_schedule->channel_plan) {
|
||||
case 0:
|
||||
//Regulator domain and operationg class inline
|
||||
*ptr++ = hopping_schedule->regulatory_domain;
|
||||
*ptr++ = hopping_schedule->operating_class;
|
||||
break;
|
||||
case 1:
|
||||
//CHo, Channel spasing and number of channel's inline
|
||||
ptr = common_write_24_bit(hopping_schedule->fhss_uc_dwell_interval, ptr);
|
||||
*ptr++ = ((hopping_schedule->channel_spacing << 4) & 0xf0);
|
||||
ptr = common_write_16_bit(hopping_schedule->number_of_channels, ptr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uint8_t cf = hopping_schedule->uc_channel_function;
|
||||
uint16_t fixed_channel = hopping_schedule->uc_fixed_channel;
|
||||
if (!unicast_schedule) {
|
||||
cf = hopping_schedule->bc_channel_function;
|
||||
}
|
||||
switch (cf) {
|
||||
case 0:
|
||||
//Fixed channel inline
|
||||
if (!unicast_schedule) {
|
||||
fixed_channel = hopping_schedule->bc_fixed_channel;
|
||||
}
|
||||
ptr = common_write_16_bit_inverse(fixed_channel, ptr);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
//No Inline
|
||||
break;
|
||||
case 3:
|
||||
//TODO do this properly
|
||||
//Hop count + channel hop list
|
||||
*ptr++ = 1;
|
||||
*ptr++ = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *ws_wp_nested_vp_write(uint8_t *ptr, uint8_t *vendor_payload, uint16_t vendor_payload_length)
|
||||
{
|
||||
if (vendor_payload_length) {
|
||||
ptr = mac_ie_nested_ie_long_base_write(ptr, WP_PAYLOAD_IE_VP_TYPE, vendor_payload_length);
|
||||
memcpy(ptr, vendor_payload, vendor_payload_length);
|
||||
ptr += vendor_payload_length;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *ws_wp_nested_pan_info_write(uint8_t *ptr, struct ws_pan_information_s *pan_congiguration)
|
||||
{
|
||||
if (!pan_congiguration) {
|
||||
return mac_ie_nested_ie_short_base_write(ptr, WP_PAYLOAD_IE_PAN_TYPE, 0);
|
||||
}
|
||||
ptr = mac_ie_nested_ie_short_base_write(ptr, WP_PAYLOAD_IE_PAN_TYPE, 5);
|
||||
ptr = common_write_16_bit_inverse(pan_congiguration->pan_size, ptr);
|
||||
ptr = common_write_16_bit_inverse(pan_congiguration->routing_cost, ptr);
|
||||
uint8_t temp8 = 0;
|
||||
temp8 |= (pan_congiguration->use_parent_bs << 0);
|
||||
temp8 |= (pan_congiguration->rpl_routing_method << 1);
|
||||
temp8 |= pan_congiguration->version << 5;
|
||||
*ptr++ = temp8;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *ws_wp_nested_netname_write(uint8_t *ptr, uint8_t *network_name, uint8_t network_name_length)
|
||||
{
|
||||
ptr = mac_ie_nested_ie_short_base_write(ptr, WP_PAYLOAD_IE_NETNAME_TYPE, network_name_length);
|
||||
if (network_name_length) {
|
||||
memcpy(ptr, network_name, network_name_length);
|
||||
ptr += network_name_length;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *ws_wp_nested_pan_ver_write(uint8_t *ptr, struct ws_pan_information_s *pan_congiguration)
|
||||
{
|
||||
if (!pan_congiguration) {
|
||||
return ptr;
|
||||
}
|
||||
ptr = mac_ie_nested_ie_short_base_write(ptr, WP_PAYLOAD_IE_PAN_VER_TYPE, 2);
|
||||
return common_write_16_bit_inverse(pan_congiguration->pan_version, ptr);
|
||||
}
|
||||
|
||||
uint8_t *ws_wp_nested_gtkhash_write(uint8_t *ptr, uint8_t *gtkhash, uint8_t gtkhash_length)
|
||||
{
|
||||
ptr = mac_ie_nested_ie_short_base_write(ptr, WP_PAYLOAD_IE_GTKHASH_TYPE, gtkhash_length);
|
||||
if (gtkhash_length) {
|
||||
memcpy(ptr, gtkhash, 32);
|
||||
ptr += 32;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool ws_wh_utt_read(uint8_t *data, uint16_t length, struct ws_utt_ie *utt_ie)
|
||||
{
|
||||
mac_header_IE_t utt_ie_data;
|
||||
utt_ie_data.id = MAC_HEADER_ASSIGNED_EXTERNAL_ORG_IE_ID;
|
||||
if (4 != mac_ie_header_sub_id_discover(data, length, &utt_ie_data, WH_IE_UTT_TYPE)) {
|
||||
// NO UTT header
|
||||
return false;
|
||||
}
|
||||
data = utt_ie_data.content_ptr;
|
||||
utt_ie->message_type = *data++;
|
||||
utt_ie->ufsi = common_read_24_bit_inverse(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ws_wh_bt_read(uint8_t *data, uint16_t length, struct ws_bt_ie *bt_ie)
|
||||
{
|
||||
mac_header_IE_t btt_ie_data;
|
||||
btt_ie_data.id = MAC_HEADER_ASSIGNED_EXTERNAL_ORG_IE_ID;
|
||||
if (5 != mac_ie_header_sub_id_discover(data, length, &btt_ie_data, WH_IE_BT_TYPE)) {
|
||||
return false;
|
||||
}
|
||||
data = btt_ie_data.content_ptr;
|
||||
bt_ie->broadcast_slot_number = common_read_16_bit_inverse(data);
|
||||
bt_ie->broadcast_interval_offset = common_read_24_bit_inverse(data + 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ws_wh_rsl_read(uint8_t *data, uint16_t length, int8_t *rsl)
|
||||
{
|
||||
mac_header_IE_t rsl_ie_data;
|
||||
rsl_ie_data.id = MAC_HEADER_ASSIGNED_EXTERNAL_ORG_IE_ID;
|
||||
if (1 != mac_ie_header_sub_id_discover(data, length, &rsl_ie_data, WH_IE_RSL_TYPE)) {
|
||||
return false;
|
||||
}
|
||||
*rsl = *rsl_ie_data.content_ptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ws_wh_ea_read(uint8_t *data, uint16_t length, uint8_t *eui64)
|
||||
{
|
||||
mac_header_IE_t rsl_ie_data;
|
||||
rsl_ie_data.id = MAC_HEADER_ASSIGNED_EXTERNAL_ORG_IE_ID;
|
||||
if (8 != mac_ie_header_sub_id_discover(data, length, &rsl_ie_data, WH_IE_EA_TYPE)) {
|
||||
return false;
|
||||
}
|
||||
memcpy(eui64, rsl_ie_data.content_ptr, 8);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t *ws_channel_plan_zero_read(uint8_t *ptr, ws_channel_plan_zero_t *plan)
|
||||
{
|
||||
plan->regulator_domain = *ptr++;
|
||||
plan->operation_class = *ptr++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static uint8_t *ws_channel_plan_one_read(uint8_t *ptr, ws_channel_plan_one_t *plan)
|
||||
{
|
||||
plan->ch0 = common_read_24_bit_inverse(ptr);
|
||||
ptr += 3;
|
||||
plan->channel_spacing = (*ptr++ & 0xf0) >> 4;
|
||||
plan->number_of_channel = common_read_16_bit_inverse(ptr);
|
||||
ptr += 2;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static uint8_t *ws_channel_function_zero_read(uint8_t *ptr, ws_channel_function_zero_t *plan)
|
||||
{
|
||||
plan->fixed_channel = common_read_16_bit_inverse(ptr);
|
||||
return ptr + 2;
|
||||
}
|
||||
|
||||
static uint8_t *ws_channel_function_three_read(uint8_t *ptr, ws_channel_function_three_t *plan)
|
||||
{
|
||||
plan->channel_hop_count = *ptr++;
|
||||
plan->channel_list = ptr++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool ws_wp_nested_us_read(uint8_t *data, uint16_t length, struct ws_us_ie *us_ie)
|
||||
{
|
||||
mac_nested_payload_IE_t nested_payload_ie;
|
||||
nested_payload_ie.id = WP_PAYLOAD_IE_US_TYPE;
|
||||
nested_payload_ie.type_long = true;
|
||||
if (mac_ie_nested_discover(data, length, &nested_payload_ie) < 4) {
|
||||
return false;
|
||||
}
|
||||
data = nested_payload_ie.content_ptr;
|
||||
us_ie->dwell_interval = *data++;
|
||||
us_ie->clock_drift = *data++;
|
||||
us_ie->timing_accurancy = *data++;
|
||||
us_ie->channel_plan = (*data & 3);
|
||||
us_ie->channel_function = (*data & 0x38) >> 3;
|
||||
us_ie->excluded_channel_ctrl = (*data & 0xc0) >> 6;
|
||||
data++;
|
||||
uint16_t info_length = 0;
|
||||
nested_payload_ie.length -= 4;
|
||||
info_length = ws_channel_plan_length(us_ie->channel_plan);
|
||||
if (nested_payload_ie.length < info_length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nested_payload_ie.length -= info_length;
|
||||
switch (us_ie->channel_plan) {
|
||||
case 0:
|
||||
data = ws_channel_plan_zero_read(data, &us_ie->plan.zero);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
data = ws_channel_plan_one_read(data, &us_ie->plan.one);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
info_length = ws_channel_function_length(us_ie->channel_function, 0);
|
||||
|
||||
if (nested_payload_ie.length < info_length) {
|
||||
return false;
|
||||
}
|
||||
nested_payload_ie.length -= info_length;
|
||||
|
||||
|
||||
switch (us_ie->channel_function) {
|
||||
case 0:
|
||||
data = ws_channel_function_zero_read(data, &us_ie->function.zero);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
||||
data = ws_channel_function_three_read(data, &us_ie->function.three);
|
||||
info_length = us_ie->function.three.channel_hop_count;
|
||||
if (nested_payload_ie.length < info_length) {
|
||||
return false;
|
||||
}
|
||||
nested_payload_ie.length -= info_length;
|
||||
data += info_length;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool ws_wp_nested_bs_read(uint8_t *data, uint16_t length, struct ws_bs_ie *bs_ie)
|
||||
{
|
||||
mac_nested_payload_IE_t nested_payload_ie;
|
||||
nested_payload_ie.id = WP_PAYLOAD_IE_BS_TYPE;
|
||||
nested_payload_ie.type_long = true;
|
||||
if (mac_ie_nested_discover(data, length, &nested_payload_ie) < 10) {
|
||||
return false;
|
||||
}
|
||||
data = nested_payload_ie.content_ptr;
|
||||
bs_ie->broadcast_interval = common_read_32_bit_inverse(data);
|
||||
bs_ie->broadcast_schedule_identifier = common_read_16_bit_inverse(data + 4);
|
||||
data += 6;
|
||||
bs_ie->dwell_interval = *data++;
|
||||
bs_ie->clock_drift = *data++;
|
||||
bs_ie->timing_accurancy = *data++;
|
||||
|
||||
bs_ie->channel_plan = (*data & 3);
|
||||
bs_ie->channel_function = (*data & 0x38) >> 3;
|
||||
bs_ie->excluded_channel_ctrl = (*data & 0xc0) >> 6;
|
||||
data++;
|
||||
nested_payload_ie.length -= 10;
|
||||
uint16_t info_length = 0;
|
||||
|
||||
info_length = ws_channel_plan_length(bs_ie->channel_plan);
|
||||
if (nested_payload_ie.length < info_length) {
|
||||
return false;
|
||||
}
|
||||
nested_payload_ie.length -= info_length;
|
||||
switch (bs_ie->channel_plan) {
|
||||
case 0:
|
||||
data = ws_channel_plan_zero_read(data, &bs_ie->plan.zero);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
data = ws_channel_plan_one_read(data, &bs_ie->plan.one);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
info_length = ws_channel_function_length(bs_ie->channel_function, 0);
|
||||
if (nested_payload_ie.length < info_length) {
|
||||
return false;
|
||||
}
|
||||
nested_payload_ie.length -= info_length;
|
||||
|
||||
switch (bs_ie->channel_function) {
|
||||
case 0:
|
||||
data = ws_channel_function_zero_read(data, &bs_ie->function.zero);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
break;
|
||||
|
||||
case 3:
|
||||
data = ws_channel_function_three_read(data, &bs_ie->function.three);
|
||||
info_length = bs_ie->function.three.channel_hop_count;
|
||||
if (nested_payload_ie.length < info_length) {
|
||||
return false;
|
||||
}
|
||||
nested_payload_ie.length -= info_length;
|
||||
data += info_length;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ws_wp_nested_pan_read(uint8_t *data, uint16_t length, struct ws_pan_information_s *pan_congiguration)
|
||||
{
|
||||
mac_nested_payload_IE_t nested_payload_ie;
|
||||
nested_payload_ie.id = WP_PAYLOAD_IE_PAN_TYPE;
|
||||
nested_payload_ie.type_long = false;
|
||||
if (mac_ie_nested_discover(data, length, &nested_payload_ie) != 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pan_congiguration->pan_size = common_read_16_bit_inverse(nested_payload_ie.content_ptr);
|
||||
pan_congiguration->routing_cost = common_read_16_bit_inverse(nested_payload_ie.content_ptr + 2);
|
||||
pan_congiguration->use_parent_bs = (nested_payload_ie.content_ptr[4] & 0x01) == 0x01;
|
||||
pan_congiguration->rpl_routing_method = (nested_payload_ie.content_ptr[4] & 0x02) == 0x02;
|
||||
pan_congiguration->version = (nested_payload_ie.content_ptr[4] & 0xe0) >> 5;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ws_wp_nested_pan_version_read(uint8_t *data, uint16_t length, uint16_t *pan_version)
|
||||
{
|
||||
mac_nested_payload_IE_t nested_payload_ie;
|
||||
nested_payload_ie.id = WP_PAYLOAD_IE_PAN_VER_TYPE;
|
||||
nested_payload_ie.type_long = false;
|
||||
if (mac_ie_nested_discover(data, length, &nested_payload_ie) != 2) {
|
||||
return false;
|
||||
}
|
||||
*pan_version = common_read_16_bit_inverse(nested_payload_ie.content_ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t *ws_wp_nested_gtkhash_read(uint8_t *data, uint16_t length)
|
||||
{
|
||||
mac_nested_payload_IE_t nested_payload_ie;
|
||||
nested_payload_ie.id = WP_PAYLOAD_IE_GTKHASH_TYPE;
|
||||
nested_payload_ie.type_long = false;
|
||||
if (mac_ie_nested_discover(data, length, &nested_payload_ie) != 32) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nested_payload_ie.content_ptr;
|
||||
}
|
||||
|
||||
|
||||
bool ws_wp_nested_network_name_read(uint8_t *data, uint16_t length, ws_wp_network_name_t *network_name)
|
||||
{
|
||||
mac_nested_payload_IE_t nested_payload_ie;
|
||||
nested_payload_ie.id = WP_PAYLOAD_IE_NETNAME_TYPE;
|
||||
nested_payload_ie.type_long = false;
|
||||
|
||||
if (0 == mac_ie_nested_discover(data, length, &nested_payload_ie)) {
|
||||
return false;
|
||||
} else if (nested_payload_ie.length > 32) {
|
||||
//Too long name
|
||||
return false;
|
||||
}
|
||||
network_name->network_name = nested_payload_ie.content_ptr;
|
||||
network_name->network_name_length = nested_payload_ie.length;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_IE_LIB_H_
|
||||
#define WS_IE_LIB_H_
|
||||
|
||||
struct ws_pan_information_s;
|
||||
struct ws_utt_ie;
|
||||
struct ws_bt_ie;
|
||||
struct ws_us_ie;
|
||||
struct ws_hopping_schedule_s;
|
||||
|
||||
/**
|
||||
* @brief ws_wp_network_name_t WS nested payload network name
|
||||
*/
|
||||
typedef struct ws_wp_network_name {
|
||||
uint8_t network_name_length;
|
||||
uint8_t *network_name;
|
||||
} ws_wp_network_name_t;
|
||||
|
||||
/* WS_WH HEADER IE */
|
||||
uint8_t *ws_wh_utt_write(uint8_t *ptr, uint8_t message_type);
|
||||
uint8_t *ws_wh_bt_write(uint8_t *ptr);
|
||||
uint8_t *ws_wh_fc_write(uint8_t *ptr, uint8_t flow_ctrl);
|
||||
uint8_t *ws_wh_rsl_write(uint8_t *ptr, int8_t rssi);
|
||||
uint8_t *ws_wh_vh_write(uint8_t *ptr, uint8_t *vendor_header, uint8_t vendor_header_length);
|
||||
uint8_t *ws_wh_ea_write(uint8_t *ptr, uint8_t *eui64);
|
||||
|
||||
bool ws_wh_utt_read(uint8_t *data, uint16_t length, struct ws_utt_ie *utt_ie);
|
||||
bool ws_wh_bt_read(uint8_t *data, uint16_t length, struct ws_bt_ie *bt_ie);
|
||||
bool ws_wh_rsl_read(uint8_t *data, uint16_t length, int8_t *rsl);
|
||||
bool ws_wh_ea_read(uint8_t *data, uint16_t length, uint8_t *eui64);
|
||||
|
||||
/* WS_WP_NESTED PAYLOD IE */
|
||||
uint8_t *ws_wp_base_write(uint8_t *ptr, uint16_t length);
|
||||
uint8_t *ws_wp_nested_hopping_schedule_write(uint8_t *ptr, struct ws_hopping_schedule_s *hopping_schedule, bool unicast_schedule);
|
||||
uint8_t *ws_wp_nested_vp_write(uint8_t *ptr, uint8_t *vendor_payload, uint16_t vendor_payload_length);
|
||||
uint8_t *ws_wp_nested_pan_info_write(uint8_t *ptr, struct ws_pan_information_s *pan_congiguration);
|
||||
uint8_t *ws_wp_nested_netname_write(uint8_t *ptr, uint8_t *network_name, uint8_t network_name_length);
|
||||
uint8_t *ws_wp_nested_pan_ver_write(uint8_t *ptr, struct ws_pan_information_s *pan_congiguration);
|
||||
uint8_t *ws_wp_nested_gtkhash_write(uint8_t *ptr, uint8_t *gtkhash, uint8_t gtkhash_length);
|
||||
uint16_t ws_wp_nested_hopping_schedule_length(struct ws_hopping_schedule_s *hopping_schedule, bool unicast_schedule);
|
||||
|
||||
bool ws_wp_nested_us_read(uint8_t *data, uint16_t length, struct ws_us_ie *us_ie);
|
||||
bool ws_wp_nested_bs_read(uint8_t *data, uint16_t length, struct ws_bs_ie *bs_ie);
|
||||
bool ws_wp_nested_pan_read(uint8_t *data, uint16_t length, struct ws_pan_information_s *pan_congiguration);
|
||||
bool ws_wp_nested_pan_version_read(uint8_t *data, uint16_t length, uint16_t *pan_version);
|
||||
bool ws_wp_nested_network_name_read(uint8_t *data, uint16_t length, ws_wp_network_name_t *network_name);
|
||||
uint8_t *ws_wp_nested_gtkhash_read(uint8_t *data, uint16_t length);
|
||||
|
||||
|
||||
#endif /* WS_IE_LIB_H_ */
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_LLC_H_
|
||||
#define WS_LLC_H_
|
||||
|
||||
#include "6LoWPAN/ws/ws_neighbor_class.h"
|
||||
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
||||
|
||||
struct protocol_interface_info_entry;
|
||||
struct mcps_data_ind_s;
|
||||
struct mcps_data_ie_list;
|
||||
struct channel_list_s;
|
||||
struct ws_pan_information_s;
|
||||
struct mlme_security_s;
|
||||
struct ws_hopping_schedule_s;
|
||||
struct ws_neighbor_class_entry;
|
||||
struct mac_neighbor_table_entry;
|
||||
|
||||
|
||||
/**
|
||||
* @brief wh_ie_sub_list_t ws asynch header IE elemnt request list
|
||||
*/
|
||||
typedef struct wh_ie_sub_list_s {
|
||||
bool utt_ie: 1; /**< Unicast Timing and Frame type information */
|
||||
bool bt_ie: 1; /**< Broadcast timing information */
|
||||
bool fc_ie: 1; /**< Flow Control for Extended Direct Frame Exchange */
|
||||
bool rsl_ie: 1; /**< Received Signal Level information */
|
||||
bool vh_ie: 1; /**< Vendor header information */
|
||||
bool ea_ie: 1; /**< EAPOL autheticator EUI-64 header information */
|
||||
} wh_ie_sub_list_t;
|
||||
|
||||
/**
|
||||
* @brief wp_nested_ie_sub_list_t ws asynch Nested Payload sub IE element request list
|
||||
*/
|
||||
typedef struct wp_nested_ie_sub_list_s {
|
||||
bool us_ie: 1; /**< Unicast Schedule information */
|
||||
bool bs_ie: 1; /**< Broadcast Schedule information */
|
||||
bool vp_ie: 1; /**< Vendor Payload information */
|
||||
bool pan_ie: 1; /**< PAN Information */
|
||||
bool net_name_ie: 1; /**< Network Name information */
|
||||
bool pan_version_ie: 1; /**< Pan configuration version */
|
||||
bool gtkhash_ie: 1; /**< GTK Hash information */
|
||||
} wp_nested_ie_sub_list_t;
|
||||
|
||||
/**
|
||||
* @brief asynch_request_t Asynch message request parameters
|
||||
*/
|
||||
typedef struct asynch_request_s {
|
||||
unsigned message_type: 3; /**< Asynch message type: WS_FT_PAN_ADVERT, WS_FT_PAN_ADVERT_SOL, WS_FT_PAN_CONF or WS_FT_PAN_CONF_SOL. */
|
||||
wh_ie_sub_list_t wh_requested_ie_list; /**< WH-IE header list to message. */
|
||||
wp_nested_ie_sub_list_t wp_requested_nested_ie_list; /**< WP-IE Nested IE list to message. */
|
||||
struct mlme_security_s security; /**< Request MAC security paramaters */
|
||||
struct channel_list_s channel_list; /**< Channel List. */
|
||||
} asynch_request_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief LLC neighbour info request parameters
|
||||
*/
|
||||
typedef struct llc_neighbour_req {
|
||||
struct mac_neighbor_table_entry *neighbor; /**< Generic Link Layer Neighbor information entry. */
|
||||
struct ws_neighbor_class_entry *ws_neighbor; /**< Wi-sun Neighbor information entry. */
|
||||
} llc_neighbour_req_t;
|
||||
|
||||
/**
|
||||
* @brief ws_asynch_ind ws asynch data indication
|
||||
* @param interface Interface pointer
|
||||
* @param data MCPS-DATA.indication specific values
|
||||
* @param ie_ext Information element list
|
||||
*/
|
||||
typedef void ws_asynch_ind(struct protocol_interface_info_entry *interface, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, uint8_t message_type);
|
||||
|
||||
/**
|
||||
* @brief ws_asynch_confirm ws asynch data confirmation to asynch message request
|
||||
* @param api The API which handled the response
|
||||
* @param data MCPS-DATA.confirm specific values
|
||||
* @param user_id MPX user ID
|
||||
*/
|
||||
typedef void ws_asynch_confirm(struct protocol_interface_info_entry *interface, uint8_t asynch_message);
|
||||
|
||||
/**
|
||||
* @brief ws_asynch_confirm ws asynch data confirmation to asynch message request
|
||||
* @param interface The interface pointer
|
||||
* @param mac_64 Neighbor 64-bit address
|
||||
* @param neighbor_buffer Buffer where neighbor infor is buffered
|
||||
* @param request_new true if is possible to allocate new entry
|
||||
*
|
||||
* @return true when neighbor info is available
|
||||
* @return false when no neighbor info
|
||||
*/
|
||||
typedef bool ws_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new);
|
||||
|
||||
/**
|
||||
* @brief ws_llc_create ws LLC module create
|
||||
* @param interface Interface pointer
|
||||
* @param asynch_ind_cb Asynch indication
|
||||
* @param ie_ext Information element list
|
||||
*
|
||||
* Function allocate and init LLC class and init it 2 supported 2 API: ws asynch and MPX user are internally registered.
|
||||
*/
|
||||
int8_t ws_llc_create(struct protocol_interface_info_entry *interface, ws_asynch_ind *asynch_ind_cb, ws_asynch_confirm *asynch_cnf_cb, ws_neighbor_info_request *ws_neighbor_info_request_cb);
|
||||
|
||||
/**
|
||||
* @brief ws_llc_reset Reset ws LLC parametrs and clean messages
|
||||
* @param interface Interface pointer
|
||||
*
|
||||
*/
|
||||
void ws_llc_reset(struct protocol_interface_info_entry *interface);
|
||||
|
||||
/**
|
||||
* @brief ws_llc_delete Delete LLC interface. ONLY for Test purpose.
|
||||
* @param interface Interface pointer
|
||||
*
|
||||
*/
|
||||
int8_t ws_llc_delete(struct protocol_interface_info_entry *interface);
|
||||
|
||||
/**
|
||||
* @brief ws_llc_mpx_api_get Get MPX api for registration purpose.
|
||||
* @param interface Interface pointer
|
||||
*
|
||||
* @return NULL when MPX is not vailabale
|
||||
* @return Pointer to MPX API
|
||||
*
|
||||
*/
|
||||
mpx_api_t *ws_llc_mpx_api_get(struct protocol_interface_info_entry *interface);
|
||||
|
||||
/**
|
||||
* @brief ws_llc_asynch_request ws asynch message request to all giving channels
|
||||
* @param interface Interface pointer
|
||||
* @param request Asynch message parameters: type, IE and channel list
|
||||
*
|
||||
* @return 0 Asynch message pushed to MAC
|
||||
* @return -1 memory allocate problem
|
||||
* @return -2 Parameter problem
|
||||
*
|
||||
*/
|
||||
int8_t ws_llc_asynch_request(struct protocol_interface_info_entry *interface, asynch_request_t *request);
|
||||
|
||||
|
||||
/**
|
||||
* @brief ws_llc_set_vendor_header_data Configure WS vendor Header data information (Data of WH_IE_VH_TYPE IE element)
|
||||
* @param interface Interface pointer
|
||||
* @param vendor_header pointer to vendor header this pointer must keep alive when it is configured to LLC
|
||||
* @param vendor_header_length configured vendor header length
|
||||
*
|
||||
*/
|
||||
void ws_llc_set_vendor_header_data(struct protocol_interface_info_entry *interface, uint8_t *vendor_header, uint8_t vendor_header_length);
|
||||
|
||||
/**
|
||||
* @brief ws_llc_set_vendor_payload_data Configure WS vendor payload data information (Data of WP_PAYLOAD_IE_VP_TYPE IE element)
|
||||
* @param interface Interface pointer
|
||||
* @param vendor_payload pointer to vendor payload this pointer must keep alive when it is configured to LLC
|
||||
* @param vendor_payload_length configured vendor payload length
|
||||
*
|
||||
*/
|
||||
void ws_llc_set_vendor_payload_data(struct protocol_interface_info_entry *interface, uint8_t *vendor_payload, uint8_t vendor_payload_length);
|
||||
|
||||
/**
|
||||
* @brief ws_llc_set_network_name Configure WS Network name (Data of WP_PAYLOAD_IE_NETNAME_TYPE IE element)
|
||||
* @param interface Interface pointer
|
||||
* @param name_length configured network name length
|
||||
* @param name pointer to network name this pointer must keep alive when it is configured to LLC
|
||||
*
|
||||
*/
|
||||
void ws_llc_set_network_name(struct protocol_interface_info_entry *interface, uint8_t *name, uint8_t name_length);
|
||||
|
||||
/**
|
||||
* @brief ws_llc_set_gtkhash Configure WS GTK hash information (Data of WP_PAYLOAD_IE_GTKHASH_TYPE IE element)
|
||||
* @param interface Interface pointer
|
||||
* @param gtkhash pointer to GTK hash which length is 32 bytes this pointer must keep alive when it is configured to LLC
|
||||
*
|
||||
*/
|
||||
void ws_llc_set_gtkhash(struct protocol_interface_info_entry *interface, uint8_t *gtkhash);
|
||||
|
||||
/**
|
||||
* @brief ws_llc_set_pan_information_pointer Configure WS PAN information (Data of WP_PAYLOAD_IE_PAN_TYPE IE element)
|
||||
* @param interface Interface pointer
|
||||
* @param pan_information_pointer pointer to Pan information this pointer must keep alive when it is configured to LLC
|
||||
*
|
||||
*/
|
||||
void ws_llc_set_pan_information_pointer(struct protocol_interface_info_entry *interface, struct ws_pan_information_s *pan_information_pointer);
|
||||
|
||||
/**
|
||||
* @brief ws_llc_hopping_schedule_config Configure channel hopping
|
||||
* @param interface Interface pointer
|
||||
* @param hopping_schedule pointer to Channel hopping schedule
|
||||
*
|
||||
*/
|
||||
void ws_llc_hopping_schedule_config(struct protocol_interface_info_entry *interface, struct ws_hopping_schedule_s *hopping_schedule);
|
||||
|
||||
|
||||
|
||||
#endif /* WS_LLC_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "nsconfig.h"
|
||||
#include "ns_types.h"
|
||||
#include "ns_trace.h"
|
||||
#include <ns_list.h>
|
||||
#include <nsdynmemLIB.h>
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "6LoWPAN/ws/ws_common.h"
|
||||
#include "6LoWPAN/ws/ws_bootstrap.h"
|
||||
|
||||
#include "ws_management_api.h"
|
||||
|
||||
#define TRACE_GROUP "wsmg"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
int ws_management_node_init(
|
||||
int8_t interface_id,
|
||||
uint8_t regulatory_domain,
|
||||
char *network_name_ptr,
|
||||
fhss_timer_t *fhss_timer_ptr)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
if (!network_name_ptr || !fhss_timer_ptr) {
|
||||
return -2;
|
||||
}
|
||||
cur->ws_info->hopping_schdule.regulatory_domain = regulatory_domain;
|
||||
if (ws_common_regulatory_domain_config(cur) < 0) {
|
||||
// Invalid regulatory domain set
|
||||
return -3;
|
||||
}
|
||||
strncpy(cur->ws_info->network_name, network_name_ptr, 32);
|
||||
cur->ws_info->fhss_timer_ptr = fhss_timer_ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_regulatory_domain_set(
|
||||
int8_t interface_id,
|
||||
uint8_t regulatory_domain,
|
||||
uint8_t operating_class,
|
||||
uint8_t operating_mode)
|
||||
{
|
||||
uint8_t regulatory_domain_saved;
|
||||
uint8_t operating_class_saved;
|
||||
uint8_t operating_mode_saved;
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
regulatory_domain_saved = cur->ws_info->hopping_schdule.regulatory_domain;
|
||||
operating_class_saved = cur->ws_info->hopping_schdule.operating_mode;
|
||||
operating_mode_saved = cur->ws_info->hopping_schdule.operating_class;
|
||||
if (regulatory_domain != 255) {
|
||||
cur->ws_info->hopping_schdule.regulatory_domain = regulatory_domain;
|
||||
}
|
||||
if (operating_mode != 255) {
|
||||
cur->ws_info->hopping_schdule.operating_mode = operating_mode;
|
||||
}
|
||||
if (operating_class != 255) {
|
||||
cur->ws_info->hopping_schdule.operating_class = operating_class;
|
||||
}
|
||||
if (ws_common_regulatory_domain_config(cur) != 0) {
|
||||
// Restore old config on failure
|
||||
//tr_error("unsupported regulatory domain: %d class: %d, mode: %d", regulatory_domain, operating_class, operating_mode);
|
||||
cur->ws_info->hopping_schdule.regulatory_domain = regulatory_domain_saved;
|
||||
cur->ws_info->hopping_schdule.operating_mode = operating_mode_saved;
|
||||
cur->ws_info->hopping_schdule.operating_class = operating_class_saved;
|
||||
ws_common_regulatory_domain_config(cur);
|
||||
return -1;
|
||||
}
|
||||
// if settings change reset_restart for the settings needed
|
||||
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
||||
// bootstrap active need to restart
|
||||
ws_bootstrap_restart(interface_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_network_size_set(
|
||||
int8_t interface_id,
|
||||
uint8_t network_size)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
if (network_size > NETWORK_SIZE_LARGE) {
|
||||
return -2;
|
||||
}
|
||||
ws_info(cur)->network_size_config = network_size;
|
||||
|
||||
if (network_size == NETWORK_SIZE_LARGE) {
|
||||
ws_common_network_size_configure(cur, 5000);
|
||||
} else {
|
||||
ws_common_network_size_configure(cur, 10);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_channel_mask_set(
|
||||
int8_t interface_id,
|
||||
uint32_t channel_mask[8])
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(cur->ws_info->fhss_channel_mask, channel_mask, sizeof(uint32_t) * 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_channel_plan_set(
|
||||
int8_t interface_id,
|
||||
uint8_t channel_plan,
|
||||
uint8_t uc_channel_function,
|
||||
uint8_t bc_channel_function,
|
||||
uint32_t ch0_freq, // Stack can not modify this
|
||||
uint8_t channel_spacing,// Stack can not modify this
|
||||
uint8_t number_of_channels)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
cur->ws_info->hopping_schdule.channel_plan = channel_plan;
|
||||
cur->ws_info->hopping_schdule.uc_channel_function = uc_channel_function;
|
||||
cur->ws_info->hopping_schdule.bc_channel_function = bc_channel_function;
|
||||
cur->ws_info->hopping_schdule.ch0_freq = ch0_freq;
|
||||
cur->ws_info->hopping_schdule.channel_spacing = channel_spacing;
|
||||
cur->ws_info->hopping_schdule.number_of_channels = number_of_channels;
|
||||
|
||||
// TODO update fields to llc
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_fhss_timing_configure(
|
||||
int8_t interface_id,
|
||||
uint8_t fhss_uc_dwell_interval,
|
||||
uint32_t fhss_broadcast_interval,
|
||||
uint8_t fhss_bc_dwell_interval)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
if (fhss_uc_dwell_interval > 0) {
|
||||
cur->ws_info->fhss_uc_dwell_interval = fhss_uc_dwell_interval;
|
||||
}
|
||||
if (fhss_broadcast_interval > 0) {
|
||||
cur->ws_info->fhss_bc_interval = fhss_broadcast_interval;
|
||||
|
||||
}
|
||||
if (fhss_bc_dwell_interval > 0) {
|
||||
cur->ws_info->fhss_bc_dwell_interval = fhss_bc_dwell_interval;
|
||||
|
||||
}
|
||||
|
||||
// if settings change reset_restart for the settings needed
|
||||
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
||||
// bootstrap active need to restart
|
||||
ws_bootstrap_restart(interface_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_management_fhss_unicast_channel_function_configure(
|
||||
int8_t interface_id,
|
||||
uint8_t channel_function,
|
||||
uint16_t fixed_channel,
|
||||
uint8_t dwell_interval)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
if (channel_function != WS_FIXED_CHANNEL &&
|
||||
channel_function != WS_VENDOR_DEF_CF &&
|
||||
channel_function != WS_DH1CF &&
|
||||
channel_function != WS_TR51CF) {
|
||||
return -2;
|
||||
}
|
||||
cur->ws_info->fhss_uc_channel_function = channel_function;
|
||||
cur->ws_info->fhss_uc_fixed_channel = fixed_channel;
|
||||
cur->ws_info->fhss_uc_dwell_interval = dwell_interval;
|
||||
|
||||
// if settings change reset_restart for the settings needed
|
||||
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
||||
// bootstrap active need to restart
|
||||
ws_bootstrap_restart(interface_id);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int ws_management_fhss_broadcast_channel_function_configure(
|
||||
int8_t interface_id,
|
||||
uint8_t channel_function,
|
||||
uint16_t fixed_channel,
|
||||
uint8_t dwell_interval,
|
||||
uint32_t broadcast_interval)
|
||||
{
|
||||
protocol_interface_info_entry_t *cur;
|
||||
|
||||
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||
if (!cur || !ws_info(cur)) {
|
||||
return -1;
|
||||
}
|
||||
if (channel_function != WS_FIXED_CHANNEL &&
|
||||
channel_function != WS_VENDOR_DEF_CF &&
|
||||
channel_function != WS_DH1CF &&
|
||||
channel_function != WS_TR51CF) {
|
||||
return -2;
|
||||
}
|
||||
cur->ws_info->fhss_bc_channel_function = channel_function;
|
||||
cur->ws_info->fhss_bc_fixed_channel = fixed_channel;
|
||||
cur->ws_info->fhss_bc_dwell_interval = dwell_interval;
|
||||
cur->ws_info->fhss_bc_interval = broadcast_interval;
|
||||
|
||||
// if settings change reset_restart for the settings needed
|
||||
if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
|
||||
// bootstrap active need to restart
|
||||
ws_bootstrap_restart(interface_id);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif // HAVE_WS
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "common_functions.h"
|
||||
#include "mac_common_defines.h"
|
||||
#include "ws_mpx_header.h"
|
||||
|
||||
bool ws_llc_mpx_header_frame_parse(uint8_t *ptr, uint16_t length, mpx_msg_t *msg)
|
||||
{
|
||||
if (!length) {
|
||||
return false;
|
||||
}
|
||||
memset(msg, 0, sizeof(mpx_msg_t));
|
||||
bool fragmented_number_present = false;
|
||||
bool multiplex_id_present = false;
|
||||
bool fragment_total_size = false;
|
||||
|
||||
msg->transfer_type = *ptr & 7;
|
||||
msg->transaction_id = ((*ptr++ & 0xf8) >> 3);
|
||||
length--;
|
||||
|
||||
|
||||
switch (msg->transfer_type) {
|
||||
case MPX_FT_FULL_FRAME:
|
||||
multiplex_id_present = true;
|
||||
break;
|
||||
case MPX_FT_FULL_FRAME_SMALL_MULTILEX_ID:
|
||||
break;
|
||||
case MPX_FT_FIRST_OR_SUB_FRAGMENT:
|
||||
case MPX_FT_LAST_FRAGMENT:
|
||||
fragmented_number_present = true;
|
||||
if (length < 2) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case MPX_FT_ABORT:
|
||||
if (length == 2) {
|
||||
fragment_total_size = true;
|
||||
} else if (length) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fragmented_number_present) {
|
||||
|
||||
msg->fragment_number = *ptr++;
|
||||
length--;
|
||||
if (msg->fragment_number == 0) { //First fragment
|
||||
fragment_total_size = true;
|
||||
multiplex_id_present = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fragment_total_size) {
|
||||
if (length < 2) {
|
||||
return false;
|
||||
}
|
||||
msg->total_upper_layer_size = common_read_16_bit_inverse(ptr);
|
||||
ptr += 2;
|
||||
length -= 2;
|
||||
}
|
||||
|
||||
if (multiplex_id_present) {
|
||||
if (length < 3) {
|
||||
return false;
|
||||
}
|
||||
msg->multiplex_id = common_read_16_bit_inverse(ptr);
|
||||
ptr += 2;
|
||||
length -= 2;
|
||||
}
|
||||
|
||||
msg->frame_ptr = ptr;
|
||||
msg->frame_length = length;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *ws_llc_mpx_header_write(uint8_t *ptr, const mpx_msg_t *msg)
|
||||
{
|
||||
|
||||
bool fragmented_number_present = false;
|
||||
bool multiplex_id_present = false;
|
||||
bool fragment_total_size = false;
|
||||
|
||||
*ptr = msg->transfer_type;
|
||||
*ptr++ |= ((msg->transaction_id << 3) & 0xf8);
|
||||
|
||||
switch (msg->transfer_type) {
|
||||
case MPX_FT_FULL_FRAME:
|
||||
multiplex_id_present = true;
|
||||
break;
|
||||
case MPX_FT_FULL_FRAME_SMALL_MULTILEX_ID:
|
||||
break;
|
||||
case MPX_FT_FIRST_OR_SUB_FRAGMENT:
|
||||
case MPX_FT_LAST_FRAGMENT:
|
||||
fragmented_number_present = true;
|
||||
if (msg->fragment_number == 0) {
|
||||
fragment_total_size = true;
|
||||
multiplex_id_present = true;
|
||||
}
|
||||
break;
|
||||
case MPX_FT_ABORT:
|
||||
if (msg->total_upper_layer_size) {
|
||||
fragment_total_size = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fragmented_number_present) {
|
||||
*ptr++ = msg->fragment_number;
|
||||
}
|
||||
|
||||
if (fragment_total_size) {
|
||||
ptr = common_write_16_bit_inverse(msg->total_upper_layer_size, ptr);
|
||||
}
|
||||
|
||||
if (multiplex_id_present) {
|
||||
ptr = common_write_16_bit_inverse(msg->multiplex_id, ptr);
|
||||
}
|
||||
return ptr;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_MPX_HEADER_H_
|
||||
#define WS_MPX_HEADER_H_
|
||||
|
||||
#define MPX_FT_FULL_FRAME 0
|
||||
#define MPX_FT_FULL_FRAME_SMALL_MULTILEX_ID 1
|
||||
#define MPX_FT_FIRST_OR_SUB_FRAGMENT 2
|
||||
#define MPX_FT_LAST_FRAGMENT 4
|
||||
#define MPX_FT_ABORT 6
|
||||
|
||||
typedef struct {
|
||||
unsigned transfer_type: 3;
|
||||
unsigned transaction_id: 5;
|
||||
uint8_t fragment_number;
|
||||
uint16_t total_upper_layer_size;
|
||||
uint16_t multiplex_id;
|
||||
uint8_t *frame_ptr;
|
||||
uint16_t frame_length;
|
||||
} mpx_msg_t;
|
||||
|
||||
bool ws_llc_mpx_header_frame_parse(uint8_t *ptr, uint16_t length, mpx_msg_t *msg);
|
||||
uint8_t *ws_llc_mpx_header_write(uint8_t *ptr, const mpx_msg_t *msg);
|
||||
|
||||
|
||||
#endif /* WS_MPX_HEADER_H_ */
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "fhss_config.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_neighbor_class.h"
|
||||
#include "6LoWPAN/ws/ws_common.h"
|
||||
#include "ws_management_api.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
|
||||
#define TRACE_GROUP "wsne"
|
||||
|
||||
|
||||
bool ws_neighbor_class_alloc(ws_neighbor_class_t *class_data, uint8_t list_size)
|
||||
{
|
||||
|
||||
class_data->neigh_info_list = ns_dyn_mem_alloc(sizeof(ws_neighbor_class_entry_t) * list_size);
|
||||
if (!class_data->neigh_info_list) {
|
||||
return false;
|
||||
}
|
||||
|
||||
class_data->list_size = list_size;
|
||||
ws_neighbor_class_entry_t *list_ptr = class_data->neigh_info_list;
|
||||
for (uint8_t i = 0; i < list_size; i++) {
|
||||
memset(list_ptr, 0, sizeof(ws_neighbor_class_entry_t));
|
||||
list_ptr->rsl_in = RSL_UNITITIALIZED;
|
||||
list_ptr->rsl_out = RSL_UNITITIALIZED;
|
||||
list_ptr++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ws_neighbor_class_dealloc(ws_neighbor_class_t *class_data)
|
||||
{
|
||||
ns_dyn_mem_free(class_data->neigh_info_list);
|
||||
class_data->neigh_info_list = NULL;
|
||||
class_data->list_size = 0;
|
||||
}
|
||||
|
||||
ws_neighbor_class_entry_t *ws_neighbor_class_entry_get(ws_neighbor_class_t *class_data, uint8_t attribute_index)
|
||||
{
|
||||
if (!class_data->neigh_info_list || attribute_index >= class_data->list_size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ws_neighbor_class_entry_t *entry = class_data->neigh_info_list + attribute_index;
|
||||
return entry;
|
||||
}
|
||||
|
||||
uint8_t ws_neighbor_class_entry_index_get(ws_neighbor_class_t *class_data, ws_neighbor_class_entry_t *entry)
|
||||
{
|
||||
if (!class_data->neigh_info_list) {
|
||||
return 0xff;
|
||||
}
|
||||
return entry - class_data->neigh_info_list;
|
||||
}
|
||||
|
||||
void ws_neighbor_class_entry_remove(ws_neighbor_class_t *class_data, uint8_t attribute_index)
|
||||
{
|
||||
ws_neighbor_class_entry_t *entry = ws_neighbor_class_entry_get(class_data, attribute_index);
|
||||
if (entry) {
|
||||
memset(entry, 0, sizeof(ws_neighbor_class_entry_t));
|
||||
entry->rsl_in = RSL_UNITITIALIZED;
|
||||
entry->rsl_out = RSL_UNITITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp = timestamp;
|
||||
ws_neighbor->fhss_data.uc_timing_info.ufsi = ws_utt->ufsi;
|
||||
}
|
||||
|
||||
void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_us_ie_t *ws_us)
|
||||
{
|
||||
ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function = ws_us->channel_function;
|
||||
if (ws_us->channel_function == WS_FIXED_CHANNEL) {
|
||||
ws_neighbor->fhss_data.uc_timing_info.fixed_channel = ws_us->function.zero.fixed_channel;
|
||||
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = 1;
|
||||
} else {
|
||||
if (ws_us->channel_plan == 0) {
|
||||
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_common_channel_number_calc(ws_us->plan.zero.regulator_domain, ws_us->plan.zero.operation_class);
|
||||
} else if (ws_us->channel_plan == 1) {
|
||||
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_us->plan.one.number_of_channel;
|
||||
} else {
|
||||
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = 0;
|
||||
}
|
||||
}
|
||||
ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval = ws_us->dwell_interval;
|
||||
}
|
||||
|
||||
|
||||
void ws_neighbor_class_neighbor_broadcast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_bt_ie_t *ws_bt_ie, uint32_t timestamp)
|
||||
{
|
||||
ws_neighbor->broadcast_timing_info_stored = true;
|
||||
ws_neighbor->fhss_data.bc_timing_info.bt_rx_timestamp = timestamp;
|
||||
ws_neighbor->fhss_data.bc_timing_info.broadcast_slot = ws_bt_ie->broadcast_slot_number;
|
||||
ws_neighbor->fhss_data.bc_timing_info.broadcast_interval_offset = ws_bt_ie->broadcast_interval_offset;
|
||||
}
|
||||
|
||||
|
||||
void ws_neighbor_class_neighbor_broadcast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_bs_ie_t *ws_bs_ie)
|
||||
{
|
||||
ws_neighbor->broadcast_shedule_info_stored = true;
|
||||
ws_neighbor->fhss_data.bc_timing_info.broadcast_channel_function = ws_bs_ie->channel_function;
|
||||
if (ws_bs_ie->channel_function == WS_FIXED_CHANNEL) {
|
||||
ws_neighbor->fhss_data.bc_timing_info.fixed_channel = ws_bs_ie->function.zero.fixed_channel;
|
||||
}
|
||||
ws_neighbor->fhss_data.bc_timing_info.broadcast_dwell_interval = ws_bs_ie->dwell_interval;
|
||||
ws_neighbor->fhss_data.bc_timing_info.broadcast_interval = ws_bs_ie->broadcast_interval;
|
||||
ws_neighbor->fhss_data.bc_timing_info.broadcast_schedule_id = ws_bs_ie->broadcast_schedule_identifier;
|
||||
}
|
||||
|
||||
uint8_t ws_neighbor_class_rssi_from_dbm_calculate(int8_t dbm_heard)
|
||||
{
|
||||
if (DEVICE_MIN_SENS > dbm_heard) {
|
||||
// We are hearing packet with lower than min_sens dynamically learn the sensitivity
|
||||
tr_info("heard packet below min sensitivity");
|
||||
DEVICE_MIN_SENS = dbm_heard;
|
||||
}
|
||||
return dbm_heard - DEVICE_MIN_SENS;
|
||||
}
|
||||
|
||||
static void ws_neighbor_class_parent_set_analyze(ws_neighbor_class_entry_t *ws_neighbor)
|
||||
{
|
||||
if (ws_neighbor->rsl_in == RSL_UNITITIALIZED ||
|
||||
ws_neighbor->rsl_out == RSL_UNITITIALIZED) {
|
||||
ws_neighbor->candidate_parent = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ws_neighbor_class_rsl_in_get(ws_neighbor) < (CAND_PARENT_THRESHOLD - CAND_PARENT_HYSTERISIS) &&
|
||||
ws_neighbor_class_rsl_out_get(ws_neighbor) < (CAND_PARENT_THRESHOLD - CAND_PARENT_HYSTERISIS)) {
|
||||
ws_neighbor->candidate_parent = false;
|
||||
}
|
||||
|
||||
if (ws_neighbor_class_rsl_in_get(ws_neighbor) > (CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) &&
|
||||
ws_neighbor_class_rsl_out_get(ws_neighbor) > (CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) {
|
||||
ws_neighbor->candidate_parent = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ws_neighbor_class_rsl_in_calculate(ws_neighbor_class_entry_t *ws_neighbor, int8_t dbm_heard)
|
||||
{
|
||||
uint8_t rssi = ws_neighbor_class_rssi_from_dbm_calculate(dbm_heard);
|
||||
if (ws_neighbor->rsl_in == RSL_UNITITIALIZED) {
|
||||
ws_neighbor->rsl_in = rssi << WS_RSL_SCALING;
|
||||
}
|
||||
ws_neighbor->rsl_in = ws_neighbor->rsl_in + rssi - (ws_neighbor->rsl_in >> WS_RSL_SCALING);
|
||||
ws_neighbor_class_parent_set_analyze(ws_neighbor);
|
||||
return;
|
||||
}
|
||||
|
||||
void ws_neighbor_class_rsl_out_calculate(ws_neighbor_class_entry_t *ws_neighbor, uint8_t rsl_reported)
|
||||
{
|
||||
if (ws_neighbor->rsl_out == RSL_UNITITIALIZED) {
|
||||
ws_neighbor->rsl_out = rsl_reported << WS_RSL_SCALING;
|
||||
}
|
||||
ws_neighbor->rsl_out = ws_neighbor->rsl_out + rsl_reported - (ws_neighbor->rsl_out >> WS_RSL_SCALING);
|
||||
ws_neighbor_class_parent_set_analyze(ws_neighbor);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* HAVE_WS */
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -0,0 +1,603 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "fhss_config.h"
|
||||
#include "eventOS_event.h"
|
||||
#include "eventOS_scheduler.h"
|
||||
#include "eventOS_event_timer.h"
|
||||
#include "ns_address.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "Security/kmp/kmp_addr.h"
|
||||
#include "Security/kmp/kmp_api.h"
|
||||
#include "Security/kmp/kmp_socket_if.h"
|
||||
#include "Security/protocols/sec_prot_certs.h"
|
||||
#include "Security/protocols/sec_prot_keys.h"
|
||||
#include "Security/protocols/key_sec_prot/key_sec_prot.h"
|
||||
#include "Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.h"
|
||||
#include "Security/protocols/tls_sec_prot/tls_sec_prot.h"
|
||||
#include "Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.h"
|
||||
#include "Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.h"
|
||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "6LoWPAN/ws/ws_pae_auth.h"
|
||||
#include "6LoWPAN/ws/ws_pae_lib.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
#ifdef HAVE_PAE_AUTH
|
||||
|
||||
#define TRACE_GROUP "wspa"
|
||||
|
||||
#define PAE_TASKLET_INIT 1
|
||||
#define PAE_TASKLET_EVENT 2
|
||||
#define PAE_TASKLET_TIMER 3
|
||||
|
||||
// Wait for for supplicant to indicate activity (e.g. to send a message)
|
||||
#define WAIT_FOR_AUTHENTICATION_TICKS 5 * 60 * 10 // 5 minutes
|
||||
|
||||
typedef struct {
|
||||
ns_list_link_t link; /**< Link */
|
||||
kmp_service_t *kmp_service; /**< KMP service */
|
||||
protocol_interface_info_entry_t *interface_ptr; /**< Interface pointer */
|
||||
supp_list_t active_supp_list; /**< List of active supplicants */
|
||||
supp_list_t inactive_supp_list; /**< List of inactive supplicants */
|
||||
arm_event_storage_t *timer; /**< Timer */
|
||||
sec_prot_gtk_keys_t *gtks; /**< GTKs */
|
||||
const sec_prot_certs_t *certs; /**< Certificates */
|
||||
bool timer_running; /**< Timer is running */
|
||||
} pae_auth_t;
|
||||
|
||||
static void ws_pae_auth_free(pae_auth_t *pae_auth);
|
||||
static pae_auth_t *ws_pae_auth_get(protocol_interface_info_entry_t *interface_ptr);
|
||||
static pae_auth_t *ws_pae_auth_by_kmp_service_get(kmp_service_t *service);
|
||||
static int8_t ws_pae_auth_event_send(kmp_service_t *service, void *data);
|
||||
static void ws_pae_auth_tasklet_handler(arm_event_s *event);
|
||||
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 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 kmp_api_t *ws_pae_auth_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type);
|
||||
static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr);
|
||||
static void ws_pae_auth_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result);
|
||||
static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr);
|
||||
static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
|
||||
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry);
|
||||
static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp);
|
||||
|
||||
static int8_t tasklet_id = -1;
|
||||
static NS_LIST_DEFINE(pae_auth_list, pae_auth_t, link);
|
||||
|
||||
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, const sec_prot_certs_t *certs)
|
||||
{
|
||||
if (!interface_ptr || !gtks || !certs) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_pae_auth_get(interface_ptr) != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = ns_dyn_mem_alloc(sizeof(pae_auth_t));
|
||||
if (!pae_auth) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_auth->interface_ptr = interface_ptr;
|
||||
ws_pae_lib_supp_list_init(&pae_auth->active_supp_list);
|
||||
ws_pae_lib_supp_list_init(&pae_auth->inactive_supp_list);
|
||||
pae_auth->timer = NULL;
|
||||
|
||||
pae_auth->gtks = gtks;
|
||||
pae_auth->certs = certs;
|
||||
|
||||
pae_auth->kmp_service = kmp_service_create();
|
||||
if (!pae_auth->kmp_service) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (kmp_service_cb_register(pae_auth->kmp_service, ws_pae_auth_kmp_incoming_ind, ws_pae_auth_kmp_service_addr_get, ws_pae_auth_kmp_service_api_get)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (kmp_service_event_if_register(pae_auth->kmp_service, ws_pae_auth_event_send)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (kmp_service_timer_if_register(pae_auth->kmp_service, ws_pae_auth_timer_if_start, ws_pae_auth_timer_if_stop)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (key_sec_prot_register(pae_auth->kmp_service) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (auth_eap_tls_sec_prot_register(pae_auth->kmp_service) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (server_tls_sec_prot_register(pae_auth->kmp_service) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (auth_fwh_sec_prot_register(pae_auth->kmp_service) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (auth_gkh_sec_prot_register(pae_auth->kmp_service) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (tasklet_id < 0) {
|
||||
tasklet_id = eventOS_event_handler_create(ws_pae_auth_tasklet_handler, PAE_TASKLET_INIT);
|
||||
if (tasklet_id < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (ws_pae_auth_timer_stop(pae_auth) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
ns_list_add_to_end(&pae_auth_list, pae_auth);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
ws_pae_auth_free(pae_auth);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t ws_pae_auth_addresses_set(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port)
|
||||
{
|
||||
if (!interface_ptr || !remote_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
|
||||
if (!pae_auth) {
|
||||
return -1;
|
||||
}
|
||||
if (!pae_auth->kmp_service) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kmp_socket_if_register(pae_auth->kmp_service, local_port, remote_addr, remote_port) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_auth_delete(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
|
||||
if (!pae_auth) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_pae_auth_free(pae_auth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ws_pae_auth_free(pae_auth_t *pae_auth)
|
||||
{
|
||||
if (!pae_auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
ws_pae_lib_supp_list_delete(&pae_auth->active_supp_list);
|
||||
ws_pae_lib_supp_list_delete(&pae_auth->inactive_supp_list);
|
||||
|
||||
kmp_socket_if_unregister(pae_auth->kmp_service);
|
||||
|
||||
kmp_service_delete(pae_auth->kmp_service);
|
||||
|
||||
ns_list_remove(&pae_auth_list, pae_auth);
|
||||
ns_dyn_mem_free(pae_auth);
|
||||
}
|
||||
|
||||
static pae_auth_t *ws_pae_auth_get(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
ns_list_foreach(pae_auth_t, entry, &pae_auth_list) {
|
||||
if (entry->interface_ptr == interface_ptr) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static pae_auth_t *ws_pae_auth_by_kmp_service_get(kmp_service_t *service)
|
||||
{
|
||||
ns_list_foreach(pae_auth_t, entry, &pae_auth_list) {
|
||||
if (entry->kmp_service == service) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_event_send(kmp_service_t *service, void *data)
|
||||
{
|
||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
if (!pae_auth) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
arm_event_s event = {
|
||||
.receiver = tasklet_id,
|
||||
.sender = 0,
|
||||
.event_id = pae_auth->interface_ptr->id,
|
||||
.data_ptr = data,
|
||||
.event_type = PAE_TASKLET_EVENT,
|
||||
.priority = ARM_LIB_LOW_PRIORITY_EVENT,
|
||||
};
|
||||
|
||||
if (eventOS_event_send(&event) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ws_pae_auth_tasklet_handler(arm_event_s *event)
|
||||
{
|
||||
if (event->event_type == PAE_TASKLET_INIT) {
|
||||
|
||||
} else if (event->event_type == PAE_TASKLET_EVENT) {
|
||||
pae_auth_t *pae_auth = NULL;
|
||||
|
||||
ns_list_foreach(pae_auth_t, entry, &pae_auth_list) {
|
||||
if (entry->interface_ptr->id == event->event_id) {
|
||||
pae_auth = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pae_auth) {
|
||||
kmp_service_event_if_event(pae_auth->kmp_service, event->data_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ws_pae_auth_timer(uint16_t ticks)
|
||||
{
|
||||
ns_list_foreach(pae_auth_t, pae_auth, &pae_auth_list) {
|
||||
if (!ws_pae_auth_timer_running(pae_auth)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Updates KMP timers
|
||||
bool running = ws_pae_lib_supp_list_timer_update(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, ticks, kmp_service_timer_if_timeout);
|
||||
if (!running) {
|
||||
ws_pae_auth_timer_stop(pae_auth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_timer_if_start(kmp_service_t *service, kmp_api_t *kmp)
|
||||
{
|
||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
if (!pae_auth) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_pae_auth_timer_start(pae_auth) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
supp_entry_t *supp_entry = kmp_api_data_get(kmp);
|
||||
if (!supp_entry) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
kmp_entry_t *entry = ws_pae_lib_kmp_list_entry_get(&supp_entry->kmp_list, kmp);
|
||||
if (!entry) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_pae_lib_supp_list_to_active(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, supp_entry);
|
||||
|
||||
ws_pae_lib_kmp_timer_start(&supp_entry->kmp_list, entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp)
|
||||
{
|
||||
(void) service;
|
||||
|
||||
supp_entry_t *supp_entry = kmp_api_data_get(kmp);
|
||||
|
||||
kmp_entry_t *entry = ws_pae_lib_kmp_list_entry_get(&supp_entry->kmp_list, kmp);
|
||||
if (!entry) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_pae_lib_kmp_timer_stop(&supp_entry->kmp_list, entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_timer_start(pae_auth_t *pae_auth)
|
||||
{
|
||||
pae_auth->timer_running = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t ws_pae_auth_timer_stop(pae_auth_t *pae_auth)
|
||||
{
|
||||
pae_auth->timer_running = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool ws_pae_auth_timer_running(pae_auth_t *pae_auth)
|
||||
{
|
||||
return pae_auth->timer_running;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
(void) service;
|
||||
|
||||
#if 0
|
||||
// Get own EUI-64
|
||||
link_layer_address_s mac_params;
|
||||
if (arm_nwk_mac_address_read(pae_auth->interface_ptr->id, &mac_params) >= 0) {
|
||||
kmp_address_eui_64_set(local_addr, mac_params.mac_long);
|
||||
}
|
||||
#endif
|
||||
|
||||
// For now fixed since not yet support for EA-IE in supplicants
|
||||
uint8_t addr[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
|
||||
kmp_address_eui_64_set(local_addr, addr);
|
||||
|
||||
// Get supplicant address
|
||||
supp_entry_t *entry = kmp_api_data_get(kmp);
|
||||
if (entry && entry->addr) {
|
||||
kmp_address_copy(remote_addr, entry->addr);
|
||||
}
|
||||
}
|
||||
|
||||
static kmp_api_t *ws_pae_auth_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type)
|
||||
{
|
||||
(void) service;
|
||||
|
||||
supp_entry_t *supp_entry = kmp_api_data_get(kmp);
|
||||
if (!supp_entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, type);
|
||||
}
|
||||
|
||||
static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr)
|
||||
{
|
||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
if (!pae_auth) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find supplicant from list of active supplicants
|
||||
supp_entry_t *supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->active_supp_list, kmp_address_eui_64_get(addr));
|
||||
|
||||
if (!supp_entry) {
|
||||
// Find supplicant from list of inactive supplicants
|
||||
supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->inactive_supp_list, kmp_address_eui_64_get(addr));
|
||||
if (supp_entry) {
|
||||
// Move supplicant to active list
|
||||
ws_pae_lib_supp_list_to_active(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, supp_entry);
|
||||
}
|
||||
}
|
||||
|
||||
// If does not exists add it to list
|
||||
if (!supp_entry) {
|
||||
supp_entry = ws_pae_lib_supp_list_add(&pae_auth->active_supp_list, addr);
|
||||
if (!supp_entry) {
|
||||
return 0;
|
||||
}
|
||||
sec_prot_keys_init(&supp_entry->sec_keys, pae_auth->gtks, pae_auth->certs);
|
||||
} else {
|
||||
// Updates relay address
|
||||
kmp_address_copy(supp_entry->addr, addr);
|
||||
}
|
||||
|
||||
// Increases waiting time for supplicant authentication
|
||||
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS);
|
||||
|
||||
// Get KMP for supplicant
|
||||
kmp_api_t *kmp = ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, type);
|
||||
if (kmp) {
|
||||
return kmp;
|
||||
}
|
||||
|
||||
// Create a new KMP for initial eapol-key
|
||||
kmp = kmp_api_create(service, type + IEEE_802_1X_INITIAL_KEY);
|
||||
|
||||
if (!kmp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
kmp_api_data_set(kmp, supp_entry);
|
||||
// Sets address to KMP
|
||||
kmp_api_addr_set(kmp, supp_entry->addr);
|
||||
|
||||
// Sets security keys to KMP
|
||||
kmp_api_sec_keys_set(kmp, &supp_entry->sec_keys);
|
||||
|
||||
if (ws_pae_lib_kmp_list_add(&supp_entry->kmp_list, kmp) == NULL) {
|
||||
kmp_api_delete(kmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kmp_api_cb_register(kmp,
|
||||
ws_pae_auth_kmp_api_create_confirm,
|
||||
ws_pae_auth_kmp_api_create_indication,
|
||||
ws_pae_auth_kmp_api_finished_indication,
|
||||
ws_pae_auth_kmp_api_finished);
|
||||
|
||||
if (kmp_api_start(kmp) < 0) {
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, kmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return kmp;
|
||||
}
|
||||
|
||||
static void ws_pae_auth_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result)
|
||||
{
|
||||
(void) kmp;
|
||||
(void) result;
|
||||
// If KMP-CREATE.request has failed, authentication error, just stop for now
|
||||
}
|
||||
|
||||
static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr)
|
||||
{
|
||||
(void) type;
|
||||
(void) addr;
|
||||
// For now, accept every KMP-CREATE.indication
|
||||
kmp_api_create_response(kmp, KMP_RESULT_OK);
|
||||
}
|
||||
|
||||
static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys)
|
||||
{
|
||||
(void) sec_keys;
|
||||
|
||||
// For now, just ignore if not ok
|
||||
if (result != KMP_RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
supp_entry_t *supp_entry = kmp_api_data_get(kmp);
|
||||
if (!supp_entry) {
|
||||
// Should not be possible
|
||||
return;
|
||||
}
|
||||
|
||||
// Gets type
|
||||
kmp_type_e type = kmp_api_type_get(kmp);
|
||||
|
||||
if (type > IEEE_802_1X_INITIAL_KEY) {
|
||||
// For EAPOL-key, start EAP-TLS towards supplicant
|
||||
type = IEEE_802_1X_MKA;
|
||||
tr_debug("PAE start EAP-TLS, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
} else if (type == IEEE_802_1X_MKA) {
|
||||
// After EAP-TLS start 4WH towards supplicant
|
||||
type = IEEE_802_11_4WH;
|
||||
// Insert GTK0
|
||||
sec_prot_keys_gtk_insert_index_set(supp_entry->sec_keys.gtks, 0);
|
||||
tr_debug("PAE start 4WH, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
} else if (type == IEEE_802_11_4WH) {
|
||||
// After 4WH start GKH towards supplicant
|
||||
type = IEEE_802_11_GKH;
|
||||
// Insert GTK1
|
||||
sec_prot_keys_gtk_insert_index_set(supp_entry->sec_keys.gtks, 1);
|
||||
tr_debug("PAE start GKH, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
} else if (type == IEEE_802_11_GKH) {
|
||||
tr_debug("PAE authenticated, eui-64: %s", trace_array(kmp_address_eui_64_get(supp_entry->addr), 8));
|
||||
// After GKH end
|
||||
return;
|
||||
}
|
||||
|
||||
// Increases waiting time for supplicant authentication
|
||||
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS);
|
||||
|
||||
kmp_service_t *service = kmp_api_service_get(kmp);
|
||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||
if (!pae_auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new instance
|
||||
kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, type, supp_entry);
|
||||
if (!new_kmp) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For EAP-TLS create also TLS in addition to EAP-TLS
|
||||
if (type == IEEE_802_1X_MKA) {
|
||||
if (ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, TLS_PROT) != NULL) {
|
||||
// TLS already exists, wait for it to be deleted
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||
return;
|
||||
}
|
||||
// Create TLS instance */
|
||||
if (ws_pae_auth_kmp_create_and_start(service, TLS_PROT, supp_entry) == NULL) {
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
kmp_api_create_request(new_kmp, type, supp_entry->addr, &supp_entry->sec_keys);
|
||||
}
|
||||
|
||||
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry)
|
||||
{
|
||||
// Create KMP instance for new authentication
|
||||
kmp_api_t *kmp = kmp_api_create(service, type);
|
||||
|
||||
if (!kmp) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ws_pae_lib_kmp_list_add(&supp_entry->kmp_list, kmp) == NULL) {
|
||||
kmp_api_delete(kmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kmp_api_cb_register(kmp,
|
||||
ws_pae_auth_kmp_api_create_confirm,
|
||||
ws_pae_auth_kmp_api_create_indication,
|
||||
ws_pae_auth_kmp_api_finished_indication,
|
||||
ws_pae_auth_kmp_api_finished);
|
||||
|
||||
kmp_api_data_set(kmp, supp_entry);
|
||||
|
||||
if (kmp_api_start(kmp) < 0) {
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, kmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return kmp;
|
||||
}
|
||||
|
||||
static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp)
|
||||
{
|
||||
supp_entry_t *supp_entry = kmp_api_data_get(kmp);
|
||||
if (!supp_entry) {
|
||||
// Should not be possible
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete KMP
|
||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, kmp);
|
||||
}
|
||||
|
||||
#endif /* HAVE_PAE_AUTH */
|
||||
#endif /* HAVE_WS */
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_PAE_AUTH_H_
|
||||
#define WS_PAE_AUTH_H_
|
||||
|
||||
#ifdef HAVE_PAE_AUTH
|
||||
|
||||
/*
|
||||
* Authenticator port access entity controls key security protocols using KMP API.
|
||||
*
|
||||
* Configures KMP service network access and provides timing and callback services
|
||||
* for it. Registers needed security protocols to KMP service.
|
||||
*
|
||||
* PAE Maintains security keys that are internal to port access entity for
|
||||
* each supplicant and maintains supplicant security registration state.
|
||||
*
|
||||
* Autenticator PAE controls network access keys and provides new network
|
||||
* access keys to supplicants when they are changed. When supplicant
|
||||
* network keys are updated, also other keys (master key, pairwise key)
|
||||
* are updated as needed.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* ws_pae_auth_init initializes PAE authenticator
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param local_port local port
|
||||
* \param remote_addr remote address
|
||||
* \param remote_port remote port
|
||||
* \param gtks group keys
|
||||
* \param cert_chain certificate chain
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, const sec_prot_certs_t *certs);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_addresses_set set relay addresses
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param local_port local port
|
||||
* \param remote_addr remote address
|
||||
* \param remote_port remote port
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_auth_addresses_set(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_delete deletes PAE authenticator
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_auth_delete(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_auth_timer PAE authenticator timer call
|
||||
*
|
||||
* \param ticks elapsed ticks
|
||||
*
|
||||
*/
|
||||
void ws_pae_auth_timer(uint16_t ticks);
|
||||
|
||||
#else
|
||||
|
||||
#define ws_pae_auth_init(interface_ptr, gtks, certs) 1
|
||||
#define ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) 1
|
||||
#define ws_pae_auth_delete NULL
|
||||
#define ws_pae_auth_timer NULL
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WS_PAE_AUTH_H_ */
|
|
@ -0,0 +1,412 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ns_types.h"
|
||||
#include "ns_list.h"
|
||||
#include "ns_trace.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "fhss_config.h"
|
||||
#include "ns_address.h"
|
||||
#include "NWK_INTERFACE/Include/protocol.h"
|
||||
#include "6LoWPAN/ws/ws_config.h"
|
||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||
#include "Security/protocols/sec_prot_certs.h"
|
||||
#include "Security/protocols/sec_prot_keys.h"
|
||||
#include "6LoWPAN/ws/ws_pae_supp.h"
|
||||
#include "6LoWPAN/ws/ws_pae_auth.h"
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
#define TRACE_GROUP "wspc"
|
||||
|
||||
typedef int8_t ws_pae_delete(protocol_interface_info_entry_t *interface_ptr);
|
||||
typedef void ws_pae_timer(uint16_t ticks);
|
||||
typedef int8_t ws_pae_br_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
|
||||
typedef int8_t ws_pae_br_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64);
|
||||
|
||||
|
||||
typedef struct {
|
||||
ns_list_link_t link; /**< Link */
|
||||
uint8_t target_eui_64[8]; /**< EAPOL target */
|
||||
uint16_t target_pan_id; /**< EAPOL target PAN ID */
|
||||
uint8_t br_eui_64[8]; /**< Border router EUI-64 */
|
||||
sec_prot_gtk_keys_t gtks; /**< GTKs */
|
||||
sec_prot_certs_t certs; /**< Certificates */
|
||||
protocol_interface_info_entry_t *interface_ptr; /**< List link entry */
|
||||
ws_pae_controller_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */
|
||||
ws_pae_controller_key_insert *key_insert; /**< Key insert callback */
|
||||
ws_pae_delete *pae_delete; /**< PAE delete callback */
|
||||
ws_pae_timer *pae_timer; /**< PAE timer callback */
|
||||
ws_pae_br_addr_write *pae_br_addr_write; /**< PAE Border router EUI-64 write callback */
|
||||
ws_pae_br_addr_read *pae_br_addr_read; /**< PAE Border router EUI-64 read callback */
|
||||
} pae_controller_t;
|
||||
|
||||
static void ws_pae_controller_test_keys_set(sec_prot_gtk_keys_t *gtks);
|
||||
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link);
|
||||
|
||||
static void ws_pae_controller_test_keys_set(sec_prot_gtk_keys_t *gtks)
|
||||
{
|
||||
uint8_t gtk[2][GTK_LEN];
|
||||
|
||||
// Test data
|
||||
for (int i = 0; i < GTK_LEN; i++) {
|
||||
gtk[0][i] = 0xcf - i;
|
||||
gtk[1][i] = 0xef - i;
|
||||
}
|
||||
|
||||
sec_prot_keys_gtk_set(gtks, 0, gtk[0]);
|
||||
sec_prot_keys_gtk_set(gtks, 1, gtk[1]);
|
||||
|
||||
sec_prot_keys_gtkl_set(gtks, 0xFF);
|
||||
|
||||
sec_prot_keys_gtk_insert_index_set(gtks, 0);
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_pae_supp_authenticate(controller->interface_ptr, controller->target_pan_id, controller->target_eui_64) == PAE_SUPP_NOT_ENABLED) {
|
||||
// Already authenticated
|
||||
ws_pae_controller_test_keys_set(&controller->gtks);
|
||||
|
||||
uint8_t index;
|
||||
uint8_t *gtk = sec_prot_keys_get_gtk_to_insert(&controller->gtks, &index);
|
||||
|
||||
controller->key_insert(controller->interface_ptr, index, gtk);
|
||||
controller->auth_completed(interface_ptr, true);
|
||||
}
|
||||
|
||||
///////////
|
||||
// For now fixed since not yet support for EA-IE
|
||||
const uint8_t addr[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
|
||||
if (controller->pae_br_addr_write) {
|
||||
controller->pae_br_addr_write(interface_ptr, addr);
|
||||
}
|
||||
////////////////
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port)
|
||||
{
|
||||
(void) local_port;
|
||||
(void) remote_port;
|
||||
|
||||
if (!interface_ptr || !remote_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_pae_controller_test_keys_set(&controller->gtks);
|
||||
|
||||
uint8_t index;
|
||||
uint8_t *gtk = sec_prot_keys_get_gtk_to_insert(&controller->gtks, &index);
|
||||
|
||||
controller->key_insert(controller->interface_ptr, index, gtk);
|
||||
|
||||
if (ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_key_insert *key_insert)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
controller->auth_completed = completed;
|
||||
controller->key_insert = key_insert;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_set_target(protocol_interface_info_entry_t *interface_ptr, uint16_t target_pan_id, uint8_t *target_eui_64)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
controller->target_pan_id = target_pan_id;
|
||||
memcpy(controller->target_eui_64, target_eui_64, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name)
|
||||
{
|
||||
(void) pan_id;
|
||||
(void) network_name;
|
||||
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ws_pae_supp_nw_info_set(interface_ptr, pan_id, network_name);
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ws_pae_supp_nw_key_valid(interface_ptr);
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_pae_controller_get(interface_ptr) != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ns_dyn_mem_alloc(sizeof(pae_controller_t));
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(controller->target_eui_64, 0, 8);
|
||||
memset(controller->br_eui_64, 0, 8);
|
||||
controller->interface_ptr = interface_ptr;
|
||||
controller->auth_completed = NULL;
|
||||
controller->key_insert = NULL;
|
||||
controller->pae_delete = NULL;
|
||||
controller->pae_timer = NULL;
|
||||
controller->pae_br_addr_write = NULL;
|
||||
controller->pae_br_addr_read = NULL;
|
||||
|
||||
sec_prot_keys_gtks_init(&controller->gtks);
|
||||
sec_prot_certs_init(&controller->certs);
|
||||
|
||||
ns_list_add_to_end(&pae_controller_list, controller);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_pae_supp_init(controller->interface_ptr, &controller->certs) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
controller->pae_delete = ws_pae_supp_delete;
|
||||
controller->pae_timer = ws_pae_supp_timer;
|
||||
controller->pae_br_addr_write = ws_pae_supp_border_router_addr_write;
|
||||
controller->pae_br_addr_read = ws_pae_supp_border_router_addr_read;
|
||||
|
||||
ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, controller->key_insert);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ws_pae_auth_init(controller->interface_ptr, &controller->gtks, &controller->certs) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
controller->pae_delete = ws_pae_auth_delete;
|
||||
controller->pae_timer = ws_pae_auth_timer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If PAE has been initialized, deletes it
|
||||
if (controller->pae_delete) {
|
||||
controller->pae_delete(interface_ptr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
if (!interface_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ws_pae_controller_stop(interface_ptr);
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ns_list_remove(&pae_controller_list, controller);
|
||||
|
||||
sec_prot_certs_delete(&controller->certs);
|
||||
|
||||
ns_dyn_mem_free(controller);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_certificate_chain_set(const arm_certificate_chain_entry_s *new_chain)
|
||||
{
|
||||
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
|
||||
// Delete previous information
|
||||
sec_prot_certs_delete(&entry->certs);
|
||||
|
||||
if (new_chain->cert_chain[0]) {
|
||||
cert_chain_entry_t *root_ca_chain = sec_prot_certs_chain_entry_create();
|
||||
sec_prot_certs_cert_set(root_ca_chain, 0, (uint8_t *) new_chain->cert_chain[0], new_chain->cert_len[0]);
|
||||
sec_prot_certs_chain_list_add(&entry->certs.trusted_cert_chain_list, root_ca_chain);
|
||||
}
|
||||
|
||||
if (new_chain->cert_chain[1] && new_chain->key_chain[1]) {
|
||||
sec_prot_certs_cert_set(&entry->certs.own_cert_chain, 0, (uint8_t *) new_chain->cert_chain[1], new_chain->cert_len[1]);
|
||||
uint8_t key_len = strlen((char *) new_chain->key_chain[1]) + 1;
|
||||
sec_prot_certs_priv_key_set(&entry->certs.own_cert_chain, (uint8_t *) new_chain->key_chain[1], key_len);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
|
||||
{
|
||||
if (!interface_ptr || !eui_64) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (controller->pae_br_addr_write) {
|
||||
return controller->pae_br_addr_write(interface_ptr, eui_64);
|
||||
} else {
|
||||
memcpy(controller->br_eui_64, eui_64, 8);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64)
|
||||
{
|
||||
if (!interface_ptr || !eui_64) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||
if (!controller) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (controller->pae_br_addr_read) {
|
||||
return controller->pae_br_addr_read(interface_ptr, eui_64);
|
||||
} else {
|
||||
memcpy(eui_64, controller->br_eui_64, 8);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ws_pae_controller_timer(uint16_t ticks)
|
||||
{
|
||||
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
|
||||
if (entry->pae_timer) {
|
||||
entry->pae_timer(ticks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr)
|
||||
{
|
||||
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
|
||||
if (entry->interface_ptr == interface_ptr) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* HAVE_WS */
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WS_PAE_CONTROLLER_H_
|
||||
#define WS_PAE_CONTROLLER_H_
|
||||
|
||||
#ifdef HAVE_WS
|
||||
|
||||
/**
|
||||
* ws_pae_controller_set_target sets EAPOL target for PAE supplicant
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param target_pan_id EAPOL target PAN ID
|
||||
* \param target_eui_64 EAPOL target
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_set_target(protocol_interface_info_entry_t *interface_ptr, uint16_t target_pan_id, uint8_t *target_eui_64);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_authenticate start PAE supplicant authentication
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_authenticator_start start PAE authenticator
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param local_port local port
|
||||
* \param remote_addr remote address
|
||||
* \param remote_port remote port
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_init initializes PAE controller
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_init initializes PAE supplicant
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_init initializes PAE authenticator
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_stop stop PAE controller (e.g. on interface down)
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_delete delete PAE controller (e.g. failure to create interface)
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_certificate_chain_set set certificate chain
|
||||
*
|
||||
* \param chain certificate chain
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_certificate_chain_set(const arm_certificate_chain_entry_s *chain);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_nw_info_set set network information
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param pan_id PAD ID
|
||||
* \param network_name network name
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_nw_key_valid network key is valid i.e. used successfully on bootstrap
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_border_router_addr_write write border router address
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param eui_64 pointer to EUI-64
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_border_router_addr_read read border router address
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param eui_64 pointer to EUI-64
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_key_insert new GTK key available callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param gtk_index index of the new GTK key
|
||||
* \param gtk new GTK key
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_key_insert(protocol_interface_info_entry_t *interface_ptr, uint8_t gtk_index, uint8_t *gtk);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_auth_completed authentication completed callback
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param success true if authentication was successful
|
||||
*
|
||||
*/
|
||||
typedef void ws_pae_controller_auth_completed(protocol_interface_info_entry_t *interface_ptr, bool success);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_cb_register register PEA controller callbacks
|
||||
*
|
||||
* \param interface_ptr interface
|
||||
* \param completed authentication completed callback
|
||||
* \param key_insert GTK key insert callback
|
||||
*
|
||||
* \return < 0 failure
|
||||
* \return >= 0 success
|
||||
*
|
||||
*/
|
||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_key_insert *key_insert);
|
||||
|
||||
/**
|
||||
* ws_pae_controller_timer PAE controller timer call
|
||||
*
|
||||
* \param ticks elapsed ticks
|
||||
*
|
||||
*/
|
||||
void ws_pae_controller_timer(uint16_t ticks);
|
||||
|
||||
#else
|
||||
|
||||
#define ws_pae_controller_set_target(interface_ptr, target_pan_id, target_dest_eui_64)
|
||||
#define ws_pae_controller_authenticate(interface_ptr)
|
||||
|
||||
#define ws_pae_controller_authenticator_start(interface_ptr, local_port, remote_address, remote_port)
|
||||
|
||||
#define ws_pae_controller_border_router_addr_write(interface_ptr, eui_64) -1
|
||||
#define ws_pae_controller_border_router_addr_read(interface_ptr, eui_64) -1
|
||||
|
||||
#define ws_pae_controller_init(interface_ptr) 1
|
||||
#define ws_pae_controller_supp_init(interface_ptr) 1
|
||||
#define ws_pae_controller_auth_init(interface_ptr) 1
|
||||
|
||||
#define ws_pae_controller_stop(interface_ptr)
|
||||
#define ws_pae_controller_delete(interface_ptr)
|
||||
#define ws_pae_controller_cb_register(interface_ptr, completed, key_insert) 1
|
||||
#define ws_pae_controller_timer(ticks)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WS_PAE_CONTROLLER_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue