Merge commit '780e9afb8f3b8f09e66573e7d4ba096dd9a87dd7'

Nanostack v10.1.0 for Mbed OS 5.12

* commit '780e9afb8f3b8f09e66573e7d4ba096dd9a87dd7':
  Squashed 'features/nanostack/sal-stack-nanostack/' changes from 513a38e..c5ee9e4
pull/9838/head
Arto Kinnunen 2019-02-25 14:24:47 +02:00
commit b68e5edbc7
275 changed files with 23239 additions and 444 deletions

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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");

View File

@ -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 .*/

View File

@ -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");

View File

@ -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");

View File

@ -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.
*

View File

@ -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");

View File

@ -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");

View File

@ -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

View File

@ -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_ */

View File

@ -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");

View File

@ -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");

View File

@ -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,13 +148,21 @@ 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
uint32_t channel_spacing; ///< Channel spacing
uint32_t datarate; ///< Data rate
uint16_t number_of_channels; ///< Number of channels
phy_modulation_e modulation; ///< Modulation scheme
uint32_t channel_0_center_frequency; ///< Center frequency
uint32_t channel_spacing; ///< Channel spacing
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 */

View File

@ -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");

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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"

View File

@ -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;

View File

@ -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
}

View File

@ -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"

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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;

View File

@ -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"

View File

@ -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");

View File

@ -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"

View File

@ -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"

View File

@ -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);

View File

@ -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"

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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,7 +2870,9 @@ void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *
}
// generate address based on res1 bit
if (curBorderRouter->P_res1) {
thread_extension_dua_address_generate(cur, curPrefix->servicesPrefix, 64);
if (!thread_dhcpv6_address_entry_available(curPrefix->servicesPrefix, &cur->ip_addresses)) {
thread_extension_dua_address_generate(cur, curPrefix->servicesPrefix, 64);
}
}
} // for each borderRouterList

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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",
trace_ipv6_prefix(linkConfiguration->mesh_local_ula_prefix, 64),
trace_ipv6(source_address));
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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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",
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)));
}
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)));
main_list = thread_prefix_entry_get(&networkDataList->localPrefixList, prefixTlv);
if (!main_list) {

View File

@ -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"

View File

@ -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);

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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
}

View File

@ -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;
}
ns_list_add_to_end(&interface_ptr->indirect_tx_queue, tx_ptr);
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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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 */

View File

@ -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_ */

View File

@ -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 */

View File

@ -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_ */

View File

@ -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 */

View File

@ -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_ */

View File

@ -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 */

View File

@ -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_ */

View File

@ -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

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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 */

View File

@ -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");

View File

@ -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 */

View File

@ -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_ */

View File

@ -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 */

View File

@ -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