mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #13451 from artokin/nanostack_release_v12_4_0_for_5_15
[mbed-os-5.15] Nanostack release v12.4.0pull/13537/head
commit
b9c0170a8e
|
@ -97,6 +97,9 @@ extern "C" {
|
||||||
// RF_PAC
|
// RF_PAC
|
||||||
#define TXPWR 0x1F
|
#define TXPWR 0x1F
|
||||||
#define TXPWR_11 (11 << 0)
|
#define TXPWR_11 (11 << 0)
|
||||||
|
#define TXPWR_0 (0 << 0)
|
||||||
|
#define TXPWR_31 (31 << 0)
|
||||||
|
|
||||||
|
|
||||||
// RF_PADFE
|
// RF_PADFE
|
||||||
#define PADFE 0xC0
|
#define PADFE 0xC0
|
||||||
|
@ -165,6 +168,9 @@ extern "C" {
|
||||||
#define SR_2 (2 << 0)
|
#define SR_2 (2 << 0)
|
||||||
#define SR_1 (1 << 0)
|
#define SR_1 (1 << 0)
|
||||||
|
|
||||||
|
// BBC_FSKPHRTX
|
||||||
|
#define DW (1 << 2)
|
||||||
|
|
||||||
// BBC_OFDMPHRTX
|
// BBC_OFDMPHRTX
|
||||||
#define MCS 0x07
|
#define MCS 0x07
|
||||||
#define MCS_0 (0 << 0)
|
#define MCS_0 (0 << 0)
|
||||||
|
|
|
@ -103,6 +103,7 @@ static int rf_set_fsk_symbol_rate_configuration(uint32_t symbol_rate, rf_modules
|
||||||
static int rf_configure_by_ofdm_bandwidth_option(uint8_t option, uint32_t data_rate, rf_modules_e module);
|
static int rf_configure_by_ofdm_bandwidth_option(uint8_t option, uint32_t data_rate, rf_modules_e module);
|
||||||
static void rf_calculate_symbol_rate(uint32_t baudrate, phy_modulation_e modulation);
|
static void rf_calculate_symbol_rate(uint32_t baudrate, phy_modulation_e modulation);
|
||||||
static void rf_conf_set_cca_threshold(uint8_t percent);
|
static void rf_conf_set_cca_threshold(uint8_t percent);
|
||||||
|
static bool rf_conf_set_tx_power(uint8_t percent);
|
||||||
// Defined register read/write functions
|
// Defined register read/write functions
|
||||||
#define rf_read_bbc_register(x, y) rf_read_rf_register(x, (rf_modules_e)(y + 2))
|
#define rf_read_bbc_register(x, y) rf_read_rf_register(x, (rf_modules_e)(y + 2))
|
||||||
#define rf_read_common_register(x) rf_read_rf_register(x, COMMON)
|
#define rf_read_common_register(x) rf_read_rf_register(x, COMMON)
|
||||||
|
@ -134,7 +135,10 @@ static uint8_t bbc0_irq_mask = 0;
|
||||||
static uint8_t bbc1_irq_mask = 0;
|
static uint8_t bbc1_irq_mask = 0;
|
||||||
|
|
||||||
static bool rf_update_config = false;
|
static bool rf_update_config = false;
|
||||||
|
static bool rf_update_tx_power = false;
|
||||||
static int8_t cca_threshold = -80;
|
static int8_t cca_threshold = -80;
|
||||||
|
static uint8_t rf_tx_power = TXPWR_31;
|
||||||
|
static bool data_whitening_enabled = true;
|
||||||
static bool cca_enabled = true;
|
static bool cca_enabled = true;
|
||||||
static uint32_t rf_symbol_rate;
|
static uint32_t rf_symbol_rate;
|
||||||
|
|
||||||
|
@ -303,9 +307,25 @@ static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_pt
|
||||||
case PHY_EXTENSION_SET_CCA_THRESHOLD:
|
case PHY_EXTENSION_SET_CCA_THRESHOLD:
|
||||||
rf_conf_set_cca_threshold(*data_ptr);
|
rf_conf_set_cca_threshold(*data_ptr);
|
||||||
break;
|
break;
|
||||||
|
case PHY_EXTENSION_SET_TX_POWER:
|
||||||
|
if (*data_ptr > 100) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rf_update_tx_power = rf_conf_set_tx_power(*data_ptr);
|
||||||
|
if (rf_update_tx_power && (rf_state == RF_IDLE)) {
|
||||||
|
rf_receive(rf_rx_channel, rf_module);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD:
|
case PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD:
|
||||||
cca_threshold = (int8_t) *data_ptr; // *NOPAD*
|
cca_threshold = (int8_t) *data_ptr; // *NOPAD*
|
||||||
break;
|
break;
|
||||||
|
case PHY_EXTENSION_SET_DATA_WHITENING:
|
||||||
|
data_whitening_enabled = (bool) *data_ptr; // *NOPAD*
|
||||||
|
rf_update_config = true;
|
||||||
|
if (rf_state == RF_IDLE) {
|
||||||
|
rf_receive(rf_rx_channel, rf_module);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PHY_EXTENSION_SET_802_15_4_MODE:
|
case PHY_EXTENSION_SET_802_15_4_MODE:
|
||||||
mac_mode = (phy_802_15_4_mode_t) *data_ptr; // *NOPAD*
|
mac_mode = (phy_802_15_4_mode_t) *data_ptr; // *NOPAD*
|
||||||
if (mac_mode == IEEE_802_15_4_2011) {
|
if (mac_mode == IEEE_802_15_4_2011) {
|
||||||
|
@ -418,6 +438,12 @@ static void rf_init_registers(rf_modules_e module)
|
||||||
rf_write_bbc_register_field(BBC_AFC0, module, AFEN0, 0);
|
rf_write_bbc_register_field(BBC_AFC0, module, AFEN0, 0);
|
||||||
// Enable FSK
|
// Enable FSK
|
||||||
if (phy_current_config.modulation == M_2FSK) {
|
if (phy_current_config.modulation == M_2FSK) {
|
||||||
|
// Enable or disable data whitening
|
||||||
|
if (data_whitening_enabled) {
|
||||||
|
rf_write_bbc_register_field(BBC_FSKPHRTX, module, DW, DW);
|
||||||
|
} else {
|
||||||
|
rf_write_bbc_register_field(BBC_FSKPHRTX, module, DW, 0);
|
||||||
|
}
|
||||||
rf_write_bbc_register_field(BBC_PC, module, PT, BB_MRFSK);
|
rf_write_bbc_register_field(BBC_PC, module, PT, BB_MRFSK);
|
||||||
// Set bandwidth time product
|
// Set bandwidth time product
|
||||||
rf_write_bbc_register_field(BBC_FSKC0, module, BT, BT_20);
|
rf_write_bbc_register_field(BBC_FSKC0, module, BT, BT_20);
|
||||||
|
@ -474,8 +500,10 @@ static void rf_init_registers(rf_modules_e module)
|
||||||
// Enable external front end with configuration 3
|
// Enable external front end with configuration 3
|
||||||
rf_write_rf_register_field(RF_PADFE, module, PADFE, RF_FEMODE3);
|
rf_write_rf_register_field(RF_PADFE, module, PADFE, RF_FEMODE3);
|
||||||
// Output power at 900MHz: 0 dBm with FSK/QPSK, less than -5 dBm with OFDM
|
// Output power at 900MHz: 0 dBm with FSK/QPSK, less than -5 dBm with OFDM
|
||||||
rf_write_rf_register_field(RF_PAC, module, TXPWR, TXPWR_11);
|
rf_tx_power = TXPWR_11;
|
||||||
}
|
}
|
||||||
|
// Set TX output power
|
||||||
|
rf_write_rf_register_field(RF_PAC, module, TXPWR, rf_tx_power);
|
||||||
// Enable analog voltage regulator
|
// Enable analog voltage regulator
|
||||||
rf_write_rf_register_field(RF_AUXS, module, AVEN, AVEN);
|
rf_write_rf_register_field(RF_AUXS, module, AVEN, AVEN);
|
||||||
// Disable filtering FCS
|
// Disable filtering FCS
|
||||||
|
@ -695,7 +723,7 @@ static void rf_handle_rx_start(void)
|
||||||
|
|
||||||
static void rf_receive(uint16_t rx_channel, rf_modules_e module)
|
static void rf_receive(uint16_t rx_channel, rf_modules_e module)
|
||||||
{
|
{
|
||||||
if ((receiver_enabled == true) && (rf_update_config == false) && (rx_channel == rf_rx_channel)) {
|
if ((receiver_enabled == true) && (rf_update_config == false) && (rf_update_tx_power == false) && (rx_channel == rf_rx_channel)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TEST_RX_DONE
|
TEST_RX_DONE
|
||||||
|
@ -706,6 +734,12 @@ static void rf_receive(uint16_t rx_channel, rf_modules_e module)
|
||||||
rf_init_registers(module);
|
rf_init_registers(module);
|
||||||
rf_change_state(RF_TXPREP, module);
|
rf_change_state(RF_TXPREP, module);
|
||||||
}
|
}
|
||||||
|
if (rf_update_tx_power == true) {
|
||||||
|
rf_update_tx_power = false;
|
||||||
|
rf_change_state(RF_TRX_OFF, module);
|
||||||
|
rf_write_rf_register_field(RF_PAC, module, TXPWR, rf_tx_power);
|
||||||
|
rf_change_state(RF_TXPREP, module);
|
||||||
|
}
|
||||||
if (rx_channel != rf_rx_channel) {
|
if (rx_channel != rf_rx_channel) {
|
||||||
rf_change_state(RF_TXPREP, module);
|
rf_change_state(RF_TXPREP, module);
|
||||||
rf_set_channel(rx_channel, module);
|
rf_set_channel(rx_channel, module);
|
||||||
|
@ -1170,6 +1204,17 @@ static void rf_conf_set_cca_threshold(uint8_t percent)
|
||||||
cca_threshold = MIN_CCA_THRESHOLD + (step * percent) / 100;
|
cca_threshold = MIN_CCA_THRESHOLD + (step * percent) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool rf_conf_set_tx_power(uint8_t percent)
|
||||||
|
{
|
||||||
|
uint8_t step = (TXPWR_31 - TXPWR_0);
|
||||||
|
uint8_t new_value = TXPWR_0 + (step * percent) / 100;
|
||||||
|
if (rf_tx_power != new_value) {
|
||||||
|
rf_tx_power = new_value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void rf_calculate_symbol_rate(uint32_t baudrate, phy_modulation_e modulation)
|
static void rf_calculate_symbol_rate(uint32_t baudrate, phy_modulation_e modulation)
|
||||||
{
|
{
|
||||||
uint8_t bits_in_symbols = 4;
|
uint8_t bits_in_symbols = 4;
|
||||||
|
|
|
@ -1328,7 +1328,7 @@ NanostackRfPhys2lp::NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName
|
||||||
#ifdef AT24MAC
|
#ifdef AT24MAC
|
||||||
_mac(i2c_sda, i2c_scl),
|
_mac(i2c_sda, i2c_scl),
|
||||||
#endif //AT24MAC
|
#endif //AT24MAC
|
||||||
_mac_addr(), _rf(NULL), _mac_set(false),
|
_mac_addr(), _rf(NULL), _test_pins(NULL), _mac_set(false),
|
||||||
_spi_sdi(spi_sdi), _spi_sdo(spi_sdo), _spi_sclk(spi_sclk), _spi_cs(spi_cs), _spi_sdn(spi_sdn),
|
_spi_sdi(spi_sdi), _spi_sdo(spi_sdo), _spi_sclk(spi_sclk), _spi_cs(spi_cs), _spi_sdn(spi_sdn),
|
||||||
_spi_gpio0(spi_gpio0), _spi_gpio1(spi_gpio1), _spi_gpio2(spi_gpio2), _spi_gpio3(spi_gpio3)
|
_spi_gpio0(spi_gpio0), _spi_gpio1(spi_gpio1), _spi_gpio2(spi_gpio2), _spi_gpio3(spi_gpio3)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,7 +26,7 @@ The purpose of the library is to provide a light, simple and general tracing sol
|
||||||
* The trace function uses `stdout` as the default output target because it goes directly to serial port in mbed-os.
|
* The trace function uses `stdout` as the default output target because it goes directly to serial port in mbed-os.
|
||||||
* The trace function produces traces like: `[<levl>][grp ]: msg`. This provides an easy way to detect trace prints and separate traces from normal prints (for example with _regex_).
|
* The trace function produces traces like: `[<levl>][grp ]: msg`. This provides an easy way to detect trace prints and separate traces from normal prints (for example with _regex_).
|
||||||
* This approach requires a `sprintf` implementation (`stdio.h`). The memory consumption is pretty high, but it allows an efficient way to format traces.
|
* This approach requires a `sprintf` implementation (`stdio.h`). The memory consumption is pretty high, but it allows an efficient way to format traces.
|
||||||
* The solution is not Interrupt safe. (PRs are more than welcome.)
|
* The solution is not Interrupt safe. ([PRs](https://github.com/ARMmbed/mbed-trace/pulls) are more than welcome.)
|
||||||
* The solution is not thread safe by default. Thread safety for the actual trace calls can be enabled by providing wait and release callback functions that use mutexes defined by the application.
|
* The solution is not thread safe by default. Thread safety for the actual trace calls can be enabled by providing wait and release callback functions that use mutexes defined by the application.
|
||||||
|
|
||||||
## Examples of traces
|
## Examples of traces
|
||||||
|
@ -43,7 +43,7 @@ The purpose of the library is to provide a light, simple and general tracing sol
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
* Initialize the serial port so that `stdout` works. You can verify that the serial port works using the `printf()` function.
|
* Initialize the serial port so that `stdout` works. You can verify that the serial port works using the `printf()` function.
|
||||||
* if you want to redirect the traces somewhere else, see the [trace API](https://github.com/ARMmbed/mbed-trace/blob/master/mbed-trace/mbed_trace.h#L245).
|
* If you want to redirect the traces somewhere else, see the [trace API](https://github.com/ARMmbed/mbed-trace/blob/master/mbed-trace/mbed_trace.h#L245).
|
||||||
* To enable the tracing API:
|
* To enable the tracing API:
|
||||||
* With yotta: set `YOTTA_CFG_MBED_TRACE` to 1 or true. Setting the flag to 0 or false disables tracing.
|
* With yotta: set `YOTTA_CFG_MBED_TRACE` to 1 or true. Setting the flag to 0 or false disables tracing.
|
||||||
* [With mbed OS 5](#enabling-the-tracing-api-in-mbed-os-5)
|
* [With mbed OS 5](#enabling-the-tracing-api-in-mbed-os-5)
|
||||||
|
@ -54,7 +54,7 @@ The purpose of the library is to provide a light, simple and general tracing sol
|
||||||
* If thread safety is needed, configure the wait and release callback functions before initialization to enable the protection. Usually, this needs to be done only once in the application's lifetime.
|
* If thread safety is needed, configure the wait and release callback functions before initialization to enable the protection. Usually, this needs to be done only once in the application's lifetime.
|
||||||
* If [helping functions](#helping-functions) are used the mutex must be **recursive** (counting) so it can be acquired from a single thread repeatedly.
|
* If [helping functions](#helping-functions) are used the mutex must be **recursive** (counting) so it can be acquired from a single thread repeatedly.
|
||||||
* Call the trace initialization (`mbed_trace_init`) once before using any other APIs. It allocates the trace buffer and initializes the internal variables.
|
* Call the trace initialization (`mbed_trace_init`) once before using any other APIs. It allocates the trace buffer and initializes the internal variables.
|
||||||
* Define `TRACE_GROUP` in your source code (not in the header!) to use traces. It is a 1-4 characters long char-array (for example `#define TRACE_GROUP "APPL"`). This will be printed on every trace line.
|
* Define `TRACE_GROUP` in your **source code (not in the header)** to use traces. It is a 1-4 characters long char-array (for example `#define TRACE_GROUP "APPL"`). This will be printed on every trace line.
|
||||||
|
|
||||||
### Enabling the tracing API in mbed OS 5
|
### Enabling the tracing API in mbed OS 5
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ To do so, add the following to your mbed_app.json:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Don't forget to fulfill the other [prerequisites](#prerequisites)!
|
Do not forget to fulfill the other [prerequisites](#prerequisites)!
|
||||||
|
|
||||||
([Click here for more information on the configuration system](https://docs.mbed.com/docs/mbed-os-api/en/latest/config_system/))
|
([Click here for more information on the configuration system](https://docs.mbed.com/docs/mbed-os-api/en/latest/config_system/))
|
||||||
|
|
||||||
|
@ -204,6 +204,52 @@ int main(void){
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Run-time trace group filtering
|
||||||
|
|
||||||
|
The trace groups you have defined using the `TRACE_GROUP` macro in your .c/.cpp files can be used to control tracing at run-time.
|
||||||
|
|
||||||
|
| Function | Explanation |
|
||||||
|
|-----------------------------------|--------------------------------------------------------------|
|
||||||
|
|`mbed_trace_include_filters_get()` | Get the exclusion filter list string. |
|
||||||
|
|`mbed_trace_include_filters_set()` | Set trace list to include only the traces matching the list. |
|
||||||
|
|`mbed_trace_exclude_filters_get()` | Get the inclusion filter list string. |
|
||||||
|
|`mbed_trace_exclude_filters_set()` | Set trace list to exclude the traces matching the list. |
|
||||||
|
|
||||||
|
The filter list is a null terminated string of comma (`,`) separated trace group names. The default maximum length of the string is 24 characters, including the terminating null. Length can be changed by defining the macro `DEFAULT_TRACE_FILTER_LENGTH`. Exclude and include filters can be combined freely as they both have their own filtering list.
|
||||||
|
|
||||||
|
The matching is done simply using `strstr()` from C standard libraries.
|
||||||
|
|
||||||
|
### Examples of trace group filtering
|
||||||
|
|
||||||
|
Assuming we have 4 modules called "MAIN", "HELP", "CALC" and "PRNT" we could use the filters in the following ways.
|
||||||
|
|
||||||
|
#### Inclusion filter
|
||||||
|
|
||||||
|
To include only "MAIN" and "CALC" traces to the trace prints, we can do:
|
||||||
|
|
||||||
|
```
|
||||||
|
mbed_trace_include_filters_set("MAIN,CALC");
|
||||||
|
```
|
||||||
|
|
||||||
|
This would print out only the traces from "MAIN" and "CALC", since they are the trace groups matching the filter list. Trace groups "HELP" and "PRNT" would not be printed out at all.
|
||||||
|
|
||||||
|
## Exclusion filter
|
||||||
|
|
||||||
|
```
|
||||||
|
mbed_trace_exclude_filters_set("HELP,PRNT");
|
||||||
|
```
|
||||||
|
|
||||||
|
This would exclue trace groups "HELP" and "PRNT" out of trace printing, thus leaving only prints from "MAIN" and "CALC" visible in the tracing.
|
||||||
|
|
||||||
|
### Reset filter
|
||||||
|
|
||||||
|
```
|
||||||
|
mbed_trace_include_filters_set(NULL);
|
||||||
|
```
|
||||||
|
|
||||||
|
This would reset the inclusion filters back to nothing and assuming no exclusion filter is in place either, all trace groups prints would get printed.
|
||||||
|
|
||||||
|
|
||||||
## Unit tests
|
## Unit tests
|
||||||
|
|
||||||
To run unit tests:
|
To run unit tests:
|
||||||
|
|
|
@ -23,8 +23,18 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** \defgroup ns_list Linked list support library.
|
||||||
|
*
|
||||||
|
* The ns_list.h file provides a doubly-linked list/queue, providing O(1)
|
||||||
|
* performance for all insertion/removal operations, and access to either
|
||||||
|
* end of the list.
|
||||||
|
*
|
||||||
|
* See \ref ns_list.h for documentation.
|
||||||
|
*/
|
||||||
|
|
||||||
/** \file
|
/** \file
|
||||||
* \brief Linked list support library
|
* \ingroup ns_list
|
||||||
|
* \brief Linked list support library.
|
||||||
*
|
*
|
||||||
* The ns_list.h file provides a doubly-linked list/queue, providing O(1)
|
* The ns_list.h file provides a doubly-linked list/queue, providing O(1)
|
||||||
* performance for all insertion/removal operations, and access to either
|
* performance for all insertion/removal operations, and access to either
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# Copyright (c) 2019 ARM Limited
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
# Define compiler toolchain with CC or PLATFORM variables
|
# Define compiler toolchain with CC or PLATFORM variables
|
||||||
# Example (GCC toolchains)
|
# Example (GCC toolchains)
|
||||||
# make PLATFORM=arm-linux-gnueabi-
|
# make PLATFORM=arm-linux-gnueabi-
|
||||||
|
|
|
@ -19,6 +19,176 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup nanostack-eventloop Nanostack's event system.
|
||||||
|
* Small event scheduler and timer system written in C.
|
||||||
|
*
|
||||||
|
* This event system is originating from project called Nanostack and developed within Arm. Therefore
|
||||||
|
* some of the types and names within this library are prefixed with `ns_*` or `arm_*` or `eventOS*`.
|
||||||
|
*
|
||||||
|
* <h3>Concept</h3>
|
||||||
|
*
|
||||||
|
* Event loop uses a concept called tasklet, which is just a callback function that receives events.
|
||||||
|
* There can be as many as 128 tasklets registered if memory allows. This is only limited by event ID being just 8-bits.
|
||||||
|
* Each tasklet is first registered to the event system, which then gives 8 bit ID number for the tasklet.
|
||||||
|
*
|
||||||
|
* @startuml
|
||||||
|
* package "eventOS" {
|
||||||
|
* [eventOS_event.h] - event_handler_create
|
||||||
|
* }
|
||||||
|
* node "application" {
|
||||||
|
* [tasklet1.cpp] ..> event_handler_create : register
|
||||||
|
* [tasklet1.cpp] - tasklet1
|
||||||
|
* [tasklet2.cpp] ..> event_handler_create : register
|
||||||
|
* [tasklet2.cpp] - tasklet2
|
||||||
|
* [tasklet3.cpp] ..> event_handler_create : register
|
||||||
|
* [tasklet3.cpp] - tasklet3
|
||||||
|
* }
|
||||||
|
* @enduml
|
||||||
|
*
|
||||||
|
* Events are send to a specific tasklet, identified by its ID.
|
||||||
|
* Each event is coded into a \ref arm_event_s structure which is then pushed into event loop by calling eventOS_event_send().
|
||||||
|
*
|
||||||
|
* @startuml
|
||||||
|
* partition tasklet1.cpp {
|
||||||
|
* (*) --> tasklet1
|
||||||
|
* }
|
||||||
|
* partition "eventOS" {
|
||||||
|
* tasklet1 -->[event:\nreceiver: 3\nevent_id: 1] eventOS_event_send
|
||||||
|
* }
|
||||||
|
* partition tasklet3.cpp {
|
||||||
|
* eventOS_event_send -->[event:\nreceiver: 3\nevent_id: 1] tasklet3
|
||||||
|
* }
|
||||||
|
* @enduml
|
||||||
|
*
|
||||||
|
* <h3>Usage</h3>
|
||||||
|
*
|
||||||
|
* To send or receive events, you first need to register your event handler.
|
||||||
|
* \code
|
||||||
|
* // In header
|
||||||
|
* extern uint8_t my_eventhandler_id;
|
||||||
|
* #define INITIALIZATION_EVENT 0
|
||||||
|
* #define MY_EVENT 1
|
||||||
|
*
|
||||||
|
* // In my_handler.cpp
|
||||||
|
* void my_event_handler(arm_event_t *e)
|
||||||
|
* {
|
||||||
|
* switch (e->event_type) {
|
||||||
|
* case INITIALIZATION_EVENT:
|
||||||
|
* // Initialize my module
|
||||||
|
* break;
|
||||||
|
* case MY_EVENT:
|
||||||
|
* // Event received
|
||||||
|
* break;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Register the handler
|
||||||
|
* my_eventhandler_id = eventOS_event_handler_create(my_event_handler, INITIALIZATION_EVENT);
|
||||||
|
* if (my_eventhandler_id < 0) {
|
||||||
|
* // fail
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* Each event is basically a \ref arm_event_s structure. You need to fill in the arm_event_s::receiver field.
|
||||||
|
* Rest of the fields are optional, and used only by the receiving callback. So you have different options to
|
||||||
|
* deliver data to a receiving tasklet. The structure is copied by the event system, so temporary storage may be used,
|
||||||
|
* and the structure may be freed after it has been pushed into event system.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* // Send the event
|
||||||
|
* arm_event_t e = {
|
||||||
|
* .receiver = my_eventhandler_id,
|
||||||
|
* .event_type = MY_EVENT
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* if (eventOS_event_send(e) != 0) {
|
||||||
|
* // fail
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* Where required, event system allows you to delay the event propagation.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* // Wait 3 seconds before the event
|
||||||
|
* #define MY_DELAY_MS 3000
|
||||||
|
*
|
||||||
|
* arm_event_t e = {
|
||||||
|
* .receiver = my_eventhandler_id,
|
||||||
|
* .event_type = MY_EVENT
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* uint32_t delay = eventOS_event_timer_ms_to_ticks(MY_DELAY_MS);
|
||||||
|
* eventOS_event_send_after(e, delay);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* \sa eventOS_event.h
|
||||||
|
* \sa eventOS_event_send_at
|
||||||
|
* \sa eventOS_event_send_in
|
||||||
|
* \sa eventOS_event_send_after
|
||||||
|
* \sa eventOS_event_send_every
|
||||||
|
*
|
||||||
|
* <h3>Pre-allocated events</h3>
|
||||||
|
*
|
||||||
|
* Two options are provided to limit the heap usage. First option is to use recurring events with eventOS_event_send_every(),
|
||||||
|
* so your event is only allocated once. This allows you to create application that does not use heap after initialization phase.
|
||||||
|
*
|
||||||
|
* Second option is to use pre-allocated or statically allocated event structure. In this model you create a space for
|
||||||
|
* \ref arm_event_storage structure and send events using eventOS_event_send_user_allocated() call. This is also
|
||||||
|
* very robust, as there is no allocation, so the sending of the event will never fail because of lack of memory.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* static bool pending = false;
|
||||||
|
* static arm_event_storage_t e;
|
||||||
|
* static int8_t foo_tasklet_id;
|
||||||
|
*
|
||||||
|
* void notify_foo()
|
||||||
|
* {
|
||||||
|
* if (!pending) {
|
||||||
|
* pending = true;
|
||||||
|
* e.data.receiver = foo_tasklet_id;
|
||||||
|
* e.data.type = MY_EVENT;
|
||||||
|
* eventOS_event_send_user_allocated(&e);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* void foo_event_handler(arm_event_t *e)
|
||||||
|
* {
|
||||||
|
* pending = false;
|
||||||
|
* // ...
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* <h3>Initialization</h3>
|
||||||
|
*
|
||||||
|
* Event system does not use malloc(), free() or any system heap directly, but uses nsdynmemLIB.h library instead.
|
||||||
|
* Event system must first be initialized by callind eventOS_scheduler_init(). This is usually done just after ns_dyn_mem_init() call.
|
||||||
|
* Where porting is already provided, these both are initialized in function called ns_hal_init().
|
||||||
|
*
|
||||||
|
* After initialization, you can start the event loop by calling eventOS_scheduler_run() which will never return. This is usually
|
||||||
|
* end of the `main()` function.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* extern void my_event_handler(arm_event_t *e);
|
||||||
|
* extern int8_t my_eventhandler_id;
|
||||||
|
*
|
||||||
|
* void main(void)
|
||||||
|
* {
|
||||||
|
* ns_dyn_mem_init(NULL, HEAP_SIZE, NULL, NULL);
|
||||||
|
* eventOS_scheduler_init();
|
||||||
|
* my_eventhandler_id = eventOS_event_handler_create(my_event_handler, INITIALIZATION_EVENT);
|
||||||
|
* eventOS_scheduler_run()
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file eventOS_event.h
|
||||||
|
* \ingroup nanostack-eventloop
|
||||||
|
* \brief Nanostack's event loop.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "ns_types.h"
|
#include "ns_types.h"
|
||||||
#include "ns_list.h"
|
#include "ns_list.h"
|
||||||
|
|
||||||
|
@ -100,10 +270,10 @@ extern int8_t eventOS_event_send(const arm_event_t *event);
|
||||||
|
|
||||||
/* Alternate names for timer function from eventOS_event_timer.h;
|
/* Alternate names for timer function from eventOS_event_timer.h;
|
||||||
* implementations may one day merge */
|
* implementations may one day merge */
|
||||||
#define eventOS_event_send_at(event, at) eventOS_event_timer_request_at(event, at)
|
#define eventOS_event_send_at(event, at) eventOS_event_timer_request_at(event, at) ///< \copydoc eventOS_event_timer_request_at
|
||||||
#define eventOS_event_send_in(event, in) eventOS_event_timer_request_in(event, in)
|
#define eventOS_event_send_in(event, in) eventOS_event_timer_request_in(event, in) ///< \copydoc eventOS_event_timer_request_in
|
||||||
#define eventOS_event_send_after(event, after) eventOS_event_timer_request_after(event, after)
|
#define eventOS_event_send_after(event, after) eventOS_event_timer_request_after(event, after) ///< \copydoc eventOS_event_timer_request_after
|
||||||
#define eventOS_event_send_every(event, every) eventOS_event_timer_request_every(event, every)
|
#define eventOS_event_send_every(event, every) eventOS_event_timer_request_every(event, every) ///< \copydoc eventOS_event_timer_request_every
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Send user-allocated event to event scheduler.
|
* \brief Send user-allocated event to event scheduler.
|
||||||
|
|
|
@ -18,6 +18,14 @@
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file eventOS_event_timer.h
|
||||||
|
* \ingroup nanostack-eventloop
|
||||||
|
* \brief Functions for sending delayed events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "ns_types.h"
|
#include "ns_types.h"
|
||||||
#include "eventOS_event.h"
|
#include "eventOS_event.h"
|
||||||
|
|
||||||
|
@ -208,9 +216,8 @@ extern int8_t eventOS_event_timer_cancel(uint8_t event_id, int8_t tasklet_id);
|
||||||
/**
|
/**
|
||||||
* System Timer shortest time in milli seconds
|
* System Timer shortest time in milli seconds
|
||||||
*
|
*
|
||||||
* \param ticks Time in 10 ms resolution
|
* \return zero, if no timers are active.
|
||||||
*
|
* \return time in milliseconds to next timer event.
|
||||||
* \return none
|
|
||||||
*
|
*
|
||||||
* */
|
* */
|
||||||
extern uint32_t eventOS_event_timer_shortest_active_timer(void);
|
extern uint32_t eventOS_event_timer_shortest_active_timer(void);
|
||||||
|
|
|
@ -15,10 +15,16 @@
|
||||||
*/
|
*/
|
||||||
#ifndef EVENTOS_SCHEDULER_H_
|
#ifndef EVENTOS_SCHEDULER_H_
|
||||||
#define EVENTOS_SCHEDULER_H_
|
#define EVENTOS_SCHEDULER_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file eventOS_scheduler.h
|
||||||
|
* \ingroup nanostack-eventloop
|
||||||
|
* \brief Event scheduler's control functions.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "ns_types.h"
|
#include "ns_types.h"
|
||||||
|
|
||||||
/* Compatibility with older ns_types.h */
|
/* Compatibility with older ns_types.h */
|
||||||
|
|
|
@ -183,6 +183,14 @@ typedef void mcps_data_indication_ext(const mac_api_t *api, const mcps_data_ind_
|
||||||
typedef void mcps_ack_data_req_ext(const mac_api_t *api, mcps_ack_data_payload_t *data, int8_t rssi, uint8_t lqi);
|
typedef void mcps_ack_data_req_ext(const mac_api_t *api, mcps_ack_data_payload_t *data, int8_t rssi, uint8_t lqi);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief mcps_edfe_handler Callback for handle and detect edfe frame
|
||||||
|
* @param api The API which handled the response
|
||||||
|
* @param response_message Enhanced message response data and status
|
||||||
|
*/
|
||||||
|
typedef void mcps_edfe_handler(const mac_api_t *api, mcps_edfe_response_t *response_message);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief mcps_purge_confirm MCPS-PURGE confirm is called as a response to MCPS-PURGE request
|
* @brief mcps_purge_confirm MCPS-PURGE confirm is called as a response to MCPS-PURGE request
|
||||||
* @param api The API which handled the request
|
* @param api The API which handled the request
|
||||||
|
@ -254,6 +262,15 @@ typedef int8_t mac_api_enable_mcps_ext(mac_api_t *api,
|
||||||
mcps_data_confirm_ext *data_cnf_cb,
|
mcps_data_confirm_ext *data_cnf_cb,
|
||||||
mcps_ack_data_req_ext *ack_data_req_cb);
|
mcps_ack_data_req_ext *ack_data_req_cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief mac_api_enable_mcps_edfe_ext Initialises MAC 2015 extension for EDFE handler callbacks must be non-NULL.
|
||||||
|
* @param api mac_api_t pointer, which is created by application.
|
||||||
|
* @param edfe_ind_cb Upper layer function to handle and detect EDFE's
|
||||||
|
* @return -1 if error, -2 if OOM, 0 otherwise
|
||||||
|
*/
|
||||||
|
typedef int8_t mac_api_enable_mcps_edfe_ext(mac_api_t *api,
|
||||||
|
mcps_edfe_handler *edfe_ind_cb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Struct mac_api_s defines functions for two-way communications between external MAC and Upper layer.
|
* \brief Struct mac_api_s defines functions for two-way communications between external MAC and Upper layer.
|
||||||
* Application creates mac_api_t object by calling external MAC's creator function.
|
* Application creates mac_api_t object by calling external MAC's creator function.
|
||||||
|
@ -263,17 +280,18 @@ typedef int8_t mac_api_enable_mcps_ext(mac_api_t *api,
|
||||||
struct mac_api_s {
|
struct mac_api_s {
|
||||||
mac_api_initialize *mac_initialize; /**< MAC initialize function to use */
|
mac_api_initialize *mac_initialize; /**< MAC initialize function to use */
|
||||||
mac_api_enable_mcps_ext *mac_mcps_extension_enable; /**< MAC MCPS IE extension enable function, optional feature */
|
mac_api_enable_mcps_ext *mac_mcps_extension_enable; /**< MAC MCPS IE extension enable function, optional feature */
|
||||||
|
mac_api_enable_mcps_edfe_ext *mac_mcps_edfe_enable; /**< MAC MCPS MCPS EDFE frame extension enable function, optional feature */
|
||||||
//External MAC callbacks
|
//External MAC callbacks
|
||||||
mlme_request *mlme_req; /**< MAC MLME request function to use */
|
mlme_request *mlme_req; /**< MAC MLME request function to use */
|
||||||
mcps_data_request *mcps_data_req; /**< MAC MCPS data request function to use */
|
mcps_data_request *mcps_data_req; /**< MAC MCPS data request function to use */
|
||||||
mcps_data_request_ext *mcps_data_req_ext; /**< MAC MCPS data request with Information element extension function to use */
|
mcps_data_request_ext *mcps_data_req_ext; /**< MAC MCPS data request with Information element extension function to use */
|
||||||
mcps_purge_request *mcps_purge_req; /**< MAC MCPS purge request function to use */
|
mcps_purge_request *mcps_purge_req; /**< MAC MCPS purge request function to use */
|
||||||
|
|
||||||
//Upper layer callbacksMLME_ASSOCIATE
|
//Upper layer callbacksMLME_ASSOCIATE
|
||||||
mcps_data_confirm *data_conf_cb; /**< MAC MCPS data confirm callback function */
|
mcps_data_confirm *data_conf_cb; /**< MAC MCPS data confirm callback function */
|
||||||
mcps_data_confirm_ext *data_conf_ext_cb; /**< MAC MCPS data confirm with payload callback function */
|
mcps_data_confirm_ext *data_conf_ext_cb; /**< MAC MCPS data confirm with payload callback function */
|
||||||
mcps_data_indication *data_ind_cb; /**< MAC MCPS data indication callback function */
|
mcps_data_indication *data_ind_cb; /**< MAC MCPS data indication callback function */
|
||||||
mcps_data_indication_ext *data_ind_ext_cb; /**< MAC MCPS data indication with IE extension's callback function */
|
mcps_data_indication_ext *data_ind_ext_cb; /**< MAC MCPS data indication with IE extension's callback function */
|
||||||
|
mcps_edfe_handler *edfe_ind_cb; /**< MAC MCPS EDFE detection extension's callback function */
|
||||||
mcps_ack_data_req_ext *enhanced_ack_data_req_cb; /**< Enhanced ACK IE element and payload request from MAC user */
|
mcps_ack_data_req_ext *enhanced_ack_data_req_cb; /**< Enhanced ACK IE element and payload request from MAC user */
|
||||||
mcps_purge_confirm *purge_conf_cb; /**< MAC MCPS purge confirm callback function */
|
mcps_purge_confirm *purge_conf_cb; /**< MAC MCPS purge confirm callback function */
|
||||||
mlme_confirm *mlme_conf_cb; /**< MAC MLME confirm callback function */
|
mlme_confirm *mlme_conf_cb; /**< MAC MLME confirm callback function */
|
||||||
|
|
|
@ -44,6 +44,7 @@ typedef struct mcps_data_req_s {
|
||||||
bool PendingBit: 1; /**< Specifies whether more fragments are to be sent or not */
|
bool PendingBit: 1; /**< Specifies whether more fragments are to be sent or not */
|
||||||
bool SeqNumSuppressed: 1; /**< True suppress sequence number from frame. This will be only checked when 2015 extension is enabled */
|
bool SeqNumSuppressed: 1; /**< True suppress sequence number from frame. This will be only checked when 2015 extension is enabled */
|
||||||
bool PanIdSuppressed: 1; /**< True suppress PAN-id is done when possible from frame. This will be only checked when 2015 extension is enabled */
|
bool PanIdSuppressed: 1; /**< True suppress PAN-id is done when possible from frame. This will be only checked when 2015 extension is enabled */
|
||||||
|
bool ExtendedFrameExchange: 1; /**< True for Extended Frame change. This will be only checked when 2015 extension and enhanced frame is enabled */
|
||||||
mlme_security_t Key; /**< Security key */
|
mlme_security_t Key; /**< Security key */
|
||||||
} mcps_data_req_t;
|
} mcps_data_req_t;
|
||||||
|
|
||||||
|
@ -86,6 +87,7 @@ typedef struct mcps_data_ind_s {
|
||||||
uint16_t SrcPANId; /**< Source PAN ID */
|
uint16_t SrcPANId; /**< Source PAN ID */
|
||||||
uint8_t SrcAddr[8]; /**< Source address */
|
uint8_t SrcAddr[8]; /**< Source address */
|
||||||
unsigned DstAddrMode: 2; /**< Destination address mode */
|
unsigned DstAddrMode: 2; /**< Destination address mode */
|
||||||
|
bool DSN_suppressed: 1; /**< Indicate when DSN not include valid sequency id */
|
||||||
uint16_t DstPANId; /**< Destination PAN ID */
|
uint16_t DstPANId; /**< Destination PAN ID */
|
||||||
uint8_t DstAddr[8]; /**< Destination address */
|
uint8_t DstAddr[8]; /**< Destination address */
|
||||||
uint8_t mpduLinkQuality; /**< LQI value measured during reception of the MPDU */
|
uint8_t mpduLinkQuality; /**< LQI value measured during reception of the MPDU */
|
||||||
|
@ -164,5 +166,31 @@ typedef struct mcps_purge_conf_s {
|
||||||
uint8_t status; /**< Status of the purge performed */
|
uint8_t status; /**< Status of the purge performed */
|
||||||
} mcps_purge_conf_t;
|
} mcps_purge_conf_t;
|
||||||
|
|
||||||
|
#define MCPS_EDFE_NORMAL_FRAME 0 /**< Normal Data message normal behaviour */
|
||||||
|
#define MCPS_EDFE_MALFORMED_FRAME 1 /**< Drop whole packet */
|
||||||
|
#define MCPS_EDFE_TX_FRAME 2 /**< Tx message send data if pending in 1ms -5ms time window */
|
||||||
|
#define MCPS_EDFE_RESPONSE_FRAME 3 /**< Response message send data if pending in 1ms -5ms time window */
|
||||||
|
#define MCPS_EDFE_FINAL_FRAME_TX 4 /**< Final response message send in 1ms -5ms time window */
|
||||||
|
#define MCPS_EDFE_FINAL_FRAME_RX 5 /**< EDFE session can be close at MAC side and drop this packet */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief struct mcps_edfe_response_t EDFE detetction and response structure
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct mcps_edfe_response_s {
|
||||||
|
struct mcps_data_ie_list ie_elements; /**< IE hader and payload's elements from Packet */
|
||||||
|
struct mcps_data_req_ie_list ie_response; /**< IE hader and payload's elements for Response Packet */
|
||||||
|
uint8_t edfe_message_status; /**< Indicate Packet handler status */
|
||||||
|
uint8_t message_handle; /**< EDFE Data request message ID for detect pending data at LLC layer*/
|
||||||
|
int8_t rssi; /**< Received packet signal streng in dbm */
|
||||||
|
unsigned SrcAddrMode: 2; /**< Source address mode: used for RX validation and TX purpose */
|
||||||
|
unsigned DstAddrMode: 2; /**< Destination address mode: used for RX validation and TX purpose */
|
||||||
|
uint8_t Address[8]; /**< RX: Packet Address Src & TX Response Destination address */
|
||||||
|
bool SeqNumSuppressed: 1; /**< True suppress sequence number from frame. This will be only checked when 2015 extension is enabled */
|
||||||
|
bool PanIdSuppressed: 1; /**< True suppress PAN-id is done when possible from frame. */
|
||||||
|
bool wait_response: 1; /**< True enable response wait timer and re-send operation. */
|
||||||
|
bool use_message_handle_to_discover: 1; /**< EDFE Data request message ID is valid at message_handle. */
|
||||||
|
} mcps_edfe_response_t;
|
||||||
|
|
||||||
|
|
||||||
#endif // MAC_MCPS_H
|
#endif // MAC_MCPS_H
|
||||||
|
|
|
@ -264,6 +264,8 @@ typedef enum {
|
||||||
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
|
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
|
||||||
macDefaultKeySource = 0x7c, /*<Default key source*/
|
macDefaultKeySource = 0x7c, /*<Default key source*/
|
||||||
//NON standard extension
|
//NON standard extension
|
||||||
|
macEdfeForceStop = 0xf2, /*< Use this command for Data wait timeout at LLC: Mac stop Edfe session data wait and enable normal FHSS mode */
|
||||||
|
macSetDataWhitening = 0xf3, /*< Enable or disable data whitening, boolean true for enable, false for disable */
|
||||||
macCCAThresholdStart = 0xf4, /*< Start automatic CCA threshold */
|
macCCAThresholdStart = 0xf4, /*< Start automatic CCA threshold */
|
||||||
macDevicePendingAckTrig = 0xf5, /*< Trig Pending ACK for Accepted Data packet for temporary neighbour */
|
macDevicePendingAckTrig = 0xf5, /*< Trig Pending ACK for Accepted Data packet for temporary neighbour */
|
||||||
mac802_15_4Mode = 0xf6, /*<IEEE 802.15.4 mode*/
|
mac802_15_4Mode = 0xf6, /*<IEEE 802.15.4 mode*/
|
||||||
|
|
|
@ -286,6 +286,12 @@ typedef struct {
|
||||||
uint8_t *beacon_payload_tlv_ptr; /**< Optional steering parameters. */
|
uint8_t *beacon_payload_tlv_ptr; /**< Optional steering parameters. */
|
||||||
} network_driver_setup_s;
|
} network_driver_setup_s;
|
||||||
|
|
||||||
|
/** CCA threshold table */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t number_of_channels; /**< Number of channels */
|
||||||
|
const int8_t *cca_threshold_table; /**< CCA threshold table */
|
||||||
|
} cca_threshold_table_s;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init 6LoWPAN library
|
* Init 6LoWPAN library
|
||||||
*
|
*
|
||||||
|
@ -1135,6 +1141,20 @@ extern int8_t arm_nwk_set_cca_threshold(int8_t interface_id, uint8_t cca_thresho
|
||||||
*/
|
*/
|
||||||
extern int8_t arm_nwk_set_tx_output_power(int8_t interface_id, uint8_t tx_power);
|
extern int8_t arm_nwk_set_tx_output_power(int8_t interface_id, uint8_t tx_power);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get CCA threshold table.
|
||||||
|
*
|
||||||
|
* This function can be used to read CCA threshold table.
|
||||||
|
* CCA threshold table structure contains number of channels and an array indicating the currently used CCA threshold value of each channel. CCA threshold values are updated by library continuously.
|
||||||
|
* If channels are reconfigured, number of channels and table length are changed automatically. User should check the table length (number of channels) before reading the table.
|
||||||
|
* Automatic CCA threshold feature may not be enabled before interface is up, causing function to return NULL.
|
||||||
|
* Returned pointer to cca_threshold_table_s structure is valid until interface is destroyed. Re-reading the pointer with this function is allowed any time.
|
||||||
|
*
|
||||||
|
* \param interface_id Network interface ID.
|
||||||
|
* \return NULL if automatic CCA threshold feature is not enabled, otherwise pointer to CCA threshold structure.
|
||||||
|
*/
|
||||||
|
extern const cca_threshold_table_s *arm_nwk_get_cca_threshold_table(int8_t interface_id);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,4 +131,50 @@ int8_t arm_nwk_ipv6_opaque_iid_key(const void *secret_key, uint8_t key_len);
|
||||||
*/
|
*/
|
||||||
int8_t arm_nwk_ipv6_opaque_iid_enable(int8_t interface_id, bool enable);
|
int8_t arm_nwk_ipv6_opaque_iid_enable(int8_t interface_id, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Enable/disable default route in Router advertisements
|
||||||
|
*
|
||||||
|
* Enable or disable RFC 4861 Default router configuration in router advertisements.
|
||||||
|
* This makes the device a default router in the interface.
|
||||||
|
*
|
||||||
|
* \param interface_id Interface ID.
|
||||||
|
* \param enable True to enable.
|
||||||
|
* \return 0 enabled/disabled OK.
|
||||||
|
* \return <0 failed (for example invalid interface ID).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t arm_nwk_ipv6_default_route_enable(int8_t interface_id, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief add Recursive DNS Server Option information to Router advertisements
|
||||||
|
*
|
||||||
|
* Add Recursive DNS Server Option from RFC 8106 to router advertisements.
|
||||||
|
* This makes it possible to configure DNS server address to other devices connected to the interface.
|
||||||
|
*
|
||||||
|
* \param interface_id Interface ID.
|
||||||
|
* \param address 16 byte array for IPv6 address.
|
||||||
|
* \param lifetime advertised lifetime of the entry. 0 to delete address.
|
||||||
|
* \return 0 DNS server option option successful.
|
||||||
|
* \return <0 failed (for example invalid interface ID).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t arm_nwk_ipv6_dns_server_add(int8_t interface_id, uint8_t *address, uint32_t lifetime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief add DNS Search List Option information to Router advertisements
|
||||||
|
*
|
||||||
|
* Add DNS Search List Option from RFC 8106 to router advertisements.
|
||||||
|
* This makes it possible to configure DNS search list to other devices connected to the interface.
|
||||||
|
*
|
||||||
|
* \param interface_id Interface ID.
|
||||||
|
* \param data byte array encoded following https://tools.ietf.org/html/rfc1035#section-3.1.
|
||||||
|
* \param data_len Length of the byte array
|
||||||
|
* \param lifetime advertised lifetime of the entry. 0 to delete address.
|
||||||
|
* \return 0 DNS server option option successful.
|
||||||
|
* \return <0 failed (for example invalid interface ID).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t arm_nwk_ipv6_dns_search_list_add(int8_t interface_id, uint8_t *data, uint16_t data_len, uint32_t lifetime);
|
||||||
|
|
||||||
|
|
||||||
#endif /* NET_IPV6_API_H_ */
|
#endif /* NET_IPV6_API_H_ */
|
||||||
|
|
|
@ -167,6 +167,43 @@ int ws_test_gtk_time_settings_set(
|
||||||
*/
|
*/
|
||||||
int ws_test_next_gtk_set(int8_t interface_id, uint8_t *gtk[4]);
|
int ws_test_next_gtk_set(int8_t interface_id, uint8_t *gtk[4]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets 6LoWPAN fragmentation MTU size to test fragmentation
|
||||||
|
*
|
||||||
|
* \param interface_id Network interface ID.
|
||||||
|
* \param mtu_size Size of 6LoWPAN MTU when fragmentation occurs.
|
||||||
|
*
|
||||||
|
* \return 0 Success
|
||||||
|
* \return <0 Failure
|
||||||
|
*/
|
||||||
|
int ws_test_6lowpan_fragmentation_mtu_size_set(int8_t interface_id, uint16_t mtu_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable First EDFE data packet send.
|
||||||
|
*
|
||||||
|
* Made only for test purpose for test EDFE client Data wait timeout.
|
||||||
|
*
|
||||||
|
* \param interface_id Network interface ID.
|
||||||
|
* \param skip True for skip first data packet false disable unused flag.
|
||||||
|
*
|
||||||
|
* \return 0 Success
|
||||||
|
* \return <0 Failure
|
||||||
|
*/
|
||||||
|
void ws_test_skip_edfe_data_send(int8_t interface_id, bool skip);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop configured EDFE data packets.
|
||||||
|
*
|
||||||
|
* Made only for test purpose for test EDFE data sender retry send logic.
|
||||||
|
*
|
||||||
|
* \param interface_id Network interface ID.
|
||||||
|
* \param number_of_dropped_frames How many packets will be dropped.
|
||||||
|
*
|
||||||
|
* \return 0 Success
|
||||||
|
* \return <0 Failure
|
||||||
|
*/
|
||||||
|
int8_t ws_test_drop_edfe_data_frames(int8_t interface_id, uint8_t number_of_dropped_frames);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -81,6 +81,7 @@ typedef enum {
|
||||||
PHY_EXTENSION_SET_TX_POWER, /**< Set TX output power which is given as percentage of maximum. 0 is the lowest possible TX power and 100 is the highest possible TX power */
|
PHY_EXTENSION_SET_TX_POWER, /**< Set TX output power which is given as percentage of maximum. 0 is the lowest possible TX power and 100 is the highest possible TX power */
|
||||||
PHY_EXTENSION_SET_CCA_THRESHOLD, /**< Set CCA threshold which is given as percentage of maximum threshold. 0 is the lowest(strictest) possible threshold and 100 is the highest possible threshold */
|
PHY_EXTENSION_SET_CCA_THRESHOLD, /**< Set CCA threshold which is given as percentage of maximum threshold. 0 is the lowest(strictest) possible threshold and 100 is the highest possible threshold */
|
||||||
PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD, /**< Set CCA threshold which is given as dBm. This value is set in PHY_LINK_CCA_PREPARE callback and PHY driver should update the CCA threshold configuration */
|
PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD, /**< Set CCA threshold which is given as dBm. This value is set in PHY_LINK_CCA_PREPARE callback and PHY driver should update the CCA threshold configuration */
|
||||||
|
PHY_EXTENSION_SET_DATA_WHITENING, /**< Enable or disable data whitening. Boolean true for enable, false for disable */
|
||||||
PHY_EXTENSION_SET_802_15_4_MODE /**< Set IEEE 802.15.4 mode as defined by phy_802_15_4_mode_t*/
|
PHY_EXTENSION_SET_802_15_4_MODE /**< Set IEEE 802.15.4 mode as defined by phy_802_15_4_mode_t*/
|
||||||
} phy_extension_type_e;
|
} phy_extension_type_e;
|
||||||
|
|
||||||
|
|
|
@ -712,11 +712,12 @@ static inline int8_t socket_read_session_address(int8_t socket, ns_address_t *ad
|
||||||
* | SOCKET_IPV6_MULTICAST_LOOP | bool | Yes | Yes | No |
|
* | SOCKET_IPV6_MULTICAST_LOOP | bool | Yes | Yes | No |
|
||||||
* | SOCKET_IPV6_JOIN_GROUP | ns_ipv6_mreq_t | Set only | No | No |
|
* | SOCKET_IPV6_JOIN_GROUP | ns_ipv6_mreq_t | Set only | No | No |
|
||||||
* | SOCKET_IPV6_LEAVE_GROUP | ns_ipv6_mreq_t | Set only | No | No |
|
* | SOCKET_IPV6_LEAVE_GROUP | ns_ipv6_mreq_t | Set only | No | No |
|
||||||
|
* | SOCKET_LATENCY | ns_ipv6_latency_t | Get only | No | No |
|
||||||
|
* | SOCKET_STAGGER | ns_ipv6_stagger_t | Get only | No | No |
|
||||||
|
* | SOCKET_EDFE_MODE | bool | Set only | No | No |
|
||||||
* | SOCKET_BROADCAST_PAN | int8_t | Yes | No | No |
|
* | SOCKET_BROADCAST_PAN | int8_t | Yes | No | No |
|
||||||
* | SOCKET_LINK_LAYER_SECURITY | int8_t | Yes | No | No |
|
* | SOCKET_LINK_LAYER_SECURITY | int8_t | Yes | No | No |
|
||||||
* | SOCKET_INTERFACE_SELECT | int8_t | Yes | No | No |
|
* | SOCKET_INTERFACE_SELECT | int8_t | Yes | No | No |
|
||||||
* | SOCKET_LATENCY | ns_ipv6_latency_t | Get only | No | No |
|
|
||||||
* | SOCKET_STAGGER | ns_ipv6_stagger_t | Get only | No | No |
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -755,11 +756,10 @@ static inline int8_t socket_read_session_address(int8_t socket, ns_address_t *ad
|
||||||
#define SOCKET_IPV6_JOIN_GROUP 15
|
#define SOCKET_IPV6_JOIN_GROUP 15
|
||||||
/** Leave a multicast group, using ns_ipv6_mreq_t */
|
/** Leave a multicast group, using ns_ipv6_mreq_t */
|
||||||
#define SOCKET_IPV6_LEAVE_GROUP 16
|
#define SOCKET_IPV6_LEAVE_GROUP 16
|
||||||
/** Read estimated latency to reach destination */
|
|
||||||
#define SOCKET_LATENCY 17
|
|
||||||
/** Read estimated stagger value that can be used as initial delay after bootstrap or firmware update. */
|
|
||||||
#define SOCKET_STAGGER 18
|
|
||||||
|
|
||||||
|
#define SOCKET_LATENCY 0xf9 /**< Not standard, read estimated latency to reach destination */
|
||||||
|
#define SOCKET_STAGGER 0xfa /**< Not standard, read estimated stagger value that can be used as initial delay after bootstrap or firmware update. */
|
||||||
|
#define SOCKET_EDFE_MODE 0xfb /**< Not standard, Extended Directed Frame Exchange mode enabled/disabled in MAC layer */
|
||||||
#define SOCKET_BROADCAST_PAN 0xfc /**< Internal use - transmit with IEEE 802.15.4 broadcast PAN ID */
|
#define SOCKET_BROADCAST_PAN 0xfc /**< Internal use - transmit with IEEE 802.15.4 broadcast PAN ID */
|
||||||
#define SOCKET_LINK_LAYER_SECURITY 0xfd /**< Not standard enable or disable socket security at link layer (For 802.15.4). */
|
#define SOCKET_LINK_LAYER_SECURITY 0xfd /**< Not standard enable or disable socket security at link layer (For 802.15.4). */
|
||||||
#define SOCKET_INTERFACE_SELECT 0xfe /**< Not standard socket interface ID. */
|
#define SOCKET_INTERFACE_SELECT 0xfe /**< Not standard socket interface ID. */
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
typedef struct bbr_information {
|
typedef struct bbr_information {
|
||||||
/** Timestamp of the the device. Can be used as version number*/
|
/** Timestamp of the the device. Can be used as version number*/
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
|
/** Default route Link Local address of north bound router*/
|
||||||
|
uint8_t gateway[16];
|
||||||
/** Border router dodag id */
|
/** Border router dodag id */
|
||||||
uint8_t dodag_id[16];
|
uint8_t dodag_id[16];
|
||||||
/** Address prefix given to devices in network set to 0 if not available*/
|
/** Address prefix given to devices in network set to 0 if not available*/
|
||||||
|
@ -130,9 +132,9 @@ int ws_bbr_info_get(int8_t interface_id, bbr_information_t *info_ptr);
|
||||||
*
|
*
|
||||||
* Table is Parent child relation using the Global address IID of the devices
|
* Table is Parent child relation using the Global address IID of the devices
|
||||||
* To get the full IPv6 address of the device.
|
* To get the full IPv6 address of the device.
|
||||||
* IPv6 = Global Prefix + IID.
|
* IPv6 = Global Prefix + IID.
|
||||||
*
|
*
|
||||||
* Routing table is in the format: 18 bytes per entry
|
* Routing table is in the format: 16 bytes per entry
|
||||||
* | Node IID 8 bytes | parent IID 8 bytes |
|
* | Node IID 8 bytes | parent IID 8 bytes |
|
||||||
* | 1122112211221122 | 1111111111111111 |
|
* | 1122112211221122 | 1111111111111111 |
|
||||||
* | 1133113311331133 | 1111111111111111 |
|
* | 1133113311331133 | 1111111111111111 |
|
||||||
|
@ -142,15 +144,18 @@ int ws_bbr_info_get(int8_t interface_id, bbr_information_t *info_ptr);
|
||||||
* | 1177117711771177 | 1155115511551155 |
|
* | 1177117711771177 | 1155115511551155 |
|
||||||
* | 1188118811881188 | 1177117711771177 |
|
* | 1188118811881188 | 1177117711771177 |
|
||||||
*
|
*
|
||||||
* Order is not assured only parent child link is given in random order
|
* Order is not assured only parent child link is given in random order,
|
||||||
*
|
*
|
||||||
* Return value is device amount in network divided by 16 bytes per route entry
|
* When preparing to call this function ws_bbr_info_get function should be called to get the amount of devices in the network.
|
||||||
|
* Memory for table is allocated based on the size of network and needs to be sizeof(bbr_route_info_t) * amount of entries.
|
||||||
*
|
*
|
||||||
* \param interface_id interface ID of the Wi-SUN network
|
* Return value is amount of route entries written to the table.
|
||||||
* \param table_ptr Application allocated memory block where routing table is written.
|
*
|
||||||
|
* \param interface_id interface ID of the Wi-SUN network.
|
||||||
|
* \param table_ptr Application allocated memory where routing table is written.
|
||||||
* \param table_len Length of the table allocated by application given as amount of entries.
|
* \param table_len Length of the table allocated by application given as amount of entries.
|
||||||
*
|
*
|
||||||
* \return 0 - x on success indicates amount of bytes written to the table_ptr
|
* \return 0 - x on success indicates amount of Route entries written to the table_ptr
|
||||||
* \return <0 in case of errors
|
* \return <0 in case of errors
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -317,7 +322,7 @@ int ws_bbr_pan_configuration_get(int8_t interface_id, uint16_t *pan_id);
|
||||||
int ws_bbr_pan_configuration_validate(int8_t interface_id, uint16_t pan_id);
|
int ws_bbr_pan_configuration_validate(int8_t interface_id, uint16_t pan_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_bbr_key_storage_memory_set sets memory used for key storages
|
* Sets memory used for key storages
|
||||||
*
|
*
|
||||||
* This functions can be used to set memory used by EAPOL key storage. When memory
|
* This functions can be used to set memory used by EAPOL key storage. When memory
|
||||||
* areas are set, module does not allocate memory internally from heap.
|
* areas are set, module does not allocate memory internally from heap.
|
||||||
|
@ -334,7 +339,7 @@ int ws_bbr_pan_configuration_validate(int8_t interface_id, uint16_t pan_id);
|
||||||
int ws_bbr_key_storage_memory_set(int8_t interface_id, uint8_t key_storages_number, const uint16_t *key_storage_size, void **key_storages);
|
int ws_bbr_key_storage_memory_set(int8_t interface_id, uint8_t key_storages_number, const uint16_t *key_storage_size, void **key_storages);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_bbr_key_storage_settings_set sets key storage settings
|
* Sets key storage settings
|
||||||
*
|
*
|
||||||
* This functions can be used to set the settings of EAPOL key storage.
|
* This functions can be used to set the settings of EAPOL key storage.
|
||||||
* Allocation max number and allocation size sets the settings that are used when key storage
|
* Allocation max number and allocation size sets the settings that are used when key storage
|
||||||
|
@ -352,4 +357,68 @@ int ws_bbr_key_storage_memory_set(int8_t interface_id, uint8_t key_storages_numb
|
||||||
*/
|
*/
|
||||||
int ws_bbr_key_storage_settings_set(int8_t interface_id, uint8_t alloc_max_number, uint16_t alloc_size, uint16_t storing_interval);
|
int ws_bbr_key_storage_settings_set(int8_t interface_id, uint8_t alloc_max_number, uint16_t alloc_size, uint16_t storing_interval);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set RADIUS server IPv6 address
|
||||||
|
*
|
||||||
|
* Function sets external RADIUS server IPv6 address to Border Router. Setting the
|
||||||
|
* address enables external RADIUS server interface on Border Router. To disable external
|
||||||
|
* RADIUS server interface, call the function with remote address set to NULL. The RADIUS
|
||||||
|
* shared secret must be set before address is set using ws_bbr_radius_shared_secret_set()
|
||||||
|
* call.
|
||||||
|
*
|
||||||
|
* \param interface_id Network interface ID.
|
||||||
|
* \param address Pointer to IPv6 address or NULL to disable RADIUS. Address is in binary format (16 bytes).
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int ws_bbr_radius_address_set(int8_t interface_id, const uint8_t *address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get RADIUS server IPv6 address
|
||||||
|
*
|
||||||
|
* Function gets external RADIUS server IPv6 address to Border Router.
|
||||||
|
*
|
||||||
|
* \param interface_id Network interface ID.
|
||||||
|
* \param address buffer where to write address, must have space at least for 39 characters and NUL terminator
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int ws_bbr_radius_address_get(int8_t interface_id, uint8_t *address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set RADIUS shared secret
|
||||||
|
*
|
||||||
|
* Function sets RADIUS shared secret to Border Router. Shared secret may be an
|
||||||
|
* ASCII string. Check the format and length constraints for the shared secret from
|
||||||
|
* the documentation of RADIUS server you are connecting to.
|
||||||
|
*
|
||||||
|
* \param interface_id Network interface ID.
|
||||||
|
* \param shared_secret_len The length of the shared secret in bytes.
|
||||||
|
* \param shared_secret Pointer to shared secret. Can be 8-bit ASCII string or byte array. Is not NUL terminated.
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int ws_bbr_radius_shared_secret_set(int8_t interface_id, const uint16_t shared_secret_len, const uint8_t *shared_secret);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get RADIUS shared secret
|
||||||
|
*
|
||||||
|
* Function gets RADIUS shared secret to Border Router.
|
||||||
|
*
|
||||||
|
* \param interface_id Network interface ID.
|
||||||
|
* \param shared_secret_len On function call, is the size of the shared secret write buffer in bytes, on return is the shared secret length in bytes.
|
||||||
|
* \param shared_secret Pointer to buffer where to write shared secret or NULL. At maximum, bytes set by the length parameter are written. If NULL only buffer length is returned.
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int ws_bbr_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret_len, uint8_t *shared_secret);
|
||||||
|
|
||||||
#endif /* WS_BBR_API_H_ */
|
#endif /* WS_BBR_API_H_ */
|
||||||
|
|
|
@ -103,6 +103,24 @@ typedef struct ws_statistics {
|
||||||
uint32_t asynch_rx_count;
|
uint32_t asynch_rx_count;
|
||||||
} ws_statistics_t;
|
} ws_statistics_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Struct ws_info defines the Wi-SUN stack state.
|
||||||
|
*/
|
||||||
|
typedef struct ws_stack_info {
|
||||||
|
/** Parent link local address */
|
||||||
|
uint8_t parent[16];
|
||||||
|
/** parent RSSI Out measured RSSI value calculated using EWMA specified by Wi-SUN from range of -174 (0) to +80 (254) dBm.*/
|
||||||
|
uint8_t rsl_out;
|
||||||
|
/** parent RSSI in measured RSSI value calculated using EWMA specified by Wi-SUN from range of -174 (0) to +80 (254) dBm.*/
|
||||||
|
uint8_t rsl_in;
|
||||||
|
/** ETX To border router */
|
||||||
|
uint16_t routing_cost;
|
||||||
|
/** Network PAN ID */
|
||||||
|
uint16_t pan_id;
|
||||||
|
/** Wi-SUN join state defined by Wi-SUN specification 1-5*/
|
||||||
|
uint8_t join_state;
|
||||||
|
} ws_stack_info_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize Wi-SUN stack.
|
* Initialize Wi-SUN stack.
|
||||||
*
|
*
|
||||||
|
@ -583,6 +601,20 @@ int ws_statistics_start(
|
||||||
int ws_statistics_stop(
|
int ws_statistics_stop(
|
||||||
int8_t interface_id);
|
int8_t interface_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information from the stack state.
|
||||||
|
* Parent information and link qualities with stack state info
|
||||||
|
*
|
||||||
|
* \param interface_id Network interface ID.
|
||||||
|
* \param info_ptr Pointer to stored stack state.
|
||||||
|
*
|
||||||
|
* \return 0 Success.
|
||||||
|
* \return <0 Failure.
|
||||||
|
*/
|
||||||
|
int ws_stack_info_get(
|
||||||
|
int8_t interface_id,
|
||||||
|
ws_stack_info_t *info_ptr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -75,7 +75,6 @@
|
||||||
#include "Service_Libs/etx/etx.h"
|
#include "Service_Libs/etx/etx.h"
|
||||||
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
|
||||||
#include "6LoWPAN/ws/ws_common.h"
|
#include "6LoWPAN/ws/ws_common.h"
|
||||||
#include "6LoWPAN/ws/ws_bootstrap.h"
|
|
||||||
#ifdef HAVE_WS
|
#ifdef HAVE_WS
|
||||||
#include "6LoWPAN/ws/ws_cfg_settings.h"
|
#include "6LoWPAN/ws/ws_cfg_settings.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -517,7 +516,7 @@ uint16_t protocol_6lowpan_neighbor_priority_set(int8_t interface_id, addrtype_t
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_primary) {
|
if (new_primary) {
|
||||||
ws_primary_parent_update(cur, entry);
|
ws_common_primary_parent_update(cur, entry);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -550,7 +549,7 @@ uint16_t protocol_6lowpan_neighbor_second_priority_set(int8_t interface_id, addr
|
||||||
protocol_stats_update(STATS_ETX_2ND_PARENT, etx_entry->etx >> 4);
|
protocol_stats_update(STATS_ETX_2ND_PARENT, etx_entry->etx >> 4);
|
||||||
}
|
}
|
||||||
if (new_secondary) {
|
if (new_secondary) {
|
||||||
ws_secondary_parent_update(cur);
|
ws_common_secondary_parent_update(cur);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
static const uint8_t mac_helper_default_key_source[8] = {0xff, 0, 0, 0, 0, 0, 0, 0};
|
static const uint8_t mac_helper_default_key_source[8] = {0xff, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
uint16_t test_6lowpan_fragmentation_mtu_size_override = 0;
|
||||||
|
|
||||||
static uint8_t mac_helper_header_security_aux_header_length(uint8_t keyIdmode);
|
static uint8_t mac_helper_header_security_aux_header_length(uint8_t keyIdmode);
|
||||||
static uint8_t mac_helper_security_mic_length_get(uint8_t security_level);
|
static uint8_t mac_helper_security_mic_length_get(uint8_t security_level);
|
||||||
static void mac_helper_keytable_pairwise_descriptor_set(struct mac_api_s *api, const uint8_t *key, const uint8_t *mac64, uint8_t attribute_id);
|
static void mac_helper_keytable_pairwise_descriptor_set(struct mac_api_s *api, const uint8_t *key, const uint8_t *mac64, uint8_t attribute_id);
|
||||||
|
@ -736,7 +738,11 @@ uint_fast16_t mac_helper_max_payload_size(protocol_interface_info_entry_t *cur,
|
||||||
{
|
{
|
||||||
uint16_t max;
|
uint16_t max;
|
||||||
|
|
||||||
max = cur->mac_api->phyMTU - frame_overhead;
|
if (test_6lowpan_fragmentation_mtu_size_override == 0) {
|
||||||
|
max = cur->mac_api->phyMTU - frame_overhead;
|
||||||
|
} else {
|
||||||
|
max = test_6lowpan_fragmentation_mtu_size_override - frame_overhead;
|
||||||
|
}
|
||||||
|
|
||||||
/* But if we want IEEE 802.15.4-2003 compatibility (and it looks like a
|
/* But if we want IEEE 802.15.4-2003 compatibility (and it looks like a
|
||||||
* standard PHY), limit ourselves to the 2003 maximum */
|
* standard PHY), limit ourselves to the 2003 maximum */
|
||||||
|
@ -744,6 +750,7 @@ uint_fast16_t mac_helper_max_payload_size(protocol_interface_info_entry_t *cur,
|
||||||
cur->mac_api->phyMTU == MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE) {
|
cur->mac_api->phyMTU == MAC_IEEE_802_15_4_MAX_PHY_PACKET_SIZE) {
|
||||||
max = MAC_IEEE_802_15_4_MAX_MAC_SAFE_PAYLOAD_SIZE;
|
max = MAC_IEEE_802_15_4_MAX_MAC_SAFE_PAYLOAD_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -988,3 +995,23 @@ int8_t mac_helper_mac_device_description_pan_id_update(int8_t interface_id, uint
|
||||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t mac_helper_start_auto_cca_threshold(int8_t interface_id, uint8_t number_of_channels, int8_t default_dbm, int8_t high_limit, int8_t low_limit)
|
||||||
|
{
|
||||||
|
protocol_interface_info_entry_t *cur;
|
||||||
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||||
|
if (!cur || !cur->mac_api) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint8_t start_cca_thr[4] = {number_of_channels, default_dbm, high_limit, low_limit};
|
||||||
|
mlme_set_t set_req;
|
||||||
|
set_req.attr = macCCAThresholdStart;
|
||||||
|
set_req.value_pointer = &start_cca_thr;
|
||||||
|
set_req.value_size = sizeof(start_cca_thr);
|
||||||
|
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);
|
||||||
|
/* Get CCA threshold table. Table is stored to interface structure */
|
||||||
|
mlme_get_t get_req;
|
||||||
|
get_req.attr = macCCAThreshold;
|
||||||
|
cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ struct ns_sockaddr;
|
||||||
struct buffer;
|
struct buffer;
|
||||||
struct mac_api_s;
|
struct mac_api_s;
|
||||||
|
|
||||||
|
extern uint16_t test_6lowpan_fragmentation_mtu_size_override;
|
||||||
|
|
||||||
void mac_create_scan_request(mac_scan_type_t type, struct channel_list_s *chanlist, uint8_t scan_duration, struct mlme_scan_s *request);
|
void mac_create_scan_request(mac_scan_type_t type, struct channel_list_s *chanlist, uint8_t scan_duration, struct mlme_scan_s *request);
|
||||||
|
|
||||||
|
@ -133,4 +134,6 @@ int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_
|
||||||
|
|
||||||
int8_t mac_helper_mac_device_description_pan_id_update(int8_t interface_id, uint16_t pan_id);
|
int8_t mac_helper_mac_device_description_pan_id_update(int8_t interface_id, uint16_t pan_id);
|
||||||
|
|
||||||
|
int8_t mac_helper_start_auto_cca_threshold(int8_t interface_id, uint8_t number_of_channels, int8_t default_dbm, int8_t high_limit, int8_t low_limit);
|
||||||
|
|
||||||
#endif // MAC_HELPER_H
|
#endif // MAC_HELPER_H
|
||||||
|
|
|
@ -81,6 +81,15 @@ static void mac_mlme_frame_counter_confirmation_handle(protocol_interface_info_e
|
||||||
info_entry->mac_parameters->security_frame_counter = *temp_ptr;
|
info_entry->mac_parameters->security_frame_counter = *temp_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mac_mlme_cca_threshold_confirmation_handle(protocol_interface_info_entry_t *info_entry, mlme_get_conf_t *confirmation)
|
||||||
|
{
|
||||||
|
if (confirmation->value_size < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
info_entry->mac_parameters->cca_thr_table.number_of_channels = confirmation->value_size;
|
||||||
|
info_entry->mac_parameters->cca_thr_table.cca_threshold_table = (int8_t *)confirmation->value_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
static void mac_mlme_get_confirmation_handler(protocol_interface_info_entry_t *info_entry, mlme_get_conf_t *confirmation)
|
static void mac_mlme_get_confirmation_handler(protocol_interface_info_entry_t *info_entry, mlme_get_conf_t *confirmation)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -96,6 +105,10 @@ static void mac_mlme_get_confirmation_handler(protocol_interface_info_entry_t *i
|
||||||
mac_mlme_frame_counter_confirmation_handle(info_entry, confirmation);
|
mac_mlme_frame_counter_confirmation_handle(info_entry, confirmation);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case macCCAThreshold:
|
||||||
|
mac_mlme_cca_threshold_confirmation_handle(info_entry, confirmation);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -351,17 +351,14 @@ int8_t lowpan_adaptation_interface_init(int8_t interface_id, uint16_t mac_mtu_si
|
||||||
|
|
||||||
//Allocate new
|
//Allocate new
|
||||||
fragmenter_interface_t *interface_ptr = ns_dyn_mem_alloc(sizeof(fragmenter_interface_t));
|
fragmenter_interface_t *interface_ptr = ns_dyn_mem_alloc(sizeof(fragmenter_interface_t));
|
||||||
uint8_t *tx_buffer = ns_dyn_mem_alloc(mac_mtu_size);
|
if (!interface_ptr) {
|
||||||
if (!interface_ptr || !tx_buffer) {
|
|
||||||
ns_dyn_mem_free(interface_ptr);
|
|
||||||
ns_dyn_mem_free(tx_buffer);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(interface_ptr, 0, sizeof(fragmenter_interface_t));
|
memset(interface_ptr, 0, sizeof(fragmenter_interface_t));
|
||||||
interface_ptr->interface_id = interface_id;
|
interface_ptr->interface_id = interface_id;
|
||||||
interface_ptr->fragment_indirect_tx_buffer = tx_buffer;
|
interface_ptr->fragment_indirect_tx_buffer = NULL;
|
||||||
interface_ptr->mtu_size = mac_mtu_size;
|
interface_ptr->mtu_size = 0;
|
||||||
interface_ptr->msduHandle = randLIB_get_8bit();
|
interface_ptr->msduHandle = randLIB_get_8bit();
|
||||||
interface_ptr->local_frag_tag = randLIB_get_16bit();
|
interface_ptr->local_frag_tag = randLIB_get_16bit();
|
||||||
|
|
||||||
|
@ -938,6 +935,7 @@ static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buf
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interface_ptr->mpx_api) {
|
if (interface_ptr->mpx_api) {
|
||||||
|
dataReq.ExtendedFrameExchange = buf->options.edfe_mode;
|
||||||
interface_ptr->mpx_api->mpx_data_request(interface_ptr->mpx_api, &dataReq, interface_ptr->mpx_user_id);
|
interface_ptr->mpx_api->mpx_data_request(interface_ptr->mpx_api, &dataReq, interface_ptr->mpx_user_id);
|
||||||
} else {
|
} else {
|
||||||
cur->mac_api->mcps_data_req(cur->mac_api, &dataReq);
|
cur->mac_api->mcps_data_req(cur->mac_api, &dataReq);
|
||||||
|
@ -996,6 +994,18 @@ int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buff
|
||||||
|
|
||||||
//Check packet size
|
//Check packet size
|
||||||
bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr);
|
bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr);
|
||||||
|
if (fragmented_needed) {
|
||||||
|
// If fragmentation TX buffer not allocated, do it now.
|
||||||
|
if (!interface_ptr->fragment_indirect_tx_buffer && !interface_ptr->mtu_size) {
|
||||||
|
interface_ptr->fragment_indirect_tx_buffer = ns_dyn_mem_alloc(cur->mac_api->phyMTU);
|
||||||
|
if (interface_ptr->fragment_indirect_tx_buffer) {
|
||||||
|
interface_ptr->mtu_size = cur->mac_api->phyMTU;
|
||||||
|
} else {
|
||||||
|
tr_error("Failed to allocate fragmentation buffer");
|
||||||
|
goto tx_error_handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
bool is_unicast = buf->link_specific.ieee802_15_4.requestAck;
|
bool is_unicast = buf->link_specific.ieee802_15_4.requestAck;
|
||||||
bool indirect = buf->link_specific.ieee802_15_4.indirectTxProcess;
|
bool indirect = buf->link_specific.ieee802_15_4.indirectTxProcess;
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,20 @@ void ws_bbr_dhcp_address_lifetime_set(protocol_interface_info_entry_t *cur, uint
|
||||||
DHCPv6_server_service_set_address_validlifetime(cur->id, current_global_prefix, dhcp_address_lifetime);
|
DHCPv6_server_service_set_address_validlifetime(cur->id, current_global_prefix, dhcp_address_lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ws_bbr_backbone_address_get(uint8_t *address)
|
||||||
|
{
|
||||||
|
if (backbone_interface_id < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arm_net_address_get(backbone_interface_id, ADDR_IPV6_GP, address) != 0) {
|
||||||
|
// No global prefix available
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void ws_bbr_rpl_root_start(protocol_interface_info_entry_t *cur, uint8_t *dodag_id)
|
static void ws_bbr_rpl_root_start(protocol_interface_info_entry_t *cur, uint8_t *dodag_id)
|
||||||
{
|
{
|
||||||
tr_info("RPL root start");
|
tr_info("RPL root start");
|
||||||
|
@ -573,6 +587,9 @@ void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur)
|
||||||
cur->ws_info->pan_information.pan_version++;
|
cur->ws_info->pan_information.pan_version++;
|
||||||
// Inconsistent for border router to make information distribute faster
|
// Inconsistent for border router to make information distribute faster
|
||||||
ws_bootstrap_configuration_trickle_reset(cur);
|
ws_bootstrap_configuration_trickle_reset(cur);
|
||||||
|
|
||||||
|
// Indicate new pan version to PAE controller
|
||||||
|
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->pan_information.pan_version, cur->ws_info->cfg->gen.network_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
|
void ws_bbr_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t seconds)
|
||||||
|
@ -790,6 +807,11 @@ int ws_bbr_info_get(int8_t interface_id, bbr_information_t *info_ptr)
|
||||||
memcpy(info_ptr->IID, wisun_if_addr + 8, 8);
|
memcpy(info_ptr->IID, wisun_if_addr + 8, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipv6_route_t *next_hop = ipv6_route_choose_next_hop(ADDR_6TO4, backbone_interface_id, NULL);
|
||||||
|
if (next_hop) {
|
||||||
|
memcpy(info_ptr->gateway, next_hop->info.next_hop_addr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
info_ptr->devices_in_network = ws_bbr_pan_size(cur);
|
info_ptr->devices_in_network = ws_bbr_pan_size(cur);
|
||||||
info_ptr->instance_id = current_instance_id;
|
info_ptr->instance_id = current_instance_id;
|
||||||
info_ptr->version = dodag_info.version_num;
|
info_ptr->version = dodag_info.version_num;
|
||||||
|
@ -1069,3 +1091,49 @@ int ws_bbr_key_storage_settings_set(int8_t interface_id, uint8_t alloc_max_numbe
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ws_bbr_radius_address_set(int8_t interface_id, const uint8_t *address)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_WS_BORDER_ROUTER
|
||||||
|
return ws_pae_controller_radius_address_set(interface_id, address);
|
||||||
|
#else
|
||||||
|
(void) interface_id;
|
||||||
|
(void) address;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int ws_bbr_radius_address_get(int8_t interface_id, uint8_t *address)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_WS_BORDER_ROUTER
|
||||||
|
return ws_pae_controller_radius_address_get(interface_id, address);
|
||||||
|
#else
|
||||||
|
(void) interface_id;
|
||||||
|
(void) address;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int ws_bbr_radius_shared_secret_set(int8_t interface_id, const uint16_t shared_secret_len, const uint8_t *shared_secret)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_WS_BORDER_ROUTER
|
||||||
|
return ws_pae_controller_radius_shared_secret_set(interface_id, shared_secret_len, shared_secret);
|
||||||
|
#else
|
||||||
|
(void) interface_id;
|
||||||
|
(void) shared_secret_len;
|
||||||
|
(void) shared_secret;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int ws_bbr_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret_len, uint8_t *shared_secret)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_WS_BORDER_ROUTER
|
||||||
|
return ws_pae_controller_radius_shared_secret_get(interface_id, shared_secret_len, shared_secret);
|
||||||
|
#else
|
||||||
|
(void) interface_id;
|
||||||
|
(void) shared_secret_len;
|
||||||
|
(void) shared_secret;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ void ws_bbr_dhcp_address_lifetime_set(protocol_interface_info_entry_t *cur, uint
|
||||||
|
|
||||||
bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur);
|
bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur);
|
||||||
|
|
||||||
|
bool ws_bbr_backbone_address_get(uint8_t *address);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ bool ws_bbr_ready_to_start(protocol_interface_info_entry_t *cur);
|
||||||
#define ws_bbr_rpl_config( cur, imin, doubling, redundancy, dag_max_rank_increase, min_hop_rank_increase)
|
#define ws_bbr_rpl_config( cur, imin, doubling, redundancy, dag_max_rank_increase, min_hop_rank_increase)
|
||||||
#define ws_bbr_dhcp_address_lifetime_set(cur, dhcp_address_lifetime)
|
#define ws_bbr_dhcp_address_lifetime_set(cur, dhcp_address_lifetime)
|
||||||
#define ws_bbr_ready_to_start(cur) true
|
#define ws_bbr_ready_to_start(cur) true
|
||||||
|
#define ws_bbr_backbone_address_get(address) 0
|
||||||
|
|
||||||
#endif //HAVE_WS_BORDER_ROUTER
|
#endif //HAVE_WS_BORDER_ROUTER
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,6 @@
|
||||||
#define TRACE_GROUP "wsbs"
|
#define TRACE_GROUP "wsbs"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ws_bootstrap_event_handler(arm_event_s *event);
|
static void ws_bootstrap_event_handler(arm_event_s *event);
|
||||||
static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state);
|
static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state);
|
||||||
static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur);
|
static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur);
|
||||||
|
@ -95,7 +94,7 @@ static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint
|
||||||
static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index);
|
static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index);
|
||||||
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter, uint8_t slot);
|
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter, uint8_t slot);
|
||||||
static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter, uint8_t slot);
|
static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter, uint8_t slot);
|
||||||
static void ws_bootstrap_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
|
static void ws_bootstrap_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, uint16_t pan_version, char *network_name);
|
||||||
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64);
|
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64);
|
||||||
static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface_info_entry_t *cur, const uint8_t *previous_eui_64, uint16_t *pan_id);
|
static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface_info_entry_t *cur, const uint8_t *previous_eui_64, uint16_t *pan_id);
|
||||||
static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur);
|
static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur);
|
||||||
|
@ -157,7 +156,7 @@ static void ws_bootstap_eapol_neigh_entry_allocate(struct protocol_interface_inf
|
||||||
uint8_t mac_64[8];
|
uint8_t mac_64[8];
|
||||||
memset(mac_64, 0, sizeof(mac_64));
|
memset(mac_64, 0, sizeof(mac_64));
|
||||||
|
|
||||||
mac_neighbor_table_entry_t *mac_entry = ws_bootstrap_mac_neighbor_add(interface, mac_64);
|
mac_neighbor_table_entry_t *mac_entry = ws_bootstrap_mac_neighbor_add(interface, mac_64);
|
||||||
|
|
||||||
if (!mac_entry) {
|
if (!mac_entry) {
|
||||||
return;
|
return;
|
||||||
|
@ -225,21 +224,21 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_
|
||||||
if (addr->source == ADDR_SOURCE_UNKNOWN || !interface->ws_info) {
|
if (addr->source == ADDR_SOURCE_UNKNOWN || !interface->ws_info) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reason == ADDR_CALLBACK_DAD_COMPLETE) {
|
if (reason == ADDR_CALLBACK_DAD_COMPLETE) {
|
||||||
//Trig Address Registartion only when Bootstrap is ready
|
//If address is generated manually we need to force registration
|
||||||
if (addr->source != ADDR_SOURCE_DHCP) {
|
if (addr->source != ADDR_SOURCE_DHCP) {
|
||||||
|
//Trigger Address Registration only when Bootstrap is ready
|
||||||
if (interface->nwk_bootstrap_state == ER_BOOTSRAP_DONE) {
|
if (interface->nwk_bootstrap_state == ER_BOOTSRAP_DONE) {
|
||||||
tr_debug("Address registration %s", trace_ipv6(addr->address));
|
tr_debug("Address registration %s", trace_ipv6(addr->address));
|
||||||
ws_address_registration_update(interface, addr->address);
|
ws_address_registration_update(interface, addr->address);
|
||||||
}
|
}
|
||||||
ws_address_reregister_trig(interface);
|
ws_address_reregister_trig(interface);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (addr_ipv6_scope(addr->address, interface) > IPV6_SCOPE_LINK_LOCAL) {
|
if (addr_ipv6_scope(addr->address, interface) > IPV6_SCOPE_LINK_LOCAL) {
|
||||||
// at least ula address available inside mesh.
|
// at least ula address available inside mesh.
|
||||||
interface->global_address_available = true;
|
interface->global_address_available = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (reason == ADDR_CALLBACK_DELETED) {
|
} else if (reason == ADDR_CALLBACK_DELETED) {
|
||||||
// What to do?
|
// What to do?
|
||||||
// Go through address list and check if there is global address still available
|
// Go through address list and check if there is global address still available
|
||||||
|
@ -261,6 +260,14 @@ static void ws_bootstrap_address_notification_cb(struct protocol_interface_info_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Addressing in Wi-SUN interface was changed for Border router send new event so Application can update the state
|
||||||
|
if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER &&
|
||||||
|
interface->nwk_bootstrap_state == ER_BOOTSRAP_DONE) {
|
||||||
|
if (interface->bootsrap_state_machine_cnt == 0) {
|
||||||
|
interface->bootsrap_state_machine_cnt = 10; //Re trigger state check
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ws_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur)
|
static int ws_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur)
|
||||||
|
@ -486,7 +493,7 @@ static void ws_bootstrap_llc_hopping_update(struct protocol_interface_info_entry
|
||||||
cur->ws_info->hopping_schdule.fhss_bsi = fhss_configuration->bsi;
|
cur->ws_info->hopping_schdule.fhss_bsi = fhss_configuration->bsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t ws_generate_exluded_channel_list_from_active_channels(ws_excluded_channel_data_t *excluded_data, const uint32_t *selected_channel_mask, uint16_t number_of_channels)
|
static uint8_t ws_generate_exluded_channel_list_from_active_channels(ws_excluded_channel_data_t *excluded_data, const uint32_t *selected_channel_mask, const uint32_t *global_channel_mask, uint16_t number_of_channels)
|
||||||
{
|
{
|
||||||
bool active_range = false;
|
bool active_range = false;
|
||||||
|
|
||||||
|
@ -494,6 +501,15 @@ static uint8_t ws_generate_exluded_channel_list_from_active_channels(ws_excluded
|
||||||
memset(excluded_data, 0, sizeof(ws_excluded_channel_data_t));
|
memset(excluded_data, 0, sizeof(ws_excluded_channel_data_t));
|
||||||
|
|
||||||
for (uint8_t i = 0; i < number_of_channels; i++) {
|
for (uint8_t i = 0; i < number_of_channels; i++) {
|
||||||
|
if (!(global_channel_mask[0 + (i / 32)] & (1 << (i % 32)))) {
|
||||||
|
//Global exluded channel
|
||||||
|
if (active_range) {
|
||||||
|
//Mark range stop here
|
||||||
|
active_range = false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (selected_channel_mask[0 + (i / 32)] & (1 << (i % 32))) {
|
if (selected_channel_mask[0 + (i / 32)] & (1 << (i % 32))) {
|
||||||
if (active_range) {
|
if (active_range) {
|
||||||
//Mark range stop here
|
//Mark range stop here
|
||||||
|
@ -549,7 +565,7 @@ static void ws_fhss_configure_channel_masks(protocol_interface_info_entry_t *cur
|
||||||
fhss_configuration->unicast_channel_mask[n] &= cur->ws_info->cfg->fhss.fhss_channel_mask[n];
|
fhss_configuration->unicast_channel_mask[n] &= cur->ws_info->cfg->fhss.fhss_channel_mask[n];
|
||||||
}
|
}
|
||||||
//Update Exluded channels
|
//Update Exluded channels
|
||||||
cur->ws_info->hopping_schdule.channel_plan = ws_generate_exluded_channel_list_from_active_channels(&cur->ws_info->hopping_schdule.excluded_channels, fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels);
|
cur->ws_info->hopping_schdule.channel_plan = ws_generate_exluded_channel_list_from_active_channels(&cur->ws_info->hopping_schdule.excluded_channels, fhss_configuration->unicast_channel_mask, fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur)
|
static int8_t ws_fhss_initialize(protocol_interface_info_entry_t *cur)
|
||||||
|
@ -1424,7 +1440,7 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry
|
||||||
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64);
|
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64);
|
||||||
//Update Neighbor Broadcast and Unicast Parameters
|
//Update Neighbor Broadcast and Unicast Parameters
|
||||||
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
|
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
|
||||||
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us);
|
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule);
|
||||||
ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt_ie, data->timestamp);
|
ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt_ie, data->timestamp);
|
||||||
ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie);
|
ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie);
|
||||||
}
|
}
|
||||||
|
@ -1508,7 +1524,7 @@ static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_in
|
||||||
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
|
if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) {
|
||||||
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64);
|
etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64);
|
||||||
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
|
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp);
|
||||||
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us);
|
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1564,6 +1580,26 @@ bool ws_bootstrap_validate_channel_plan(ws_us_ie_t *ws_us, struct protocol_inter
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ws_bootstrap_validate_channel_function(ws_us_ie_t *ws_us, ws_bs_ie_t *ws_bs)
|
||||||
|
{
|
||||||
|
if (ws_us) {
|
||||||
|
if (ws_us->channel_function != WS_FIXED_CHANNEL &&
|
||||||
|
ws_us->channel_function != WS_TR51CF &&
|
||||||
|
ws_us->channel_function != WS_DH1CF) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ws_bs) {
|
||||||
|
if (ws_bs->channel_function != WS_FIXED_CHANNEL &&
|
||||||
|
ws_bs->channel_function != WS_TR51CF &&
|
||||||
|
ws_bs->channel_function != WS_DH1CF) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, uint8_t message_type)
|
static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, uint8_t message_type)
|
||||||
{
|
{
|
||||||
|
@ -1602,7 +1638,8 @@ static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, c
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ws_bootstrap_validate_channel_plan(&ws_us, cur)) {
|
if (!ws_bootstrap_validate_channel_plan(&ws_us, cur) ||
|
||||||
|
!ws_bootstrap_validate_channel_function(&ws_us, NULL)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2098,11 +2135,7 @@ int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_rf_chan
|
||||||
set_request.value_size = sizeof(mlme_multi_csma_ca_param_t);
|
set_request.value_size = sizeof(mlme_multi_csma_ca_param_t);
|
||||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request);
|
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request);
|
||||||
// Start automatic CCA threshold
|
// Start automatic CCA threshold
|
||||||
uint8_t start_cca_thr[4] = {cur->ws_info->hopping_schdule.number_of_channels, CCA_DEFAULT_DBM, CCA_HIGH_LIMIT, CCA_LOW_LIMIT};
|
mac_helper_start_auto_cca_threshold(cur->id, cur->ws_info->hopping_schdule.number_of_channels, CCA_DEFAULT_DBM, CCA_HIGH_LIMIT, CCA_LOW_LIMIT);
|
||||||
set_request.attr = macCCAThresholdStart;
|
|
||||||
set_request.value_pointer = &start_cca_thr;
|
|
||||||
set_request.value_size = sizeof(start_cca_thr);
|
|
||||||
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2275,7 +2308,7 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle)
|
||||||
// Set both own port and border router port to 10253
|
// Set both own port and border router port to 10253
|
||||||
ws_eapol_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, dodag_info.dodag_id, EAPOL_RELAY_SOCKET_PORT);
|
ws_eapol_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, dodag_info.dodag_id, EAPOL_RELAY_SOCKET_PORT);
|
||||||
// Set network information to PAE
|
// Set network information to PAE
|
||||||
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->cfg->gen.network_name);
|
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->pan_information.pan_version, cur->ws_info->cfg->gen.network_name);
|
||||||
// Network key is valid, indicate border router IID to controller
|
// Network key is valid, indicate border router IID to controller
|
||||||
ws_pae_controller_nw_key_valid(cur, &dodag_info.dodag_id[8]);
|
ws_pae_controller_nw_key_valid(cur, &dodag_info.dodag_id[8]);
|
||||||
|
|
||||||
|
@ -2635,7 +2668,7 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
|
||||||
static void ws_bootstrap_start_authentication(protocol_interface_info_entry_t *cur)
|
static void ws_bootstrap_start_authentication(protocol_interface_info_entry_t *cur)
|
||||||
{
|
{
|
||||||
// Set PAN ID and network name to controller
|
// Set PAN ID and network name to controller
|
||||||
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->cfg->gen.network_name);
|
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->pan_information.pan_version, cur->ws_info->cfg->gen.network_name);
|
||||||
|
|
||||||
ws_pae_controller_authenticate(cur);
|
ws_pae_controller_authenticate(cur);
|
||||||
}
|
}
|
||||||
|
@ -2683,22 +2716,26 @@ static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *
|
||||||
mac_helper_key_link_frame_counter_read(cur->id, counter, slot);
|
mac_helper_key_link_frame_counter_read(cur->id, counter, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ws_bootstrap_nw_info_updated(protocol_interface_info_entry_t *cur, uint16_t pan_id, char *network_name)
|
static void ws_bootstrap_nw_info_updated(protocol_interface_info_entry_t *cur, uint16_t pan_id, uint16_t pan_version, char *network_name)
|
||||||
{
|
{
|
||||||
/* For border router, the PAE controller reads pan_id and network name from storage.
|
/* For border router, the PAE controller reads PAN ID, PAN version and network name from storage.
|
||||||
* If they are set, takes them into use here.
|
* If they are set, takes them into use here.
|
||||||
*/
|
*/
|
||||||
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) {
|
||||||
// Get pad_id and network name
|
// Get PAN ID and network name
|
||||||
ws_gen_cfg_t gen_cfg;
|
ws_gen_cfg_t gen_cfg;
|
||||||
if (ws_cfg_gen_get(&gen_cfg, NULL) < 0) {
|
if (ws_cfg_gen_get(&gen_cfg, NULL) < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If pan_id has not been set, set it
|
// If PAN ID has not been set, set it
|
||||||
if (gen_cfg.network_pan_id == 0xffff) {
|
if (gen_cfg.network_pan_id == 0xffff) {
|
||||||
gen_cfg.network_pan_id = pan_id;
|
gen_cfg.network_pan_id = pan_id;
|
||||||
|
// Sets PAN version
|
||||||
|
cur->ws_info->pan_information.pan_version = pan_version;
|
||||||
|
cur->ws_info->pan_information.pan_version_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If network name has not been set, set it
|
// If network name has not been set, set it
|
||||||
if (strlen(gen_cfg.network_name) == 0) {
|
if (strlen(gen_cfg.network_name) == 0) {
|
||||||
strncpy(gen_cfg.network_name, network_name, 32);
|
strncpy(gen_cfg.network_name, network_name, 32);
|
||||||
|
@ -2989,6 +3026,18 @@ static void ws_bootstrap_pan_config(protocol_interface_info_entry_t *cur)
|
||||||
ws_llc_asynch_request(cur, &async_req);
|
ws_llc_asynch_request(cur, &async_req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int8_t ws_bootstrap_backbone_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address)
|
||||||
|
{
|
||||||
|
(void) interface_ptr;
|
||||||
|
(void) address;
|
||||||
|
|
||||||
|
if (ws_bbr_backbone_address_get(address)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void ws_bootstrap_event_handler(arm_event_s *event)
|
static void ws_bootstrap_event_handler(arm_event_s *event)
|
||||||
{
|
{
|
||||||
ws_bootsrap_event_type_e event_type;
|
ws_bootsrap_event_type_e event_type;
|
||||||
|
@ -3045,8 +3094,11 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
|
||||||
} else {
|
} else {
|
||||||
cur->ws_info->network_pan_id = cur->ws_info->cfg->gen.network_pan_id;
|
cur->ws_info->network_pan_id = cur->ws_info->cfg->gen.network_pan_id;
|
||||||
}
|
}
|
||||||
|
if (!cur->ws_info->pan_information.pan_version_set) {
|
||||||
|
cur->ws_info->pan_information.pan_version = randLIB_get_random_in_range(0, 0xffff);
|
||||||
|
cur->ws_info->pan_information.pan_version_set = true;
|
||||||
|
}
|
||||||
cur->ws_info->pan_information.pan_size = 0;
|
cur->ws_info->pan_information.pan_size = 0;
|
||||||
cur->ws_info->pan_information.pan_version = randLIB_get_random_in_range(0, 0xffff);
|
|
||||||
cur->ws_info->pan_information.routing_cost = 0;
|
cur->ws_info->pan_information.routing_cost = 0;
|
||||||
cur->ws_info->pan_information.rpl_routing_method = true;
|
cur->ws_info->pan_information.rpl_routing_method = true;
|
||||||
cur->ws_info->pan_information.use_parent_bs = true;
|
cur->ws_info->pan_information.use_parent_bs = true;
|
||||||
|
@ -3075,7 +3127,10 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
|
||||||
ws_eapol_auth_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, ll_addr, PAE_AUTH_SOCKET_PORT);
|
ws_eapol_auth_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, ll_addr, PAE_AUTH_SOCKET_PORT);
|
||||||
|
|
||||||
// Set PAN ID and network name to controller
|
// Set PAN ID and network name to controller
|
||||||
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->cfg->gen.network_name);
|
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->pan_information.pan_version, cur->ws_info->cfg->gen.network_name);
|
||||||
|
|
||||||
|
// Set backbone IP address get callback
|
||||||
|
ws_pae_controller_auth_cb_register(cur, ws_bootstrap_backbone_ip_addr_get);
|
||||||
|
|
||||||
// Set PAE port to 10254 and authenticator relay to 10253 (and to own ll address)
|
// Set PAE port to 10254 and authenticator relay to 10253 (and to own ll address)
|
||||||
ws_pae_controller_authenticator_start(cur, PAE_AUTH_SOCKET_PORT, ll_addr, EAPOL_RELAY_SOCKET_PORT);
|
ws_pae_controller_authenticator_start(cur, PAE_AUTH_SOCKET_PORT, ll_addr, EAPOL_RELAY_SOCKET_PORT);
|
||||||
|
@ -3173,7 +3228,7 @@ static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, pa
|
||||||
}
|
}
|
||||||
|
|
||||||
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &parent_ptr->ws_utt, parent_ptr->timestamp);
|
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &parent_ptr->ws_utt, parent_ptr->timestamp);
|
||||||
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &parent_ptr->ws_us);
|
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &parent_ptr->ws_us, &cur->ws_info->hopping_schdule);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3222,11 +3277,7 @@ void ws_bootstrap_configure_process(protocol_interface_info_entry_t *cur)
|
||||||
|
|
||||||
if (cur->ws_info->configuration_learned) {
|
if (cur->ws_info->configuration_learned) {
|
||||||
ws_bootstrap_network_configuration_learn(cur);
|
ws_bootstrap_network_configuration_learn(cur);
|
||||||
|
|
||||||
|
|
||||||
ws_bootstrap_event_operation_start(cur);
|
ws_bootstrap_event_operation_start(cur);
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -3249,7 +3300,22 @@ void ws_bootstrap_rpl_wait_process(protocol_interface_info_entry_t *cur)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur)
|
||||||
|
{
|
||||||
|
if (cur->nwk_bootstrap_state == ER_ACTIVE_SCAN) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ws_bootstrap_state_authenticate(struct protocol_interface_info_entry *cur)
|
||||||
|
{
|
||||||
|
// Think about the state value
|
||||||
|
if (cur->nwk_bootstrap_state == ER_PANA_AUTH) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool ws_bootstrap_state_configure(struct protocol_interface_info_entry *cur)
|
static bool ws_bootstrap_state_configure(struct protocol_interface_info_entry *cur)
|
||||||
{
|
{
|
||||||
|
@ -3260,10 +3326,10 @@ static bool ws_bootstrap_state_configure(struct protocol_interface_info_entry *c
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
static bool ws_bootstrap_state_wait_rpl(struct protocol_interface_info_entry *cur)
|
||||||
static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur)
|
|
||||||
{
|
{
|
||||||
if (cur->nwk_bootstrap_state == ER_ACTIVE_SCAN) {
|
// Think about the state value
|
||||||
|
if (cur->nwk_bootstrap_state == ER_RPL_SCAN) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -3276,14 +3342,6 @@ static bool ws_bootstrap_state_active(struct protocol_interface_info_entry *cur)
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool ws_bootstrap_state_wait_rpl(struct protocol_interface_info_entry *cur)
|
|
||||||
{
|
|
||||||
// Think about the state value
|
|
||||||
if (cur->nwk_bootstrap_state == ER_RPL_SCAN) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state)
|
static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp_state_t nwk_bootstrap_state)
|
||||||
{
|
{
|
||||||
|
@ -3431,7 +3489,7 @@ void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t s
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor)
|
void ws_bootstrap_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor)
|
||||||
{
|
{
|
||||||
if (interface->ws_info) {
|
if (interface->ws_info) {
|
||||||
llc_neighbour_req_t neighbor_info;
|
llc_neighbour_req_t neighbor_info;
|
||||||
|
@ -3442,11 +3500,11 @@ void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_ne
|
||||||
ws_bootsrap_create_ll_address(link_local_address, neighbor->mac64);
|
ws_bootsrap_create_ll_address(link_local_address, neighbor->mac64);
|
||||||
dhcp_client_server_address_update(interface->id, NULL, link_local_address);
|
dhcp_client_server_address_update(interface->id, NULL, link_local_address);
|
||||||
|
|
||||||
ws_secondary_parent_update(interface);
|
ws_bootstrap_secondary_parent_update(interface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_secondary_parent_update(protocol_interface_info_entry_t *interface)
|
void ws_bootstrap_secondary_parent_update(protocol_interface_info_entry_t *interface)
|
||||||
{
|
{
|
||||||
if (interface->ws_info) {
|
if (interface->ws_info) {
|
||||||
ns_list_foreach(if_address_entry_t, address, &interface->ip_addresses) {
|
ns_list_foreach(if_address_entry_t, address, &interface->ip_addresses) {
|
||||||
|
@ -3457,4 +3515,40 @@ void ws_secondary_parent_update(protocol_interface_info_entry_t *interface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_info *info_ptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
ws_neighbor_class_entry_t *ws_neighbour = NULL;
|
||||||
|
|
||||||
|
memset(info_ptr, 0, sizeof(struct ws_stack_info));
|
||||||
|
mac_neighbor_table_entry_t *mac_parent = mac_neighbor_entry_get_priority(mac_neighbor_info(cur));
|
||||||
|
|
||||||
|
if (mac_parent) {
|
||||||
|
ws_neighbour = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, mac_parent->index);
|
||||||
|
|
||||||
|
memcpy(info_ptr->parent, ADDR_LINK_LOCAL_PREFIX, 8);
|
||||||
|
memcpy(info_ptr->parent + 8, mac_parent->mac64, 8);
|
||||||
|
info_ptr->parent[8] ^= 2;
|
||||||
|
}
|
||||||
|
if (ws_neighbour) {
|
||||||
|
info_ptr->rsl_in = ws_neighbour->rsl_in;
|
||||||
|
info_ptr->rsl_out = ws_neighbour->rsl_out;
|
||||||
|
info_ptr->routing_cost = ws_neighbour->routing_cost;
|
||||||
|
}
|
||||||
|
if (ws_bootstrap_state_discovery(cur)) {
|
||||||
|
info_ptr->join_state = 1;
|
||||||
|
} else if (ws_bootstrap_state_authenticate(cur)) {
|
||||||
|
info_ptr->join_state = 2;
|
||||||
|
} else if (ws_bootstrap_state_configure(cur)) {
|
||||||
|
info_ptr->join_state = 3;
|
||||||
|
} else if (ws_bootstrap_state_wait_rpl(cur)) {
|
||||||
|
info_ptr->join_state = 4;
|
||||||
|
} else if (ws_bootstrap_state_active(cur)) {
|
||||||
|
info_ptr->join_state = 5;
|
||||||
|
}
|
||||||
|
info_ptr->pan_id = cur->ws_info->network_pan_id;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif //HAVE_WS
|
#endif //HAVE_WS
|
||||||
|
|
|
@ -31,7 +31,9 @@ typedef enum {
|
||||||
|
|
||||||
struct llc_neighbour_req;
|
struct llc_neighbour_req;
|
||||||
struct ws_us_ie;
|
struct ws_us_ie;
|
||||||
|
struct ws_bs_ie;
|
||||||
struct ws_neighbor_class_entry;
|
struct ws_neighbor_class_entry;
|
||||||
|
struct ws_stack_info;
|
||||||
|
|
||||||
int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode);
|
int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode);
|
||||||
|
|
||||||
|
@ -64,9 +66,9 @@ void ws_bootstrap_seconds_timer(protocol_interface_info_entry_t *cur, uint32_t s
|
||||||
|
|
||||||
void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks);
|
void ws_bootstrap_trickle_timer(protocol_interface_info_entry_t *cur, uint16_t ticks);
|
||||||
|
|
||||||
void ws_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor);
|
void ws_bootstrap_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor);
|
||||||
|
|
||||||
void ws_secondary_parent_update(protocol_interface_info_entry_t *interface);
|
void ws_bootstrap_secondary_parent_update(protocol_interface_info_entry_t *interface);
|
||||||
|
|
||||||
void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor);
|
void ws_nud_entry_remove_active(protocol_interface_info_entry_t *cur, void *neighbor);
|
||||||
|
|
||||||
|
@ -82,12 +84,16 @@ void ws_bootstrap_eapol_parent_synch(struct protocol_interface_info_entry *cur,
|
||||||
|
|
||||||
bool ws_bootstrap_validate_channel_plan(struct ws_us_ie *ws_us, struct protocol_interface_info_entry *cur);
|
bool ws_bootstrap_validate_channel_plan(struct ws_us_ie *ws_us, struct protocol_interface_info_entry *cur);
|
||||||
|
|
||||||
|
bool ws_bootstrap_validate_channel_function(struct ws_us_ie *ws_us, struct ws_bs_ie *ws_bs);
|
||||||
|
|
||||||
void ws_bootstrap_eapol_rx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64);
|
void ws_bootstrap_eapol_rx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64);
|
||||||
|
|
||||||
struct ws_neighbor_class_entry *ws_bootstrap_eapol_tx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64);
|
struct ws_neighbor_class_entry *ws_bootstrap_eapol_tx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64);
|
||||||
|
|
||||||
void ws_bootstrap_eapol_tx_temporary_clear(struct protocol_interface_info_entry *interface);
|
void ws_bootstrap_eapol_tx_temporary_clear(struct protocol_interface_info_entry *interface);
|
||||||
|
|
||||||
|
int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_info *info_ptr);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)
|
#define ws_bootstrap_init(interface_id, bootstrap_mode) (-1)
|
||||||
|
@ -95,8 +101,9 @@ void ws_bootstrap_eapol_tx_temporary_clear(struct protocol_interface_info_entry
|
||||||
#define ws_bootstrap_restart(cur)
|
#define ws_bootstrap_restart(cur)
|
||||||
#define ws_bootstrap_neighbor_remove(cur, ll_address)
|
#define ws_bootstrap_neighbor_remove(cur, ll_address)
|
||||||
#define ws_bootstrap_aro_failure(cur, ll_address)
|
#define ws_bootstrap_aro_failure(cur, ll_address)
|
||||||
#define ws_primary_parent_update(interface, neighbor)
|
#define ws_bootstrap_primary_parent_update(interface, neighbor)
|
||||||
#define ws_secondary_parent_update(interface)
|
#define ws_bootstrap_secondary_parent_update(interface)
|
||||||
|
#define ws_bootstrap_get_info(cur, info_ptr)
|
||||||
|
|
||||||
#endif //HAVE_WS
|
#endif //HAVE_WS
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,12 @@
|
||||||
#include <ns_list.h>
|
#include <ns_list.h>
|
||||||
#include <nsdynmemLIB.h>
|
#include <nsdynmemLIB.h>
|
||||||
#include "Common_Protocols/icmpv6.h"
|
#include "Common_Protocols/icmpv6.h"
|
||||||
|
#include "mac_common_defines.h"
|
||||||
|
#include "net_interface.h"
|
||||||
|
#include "6LoWPAN/MAC/mpx_api.h"
|
||||||
#include "6LoWPAN/ws/ws_config.h"
|
#include "6LoWPAN/ws/ws_config.h"
|
||||||
#include "6LoWPAN/ws/ws_common_defines.h"
|
#include "6LoWPAN/ws/ws_common_defines.h"
|
||||||
|
#include "6LoWPAN/ws/ws_llc.h"
|
||||||
#include "6LoWPAN/ws/ws_common.h"
|
#include "6LoWPAN/ws/ws_common.h"
|
||||||
#include "6LoWPAN/ws/ws_bootstrap.h"
|
#include "6LoWPAN/ws/ws_bootstrap.h"
|
||||||
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
|
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
|
||||||
|
@ -81,6 +85,18 @@ int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_chann
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t ws_active_channel_count(uint32_t *channel_mask, uint16_t number_of_channels)
|
||||||
|
{
|
||||||
|
uint16_t active_channels = 0;
|
||||||
|
// Set channel maks outside excluded channels
|
||||||
|
for (uint16_t i = 0; i < number_of_channels; i++) {
|
||||||
|
if (channel_mask[0 + (i / 32)] & (1 << (i % 32))) {
|
||||||
|
active_channels++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return active_channels;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t ws_decode_channel_spacing(uint8_t channel_spacing)
|
uint32_t ws_decode_channel_spacing(uint8_t channel_spacing)
|
||||||
{
|
{
|
||||||
if (CHANNEL_SPACING_100 == channel_spacing) {
|
if (CHANNEL_SPACING_100 == channel_spacing) {
|
||||||
|
@ -307,6 +323,7 @@ int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur)
|
||||||
cur->ws_info->network_pan_id = 0xffff;
|
cur->ws_info->network_pan_id = 0xffff;
|
||||||
cur->ws_info->pan_information.use_parent_bs = true;
|
cur->ws_info->pan_information.use_parent_bs = true;
|
||||||
cur->ws_info->pan_information.rpl_routing_method = true;
|
cur->ws_info->pan_information.rpl_routing_method = true;
|
||||||
|
cur->ws_info->pan_information.pan_version_set = false;
|
||||||
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0;
|
cur->ws_info->pan_information.version = WS_FAN_VERSION_1_0;
|
||||||
|
|
||||||
cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS;
|
cur->ws_info->pending_key_index_info.state = NO_PENDING_PROCESS;
|
||||||
|
@ -336,6 +353,7 @@ void ws_common_fast_timer(protocol_interface_info_entry_t *cur, uint16_t ticks)
|
||||||
{
|
{
|
||||||
ws_bootstrap_trickle_timer(cur, ticks);
|
ws_bootstrap_trickle_timer(cur, ticks);
|
||||||
ws_nud_active_timer(cur, ticks);
|
ws_nud_active_timer(cur, ticks);
|
||||||
|
ws_llc_fast_timer(cur, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -461,4 +479,14 @@ uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cu
|
||||||
return network_size_estimate;
|
return network_size_estimate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ws_common_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor)
|
||||||
|
{
|
||||||
|
ws_bootstrap_primary_parent_update(interface, neighbor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ws_common_secondary_parent_update(protocol_interface_info_entry_t *interface)
|
||||||
|
{
|
||||||
|
ws_bootstrap_secondary_parent_update(interface);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAVE_WS
|
#endif // HAVE_WS
|
||||||
|
|
|
@ -115,6 +115,8 @@ typedef struct ws_info_s {
|
||||||
|
|
||||||
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class);
|
int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class);
|
||||||
|
|
||||||
|
uint16_t ws_active_channel_count(uint32_t *channel_mask, uint16_t number_of_channels);
|
||||||
|
|
||||||
uint32_t ws_decode_channel_spacing(uint8_t channel_spacing);
|
uint32_t ws_decode_channel_spacing(uint8_t channel_spacing);
|
||||||
|
|
||||||
uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode);
|
uint32_t ws_get_datarate_using_operating_mode(uint8_t operating_mode);
|
||||||
|
@ -149,6 +151,10 @@ uint32_t ws_common_datarate_get(protocol_interface_info_entry_t *cur);
|
||||||
|
|
||||||
uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cur);
|
uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cur);
|
||||||
|
|
||||||
|
void ws_common_primary_parent_update(protocol_interface_info_entry_t *interface, mac_neighbor_table_entry_t *neighbor);
|
||||||
|
|
||||||
|
void ws_common_secondary_parent_update(protocol_interface_info_entry_t *interface);
|
||||||
|
|
||||||
#define ws_info(cur) ((cur)->ws_info)
|
#define ws_info(cur) ((cur)->ws_info)
|
||||||
#else
|
#else
|
||||||
#define ws_info(cur) ((ws_info_t *) NULL)
|
#define ws_info(cur) ((ws_info_t *) NULL)
|
||||||
|
@ -162,6 +168,9 @@ uint32_t ws_common_network_size_estimate_get(protocol_interface_info_entry_t *cu
|
||||||
#define ws_common_latency_estimate_get(cur) 0
|
#define ws_common_latency_estimate_get(cur) 0
|
||||||
#define ws_common_datarate_get(cur) 0
|
#define ws_common_datarate_get(cur) 0
|
||||||
#define ws_common_network_size_estimate_get(cur) 0
|
#define ws_common_network_size_estimate_get(cur) 0
|
||||||
|
#define ws_common_primary_parent_update(interface, neighbor)
|
||||||
|
#define ws_common_secondary_parent_update(interface)
|
||||||
|
|
||||||
|
|
||||||
#endif //HAVE_WS
|
#endif //HAVE_WS
|
||||||
#endif //WS_COMMON_H_
|
#endif //WS_COMMON_H_
|
||||||
|
|
|
@ -67,6 +67,7 @@ typedef struct ws_pan_information_s {
|
||||||
uint16_t pan_version; /**< Pan configuration version will be updatd by Border router at PAN. */
|
uint16_t pan_version; /**< Pan configuration version will be updatd by Border router at PAN. */
|
||||||
bool use_parent_bs: 1; /**< 1 for force to follow parent broadcast schedule. 0 node may define own schedule. */
|
bool use_parent_bs: 1; /**< 1 for force to follow parent broadcast schedule. 0 node may define own schedule. */
|
||||||
bool rpl_routing_method: 1; /**< 1 when RPL routing is selected and 0 when L2 routing. */
|
bool rpl_routing_method: 1; /**< 1 when RPL routing is selected and 0 when L2 routing. */
|
||||||
|
bool pan_version_set: 1; /**< 1 PAN version is set. */
|
||||||
unsigned version: 3; /**< Pan version support. */
|
unsigned version: 3; /**< Pan version support. */
|
||||||
} ws_pan_information_t;
|
} ws_pan_information_t;
|
||||||
|
|
||||||
|
@ -130,6 +131,13 @@ typedef struct ws_bt_ie {
|
||||||
uint_fast24_t broadcast_interval_offset;
|
uint_fast24_t broadcast_interval_offset;
|
||||||
} ws_bt_ie_t;
|
} ws_bt_ie_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ws_fc_ie_t WS FC-IE element
|
||||||
|
*/
|
||||||
|
typedef struct ws_fc_ie {
|
||||||
|
uint8_t tx_flow_ctrl;
|
||||||
|
uint8_t rx_flow_ctrl;
|
||||||
|
} ws_fc_ie_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ws_channel_plan_zero_t WS channel plan 0 define domain and class
|
* @brief ws_channel_plan_zero_t WS channel plan 0 define domain and class
|
||||||
|
|
|
@ -69,6 +69,10 @@
|
||||||
|
|
||||||
#define PAN_VERSION_CHANGE_INTERVAL 3
|
#define PAN_VERSION_CHANGE_INTERVAL 3
|
||||||
|
|
||||||
|
/* If PAN version lifetime would be 10 minutes, 1000 increments is about 7 days i.e. storage must
|
||||||
|
be written at least once a week */
|
||||||
|
#define PAN_VERSION_STORAGE_READ_INCREMENT 1000
|
||||||
|
|
||||||
// RPL version number update intervall
|
// RPL version number update intervall
|
||||||
// after restart version numbers are increased faster and then slowed down when network is stable
|
// after restart version numbers are increased faster and then slowed down when network is stable
|
||||||
#define RPL_VERSION_LIFETIME 12*3600
|
#define RPL_VERSION_LIFETIME 12*3600
|
||||||
|
|
|
@ -380,6 +380,14 @@ int ws_test_next_gtk_set(int8_t interface_id, uint8_t *gtk[4])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ws_test_6lowpan_fragmentation_mtu_size_set(int8_t interface_id, uint16_t mtu_size)
|
||||||
|
{
|
||||||
|
(void) interface_id;
|
||||||
|
(void) mtu_size;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int ws_statistics_start(int8_t interface_id, ws_statistics_t *stats_ptr)
|
int ws_statistics_start(int8_t interface_id, ws_statistics_t *stats_ptr)
|
||||||
{
|
{
|
||||||
(void) interface_id;
|
(void) interface_id;
|
||||||
|
@ -398,4 +406,11 @@ void ns_time_api_system_time_callback_set(ns_time_api_system_time_callback callb
|
||||||
(void) callback;
|
(void) callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ws_stack_info_get(int8_t interface_id, ws_stack_info_t *info_ptr)
|
||||||
|
{
|
||||||
|
(void) interface_id;
|
||||||
|
(void) info_ptr;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // no HAVE_WS
|
#endif // no HAVE_WS
|
||||||
|
|
|
@ -110,10 +110,11 @@ 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_fc_write(uint8_t *ptr, ws_fc_ie_t *fc_ie)
|
||||||
{
|
{
|
||||||
ptr = ws_wh_header_base_write(ptr, 1, WH_IE_FC_TYPE);
|
ptr = ws_wh_header_base_write(ptr, 2, WH_IE_FC_TYPE);
|
||||||
*ptr++ = flow_ctrl;
|
*ptr++ = fc_ie->tx_flow_ctrl;
|
||||||
|
*ptr++ = fc_ie->rx_flow_ctrl;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,6 +342,19 @@ bool ws_wh_bt_read(uint8_t *data, uint16_t length, struct ws_bt_ie *bt_ie)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ws_wh_fc_read(uint8_t *data, uint16_t length, struct ws_fc_ie *fc_ie)
|
||||||
|
{
|
||||||
|
mac_header_IE_t fc_ie_data;
|
||||||
|
fc_ie_data.id = MAC_HEADER_ASSIGNED_EXTERNAL_ORG_IE_ID;
|
||||||
|
if (2 != mac_ie_header_sub_id_discover(data, length, &fc_ie_data, WH_IE_FC_TYPE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data = fc_ie_data.content_ptr;
|
||||||
|
fc_ie->tx_flow_ctrl = *data++;
|
||||||
|
fc_ie->rx_flow_ctrl = *data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ws_wh_rsl_read(uint8_t *data, uint16_t length, int8_t *rsl)
|
bool ws_wh_rsl_read(uint8_t *data, uint16_t length, int8_t *rsl)
|
||||||
{
|
{
|
||||||
mac_header_IE_t rsl_ie_data;
|
mac_header_IE_t rsl_ie_data;
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct ws_utt_ie;
|
||||||
struct ws_bt_ie;
|
struct ws_bt_ie;
|
||||||
struct ws_us_ie;
|
struct ws_us_ie;
|
||||||
struct ws_hopping_schedule_s;
|
struct ws_hopping_schedule_s;
|
||||||
|
struct ws_fc_ie;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ws_wp_network_name_t WS nested payload network name
|
* @brief ws_wp_network_name_t WS nested payload network name
|
||||||
|
@ -35,13 +36,14 @@ typedef struct ws_wp_network_name {
|
||||||
/* WS_WH HEADER IE */
|
/* WS_WH HEADER IE */
|
||||||
uint8_t *ws_wh_utt_write(uint8_t *ptr, uint8_t message_type);
|
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_bt_write(uint8_t *ptr);
|
||||||
uint8_t *ws_wh_fc_write(uint8_t *ptr, uint8_t flow_ctrl);
|
uint8_t *ws_wh_fc_write(uint8_t *ptr, struct ws_fc_ie *fc_ie);
|
||||||
uint8_t *ws_wh_rsl_write(uint8_t *ptr, uint8_t rsl);
|
uint8_t *ws_wh_rsl_write(uint8_t *ptr, uint8_t rsl);
|
||||||
uint8_t *ws_wh_vh_write(uint8_t *ptr, uint8_t *vendor_header, uint8_t vendor_header_length);
|
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);
|
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_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_bt_read(uint8_t *data, uint16_t length, struct ws_bt_ie *bt_ie);
|
||||||
|
bool ws_wh_fc_read(uint8_t *data, uint16_t length, struct ws_fc_ie *fc_ie);
|
||||||
bool ws_wh_rsl_read(uint8_t *data, uint16_t length, int8_t *rsl);
|
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);
|
bool ws_wh_ea_read(uint8_t *data, uint16_t length, uint8_t *eui64);
|
||||||
|
|
||||||
|
|
|
@ -226,6 +226,8 @@ void ws_llc_hopping_schedule_config(struct protocol_interface_info_entry *interf
|
||||||
|
|
||||||
void ws_llc_timer_seconds(struct protocol_interface_info_entry *interface, uint16_t seconds_update);
|
void ws_llc_timer_seconds(struct protocol_interface_info_entry *interface, uint16_t seconds_update);
|
||||||
|
|
||||||
|
void ws_llc_fast_timer(struct protocol_interface_info_entry *interface, uint16_t ticks);
|
||||||
|
|
||||||
bool ws_llc_eapol_relay_forward_filter(struct protocol_interface_info_entry *interface, const uint8_t *joiner_eui64, uint8_t mac_sequency, uint32_t rx_timestamp);
|
bool ws_llc_eapol_relay_forward_filter(struct protocol_interface_info_entry *interface, const uint8_t *joiner_eui64, uint8_t mac_sequency, uint32_t rx_timestamp);
|
||||||
|
|
||||||
ws_neighbor_temp_class_t *ws_llc_get_multicast_temp_entry(struct protocol_interface_info_entry *interface, const uint8_t *mac64);
|
ws_neighbor_temp_class_t *ws_llc_get_multicast_temp_entry(struct protocol_interface_info_entry *interface, const uint8_t *mac64);
|
||||||
|
|
|
@ -112,10 +112,16 @@ typedef struct {
|
||||||
bool active_eapol_session: 1; /**< Indicating active EAPOL message */
|
bool active_eapol_session: 1; /**< Indicating active EAPOL message */
|
||||||
} temp_entriest_t;
|
} temp_entriest_t;
|
||||||
|
|
||||||
|
/** EDFE response and Enhanced ACK data length */
|
||||||
|
|
||||||
|
#define ENHANCED_FRAME_RESPONSE (WH_IE_ELEMENT_HEADER_LENGTH + 2 + WH_IE_ELEMENT_HEADER_LENGTH + 4 + WH_IE_ELEMENT_HEADER_LENGTH + 1 + WH_IE_ELEMENT_HEADER_LENGTH + 5)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t mac_handle_base; /**< Mac handle id base this will be updated by 1 after use */
|
uint8_t mac_handle_base; /**< Mac handle id base this will be updated by 1 after use */
|
||||||
uint8_t llc_message_list_size; /**< llc_message_list list size */
|
uint8_t llc_message_list_size; /**< llc_message_list list size */
|
||||||
|
uint16_t edfe_rx_wait_timer;
|
||||||
mpx_class_t mpx_data_base; /**< MPX data be including USER API Class and user call backs */
|
mpx_class_t mpx_data_base; /**< MPX data be including USER API Class and user call backs */
|
||||||
|
|
||||||
llc_message_list_t llc_message_list; /**< Active Message list */
|
llc_message_list_t llc_message_list; /**< Active Message list */
|
||||||
llc_ie_params_t ie_params; /**< LLC IE header and Payload data configuration */
|
llc_ie_params_t ie_params; /**< LLC IE header and Payload data configuration */
|
||||||
temp_entriest_t *temp_entries;
|
temp_entriest_t *temp_entries;
|
||||||
|
@ -123,7 +129,7 @@ typedef struct {
|
||||||
ws_asynch_ind *asynch_ind; /**< LLC Asynch data indication call back configured by user */
|
ws_asynch_ind *asynch_ind; /**< LLC Asynch data indication call back configured by user */
|
||||||
ws_asynch_confirm *asynch_confirm; /**< LLC Asynch data confirmation call back configured by user */
|
ws_asynch_confirm *asynch_confirm; /**< LLC Asynch data confirmation call back configured by user */
|
||||||
ws_neighbor_info_request *ws_neighbor_info_request_cb; /**< LLC Neighbour discover API*/
|
ws_neighbor_info_request *ws_neighbor_info_request_cb; /**< LLC Neighbour discover API*/
|
||||||
uint8_t ws_enhanced_ack_elements[WH_IE_ELEMENT_HEADER_LENGTH + 4 + WH_IE_ELEMENT_HEADER_LENGTH + 1];
|
uint8_t ws_enhanced_response_elements[ENHANCED_FRAME_RESPONSE];
|
||||||
ns_ie_iovec_t ws_header_vector;
|
ns_ie_iovec_t ws_header_vector;
|
||||||
protocol_interface_info_entry_t *interface_ptr; /**< List link entry */
|
protocol_interface_info_entry_t *interface_ptr; /**< List link entry */
|
||||||
|
|
||||||
|
@ -167,6 +173,30 @@ static ws_neighbor_temp_class_t *ws_allocate_eapol_temp_entry(temp_entriest_t *b
|
||||||
|
|
||||||
static void ws_llc_mpx_eapol_send(llc_data_base_t *base, llc_message_t *message);
|
static void ws_llc_mpx_eapol_send(llc_data_base_t *base, llc_message_t *message);
|
||||||
|
|
||||||
|
static bool test_skip_first_init_response = false;
|
||||||
|
static uint8_t test_drop_data_message = 0;
|
||||||
|
|
||||||
|
|
||||||
|
int8_t ws_test_skip_edfe_data_send(int8_t interface_id, bool skip)
|
||||||
|
{
|
||||||
|
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||||
|
if (!cur || !ws_info(cur)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
test_skip_first_init_response = skip;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t ws_test_drop_edfe_data_frames(int8_t interface_id, uint8_t number_of_dropped_frames)
|
||||||
|
{
|
||||||
|
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||||
|
if (!cur || !ws_info(cur)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
test_drop_data_message = number_of_dropped_frames;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Discover Message by message handle id */
|
/** Discover Message by message handle id */
|
||||||
static llc_message_t *llc_message_discover_by_mac_handle(uint8_t handle, llc_message_list_t *list)
|
static llc_message_t *llc_message_discover_by_mac_handle(uint8_t handle, llc_message_list_t *list)
|
||||||
{
|
{
|
||||||
|
@ -304,7 +334,7 @@ static uint16_t ws_wh_headers_length(wh_ie_sub_list_t requested_list, llc_ie_par
|
||||||
|
|
||||||
if (requested_list.fc_ie) {
|
if (requested_list.fc_ie) {
|
||||||
//Static 1 bytes allways
|
//Static 1 bytes allways
|
||||||
length += WH_IE_ELEMENT_HEADER_LENGTH + 1;
|
length += WH_IE_ELEMENT_HEADER_LENGTH + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requested_list.rsl_ie) {
|
if (requested_list.rsl_ie) {
|
||||||
|
@ -414,7 +444,6 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol_interface_info_entry_t *interface = base->interface_ptr;
|
protocol_interface_info_entry_t *interface = base->interface_ptr;
|
||||||
|
|
||||||
llc_message_t *message = llc_message_discover_by_mac_handle(data->msduHandle, &base->llc_message_list);
|
llc_message_t *message = llc_message_discover_by_mac_handle(data->msduHandle, &base->llc_message_list);
|
||||||
if (!message) {
|
if (!message) {
|
||||||
return;
|
return;
|
||||||
|
@ -520,14 +549,15 @@ static void ws_llc_ack_data_req_ext(const mac_api_t *api, mcps_ack_data_payload_
|
||||||
memset(data, 0, sizeof(mcps_ack_data_payload_t));
|
memset(data, 0, sizeof(mcps_ack_data_payload_t));
|
||||||
//Add just 2 header elements to inside 1 block
|
//Add just 2 header elements to inside 1 block
|
||||||
data->ie_elements.headerIeVectorList = &base->ws_header_vector;
|
data->ie_elements.headerIeVectorList = &base->ws_header_vector;
|
||||||
base->ws_header_vector.ieBase = base->ws_enhanced_ack_elements;
|
base->ws_header_vector.ieBase = base->ws_enhanced_response_elements;
|
||||||
base->ws_header_vector.iovLen = sizeof(base->ws_enhanced_ack_elements);
|
|
||||||
data->ie_elements.headerIovLength = 1;
|
data->ie_elements.headerIovLength = 1;
|
||||||
|
|
||||||
//Write Data to block
|
//Write Data to block
|
||||||
uint8_t *ptr = base->ws_enhanced_ack_elements;
|
uint8_t *ptr = base->ws_enhanced_response_elements;
|
||||||
ptr = ws_wh_utt_write(ptr, WS_FT_ACK);
|
ptr = ws_wh_utt_write(ptr, WS_FT_ACK);
|
||||||
ws_wh_rsl_write(ptr, ws_neighbor_class_rsl_from_dbm_calculate(rssi));
|
ptr = ws_wh_rsl_write(ptr, ws_neighbor_class_rsl_from_dbm_calculate(rssi));
|
||||||
|
base->ws_header_vector.iovLen = ptr - base->ws_enhanced_response_elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -613,8 +643,14 @@ static void ws_llc_data_indication_cb(const mac_api_t *api, const mcps_data_ind_
|
||||||
protocol_interface_info_entry_t *interface = base->interface_ptr;
|
protocol_interface_info_entry_t *interface = base->interface_ptr;
|
||||||
|
|
||||||
//Validate Unicast shedule Channel Plan
|
//Validate Unicast shedule Channel Plan
|
||||||
if (us_ie_inline && !ws_bootstrap_validate_channel_plan(&us_ie, interface)) {
|
if (us_ie_inline &&
|
||||||
//Channel plan configuration mismatch
|
(!ws_bootstrap_validate_channel_plan(&us_ie, interface) ||
|
||||||
|
!ws_bootstrap_validate_channel_function(&us_ie, NULL))) {
|
||||||
|
//Channel plan or channel function configuration mismatch
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs_ie_inline && !ws_bootstrap_validate_channel_function(NULL, &ws_bs_ie)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,14 +684,14 @@ static void ws_llc_data_indication_cb(const mac_api_t *api, const mcps_data_ind_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!multicast && !ws_neighbor_class_neighbor_duplicate_packet_check(neighbor_info.ws_neighbor, data->DSN, data->timestamp)) {
|
if (!multicast && !data->DSN_suppressed && !ws_neighbor_class_neighbor_duplicate_packet_check(neighbor_info.ws_neighbor, data->DSN, data->timestamp)) {
|
||||||
tr_info("Drop duplicate message");
|
tr_info("Drop duplicate message");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp);
|
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp);
|
||||||
if (us_ie_inline) {
|
if (us_ie_inline) {
|
||||||
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie);
|
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie, &interface->ws_info->hopping_schdule);
|
||||||
}
|
}
|
||||||
//Update BS if it is part of message
|
//Update BS if it is part of message
|
||||||
if (bs_ie_inline) {
|
if (bs_ie_inline) {
|
||||||
|
@ -730,8 +766,14 @@ static void ws_llc_eapol_indication_cb(const mac_api_t *api, const mcps_data_ind
|
||||||
protocol_interface_info_entry_t *interface = base->interface_ptr;
|
protocol_interface_info_entry_t *interface = base->interface_ptr;
|
||||||
|
|
||||||
//Validate Unicast shedule Channel Plan
|
//Validate Unicast shedule Channel Plan
|
||||||
if (us_ie_inline && !ws_bootstrap_validate_channel_plan(&us_ie, interface)) {
|
if (us_ie_inline &&
|
||||||
//Channel plan configuration mismatch
|
(!ws_bootstrap_validate_channel_plan(&us_ie, interface) ||
|
||||||
|
!ws_bootstrap_validate_channel_function(&us_ie, NULL))) {
|
||||||
|
//Channel plan or channel function configuration mismatch
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs_ie_inline && !ws_bootstrap_validate_channel_function(NULL, &ws_bs_ie)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -755,7 +797,7 @@ static void ws_llc_eapol_indication_cb(const mac_api_t *api, const mcps_data_ind
|
||||||
uint8_t auth_eui64[8];
|
uint8_t auth_eui64[8];
|
||||||
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp);
|
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp);
|
||||||
if (us_ie_inline) {
|
if (us_ie_inline) {
|
||||||
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie);
|
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie, &interface->ws_info->hopping_schdule);
|
||||||
}
|
}
|
||||||
//Update BS if it is part of message
|
//Update BS if it is part of message
|
||||||
if (bs_ie_inline) {
|
if (bs_ie_inline) {
|
||||||
|
@ -933,6 +975,9 @@ static void ws_llc_lowpan_mpx_data_request(llc_data_base_t *base, mpx_user_t *us
|
||||||
nested_wp_id.vp_ie = true;
|
nested_wp_id.vp_ie = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->ExtendedFrameExchange && data->TxAckReq) {
|
||||||
|
ie_header_mask.fc_ie = true;
|
||||||
|
}
|
||||||
if (!data->TxAckReq) {
|
if (!data->TxAckReq) {
|
||||||
nested_wp_id.bs_ie = true;
|
nested_wp_id.bs_ie = true;
|
||||||
}
|
}
|
||||||
|
@ -977,17 +1022,31 @@ static void ws_llc_lowpan_mpx_data_request(llc_data_base_t *base, mpx_user_t *us
|
||||||
data_req.msduLength = 0;
|
data_req.msduLength = 0;
|
||||||
data_req.msduHandle = message->msg_handle;
|
data_req.msduHandle = message->msg_handle;
|
||||||
|
|
||||||
if (!data->TxAckReq) {
|
if (data->ExtendedFrameExchange && data->TxAckReq) {
|
||||||
data_req.PanIdSuppressed = false;
|
data_req.SeqNumSuppressed = true;
|
||||||
data_req.DstAddrMode = MAC_ADDR_MODE_NONE;
|
|
||||||
} else {
|
|
||||||
data_req.PanIdSuppressed = true;
|
data_req.PanIdSuppressed = true;
|
||||||
|
data_req.TxAckReq = true; // This will be changed inside MAC
|
||||||
|
} else {
|
||||||
|
data_req.ExtendedFrameExchange = false; //Do not accept EDFE for non unicast traffic
|
||||||
|
if (!data->TxAckReq) {
|
||||||
|
data_req.PanIdSuppressed = false;
|
||||||
|
data_req.DstAddrMode = MAC_ADDR_MODE_NONE;
|
||||||
|
} else {
|
||||||
|
data_req.PanIdSuppressed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *ptr = ws_message_buffer_ptr_get(message);
|
uint8_t *ptr = ws_message_buffer_ptr_get(message);
|
||||||
message->messsage_type = WS_FT_DATA;
|
message->messsage_type = WS_FT_DATA;
|
||||||
|
|
||||||
message->ie_vector_list[0].ieBase = ptr;
|
message->ie_vector_list[0].ieBase = ptr;
|
||||||
|
if (ie_header_mask.fc_ie) {
|
||||||
|
ws_fc_ie_t fc_ie;
|
||||||
|
fc_ie.tx_flow_ctrl = 50;//No data at initial frame
|
||||||
|
fc_ie.rx_flow_ctrl = 255;
|
||||||
|
//Write Flow control for 1 packet send this will be modified at real data send
|
||||||
|
ptr = ws_wh_fc_write(ptr, &fc_ie);
|
||||||
|
}
|
||||||
//Write UTT
|
//Write UTT
|
||||||
|
|
||||||
ptr = ws_wh_utt_write(ptr, message->messsage_type);
|
ptr = ws_wh_utt_write(ptr, message->messsage_type);
|
||||||
|
@ -1022,6 +1081,9 @@ static void ws_llc_lowpan_mpx_data_request(llc_data_base_t *base, mpx_user_t *us
|
||||||
message->ie_vector_list[2].iovLen = data->msduLength;
|
message->ie_vector_list[2].iovLen = data->msduLength;
|
||||||
|
|
||||||
ws_llc_lowpan_mpx_header_set(message, MPX_LOWPAN_ENC_USER_ID);
|
ws_llc_lowpan_mpx_header_set(message, MPX_LOWPAN_ENC_USER_ID);
|
||||||
|
if (data->ExtendedFrameExchange) {
|
||||||
|
message->ie_ext.payloadIovLength = 0; //Set Back 2 at response handler
|
||||||
|
}
|
||||||
|
|
||||||
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, NULL);
|
base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, NULL);
|
||||||
}
|
}
|
||||||
|
@ -1050,6 +1112,7 @@ static void ws_llc_eapol_data_req_init(mcps_data_req_t *data_req, llc_message_t
|
||||||
data_req->TxAckReq = message->ack_requested;
|
data_req->TxAckReq = message->ack_requested;
|
||||||
data_req->DstPANId = message->pan_id;
|
data_req->DstPANId = message->pan_id;
|
||||||
data_req->SrcAddrMode = message->src_address_type;
|
data_req->SrcAddrMode = message->src_address_type;
|
||||||
|
data_req->ExtendedFrameExchange = false;
|
||||||
if (!data_req->TxAckReq) {
|
if (!data_req->TxAckReq) {
|
||||||
data_req->PanIdSuppressed = false;
|
data_req->PanIdSuppressed = false;
|
||||||
data_req->DstAddrMode = MAC_ADDR_MODE_NONE;
|
data_req->DstAddrMode = MAC_ADDR_MODE_NONE;
|
||||||
|
@ -1403,6 +1466,104 @@ void ws_llc_free_multicast_temp_entry(protocol_interface_info_entry_t *cur, ws_n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ws_llc_build_edfe_response(llc_data_base_t *base, mcps_edfe_response_t *response_message, ws_fc_ie_t fc_ie)
|
||||||
|
{
|
||||||
|
memset(&response_message->ie_response, 0, sizeof(mcps_data_req_ie_list_t));
|
||||||
|
response_message->ie_response.headerIeVectorList = &base->ws_header_vector;
|
||||||
|
base->ws_header_vector.ieBase = base->ws_enhanced_response_elements;
|
||||||
|
response_message->ie_response.headerIovLength = 1;
|
||||||
|
|
||||||
|
//Write Data to block
|
||||||
|
uint8_t *ptr = base->ws_header_vector.ieBase;
|
||||||
|
ptr = ws_wh_fc_write(ptr, &fc_ie);
|
||||||
|
ptr = ws_wh_utt_write(ptr, WS_FT_DATA);
|
||||||
|
ptr = ws_wh_bt_write(ptr);
|
||||||
|
ptr = ws_wh_rsl_write(ptr, ws_neighbor_class_rsl_from_dbm_calculate(response_message->rssi));
|
||||||
|
base->ws_header_vector.iovLen = ptr - base->ws_enhanced_response_elements;
|
||||||
|
response_message->SrcAddrMode = MAC_ADDR_MODE_NONE;
|
||||||
|
response_message->wait_response = false;
|
||||||
|
response_message->PanIdSuppressed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ws_llc_build_edfe_frame(llc_message_t *message, mcps_edfe_response_t *response_message, ws_fc_ie_t fc_ie)
|
||||||
|
{
|
||||||
|
memset(&response_message->ie_response, 0, sizeof(mcps_data_req_ie_list_t));
|
||||||
|
uint8_t *ptr = message->ie_vector_list[0].ieBase;
|
||||||
|
fc_ie.tx_flow_ctrl = 0;//Put Data with Handshake
|
||||||
|
fc_ie.rx_flow_ctrl = 255;
|
||||||
|
//Write Flow control for 1 packet send this will be modified at real data send
|
||||||
|
ptr = ws_wh_fc_write(ptr, &fc_ie);
|
||||||
|
response_message->ie_response.headerIeVectorList = &message->ie_vector_list[0];
|
||||||
|
response_message->ie_response.headerIovLength = 1;
|
||||||
|
response_message->ie_response.payloadIeVectorList = &message->ie_vector_list[1];
|
||||||
|
response_message->ie_response.payloadIovLength = 2;
|
||||||
|
response_message->SrcAddrMode = MAC_ADDR_MODE_NONE;
|
||||||
|
response_message->wait_response = true;
|
||||||
|
response_message->PanIdSuppressed = true;
|
||||||
|
//tr_debug("FC:Send Data frame");
|
||||||
|
response_message->edfe_message_status = MCPS_EDFE_TX_FRAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ws_llc_mcps_edfe_handler(const mac_api_t *api, mcps_edfe_response_t *response_message)
|
||||||
|
{
|
||||||
|
// INSIDE this shuold not print anything
|
||||||
|
response_message->edfe_message_status = MCPS_EDFE_NORMAL_FRAME;
|
||||||
|
llc_data_base_t *base = ws_llc_discover_by_mac(api);
|
||||||
|
if (!base) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Discover Here header FC-IE element
|
||||||
|
ws_fc_ie_t fc_ie;
|
||||||
|
if (!ws_wh_fc_read(response_message->ie_elements.headerIeList, response_message->ie_elements.headerIeListLength, &fc_ie)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//tr_debug("Flow ctrl(%u TX,%u RX)", fc_ie.tx_flow_ctrl, fc_ie.rx_flow_ctrl);
|
||||||
|
if (fc_ie.tx_flow_ctrl == 0 && fc_ie.rx_flow_ctrl) {
|
||||||
|
|
||||||
|
llc_message_t *message = NULL;
|
||||||
|
if (response_message->use_message_handle_to_discover) {
|
||||||
|
message = llc_message_discover_by_mac_handle(response_message->message_handle, &base->llc_message_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!message) {
|
||||||
|
//tr_debug("FC:Send a Final Frame");
|
||||||
|
if (test_drop_data_message) {
|
||||||
|
test_drop_data_message--;
|
||||||
|
base->edfe_rx_wait_timer += 99;
|
||||||
|
response_message->edfe_message_status = MCPS_EDFE_MALFORMED_FRAME;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fc_ie.rx_flow_ctrl = 0;
|
||||||
|
base->edfe_rx_wait_timer = 0;
|
||||||
|
ws_llc_build_edfe_response(base, response_message, fc_ie);
|
||||||
|
response_message->edfe_message_status = MCPS_EDFE_FINAL_FRAME_TX;
|
||||||
|
} else {
|
||||||
|
if (test_skip_first_init_response) {
|
||||||
|
//Skip data send and test timeout at Slave side
|
||||||
|
test_skip_first_init_response = false;
|
||||||
|
response_message->edfe_message_status = MCPS_EDFE_FINAL_FRAME_RX;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ws_llc_build_edfe_frame(message, response_message, fc_ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (fc_ie.tx_flow_ctrl == 0 && fc_ie.rx_flow_ctrl == 0) {
|
||||||
|
//tr_debug("FC:Received a Final Frame");
|
||||||
|
base->edfe_rx_wait_timer = 0;
|
||||||
|
response_message->edfe_message_status = MCPS_EDFE_FINAL_FRAME_RX;
|
||||||
|
} else if (fc_ie.tx_flow_ctrl && fc_ie.rx_flow_ctrl) {
|
||||||
|
base->edfe_rx_wait_timer = fc_ie.tx_flow_ctrl + 99;
|
||||||
|
fc_ie.tx_flow_ctrl = 0;
|
||||||
|
fc_ie.rx_flow_ctrl = 255;
|
||||||
|
//tr_debug("FC:Send a response");
|
||||||
|
//Enable or refesh timeout timer
|
||||||
|
ws_llc_build_edfe_response(base, response_message, fc_ie);
|
||||||
|
response_message->edfe_message_status = MCPS_EDFE_RESPONSE_FRAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
llc_data_base_t *base = ws_llc_discover_by_interface(interface);
|
llc_data_base_t *base = ws_llc_discover_by_interface(interface);
|
||||||
|
@ -1423,6 +1584,7 @@ int8_t ws_llc_create(struct protocol_interface_info_entry *interface, ws_asynch_
|
||||||
base->ws_neighbor_info_request_cb = ws_neighbor_info_request_cb;
|
base->ws_neighbor_info_request_cb = ws_neighbor_info_request_cb;
|
||||||
//Register MAC Extensions
|
//Register MAC Extensions
|
||||||
base->interface_ptr->mac_api->mac_mcps_extension_enable(base->interface_ptr->mac_api, &ws_llc_mac_indication_cb, &ws_llc_mac_confirm_cb, &ws_llc_ack_data_req_ext);
|
base->interface_ptr->mac_api->mac_mcps_extension_enable(base->interface_ptr->mac_api, &ws_llc_mac_indication_cb, &ws_llc_mac_confirm_cb, &ws_llc_ack_data_req_ext);
|
||||||
|
base->interface_ptr->mac_api->mac_mcps_edfe_enable(base->interface_ptr->mac_api, &ws_llc_mcps_edfe_handler);
|
||||||
//Init MPX class
|
//Init MPX class
|
||||||
ws_llc_mpx_init(&base->mpx_data_base);
|
ws_llc_mpx_init(&base->mpx_data_base);
|
||||||
ws_llc_temp_neigh_info_table_reset(base->temp_entries);
|
ws_llc_temp_neigh_info_table_reset(base->temp_entries);
|
||||||
|
@ -1508,6 +1670,7 @@ int8_t ws_llc_asynch_request(struct protocol_interface_info_entry *interface, as
|
||||||
data_req.SrcAddrMode = MAC_ADDR_MODE_64_BIT;
|
data_req.SrcAddrMode = MAC_ADDR_MODE_64_BIT;
|
||||||
data_req.Key = request->security;
|
data_req.Key = request->security;
|
||||||
data_req.msduHandle = message->msg_handle;
|
data_req.msduHandle = message->msg_handle;
|
||||||
|
data_req.ExtendedFrameExchange = false;
|
||||||
if (request->message_type == WS_FT_PAN_ADVERT_SOL) {
|
if (request->message_type == WS_FT_PAN_ADVERT_SOL) {
|
||||||
// PANID not know yet must be supressed
|
// PANID not know yet must be supressed
|
||||||
data_req.PanIdSuppressed = true;
|
data_req.PanIdSuppressed = true;
|
||||||
|
@ -1651,6 +1814,39 @@ void ws_llc_hopping_schedule_config(struct protocol_interface_info_entry *interf
|
||||||
base->ie_params.hopping_schedule = hopping_schedule;
|
base->ie_params.hopping_schedule = hopping_schedule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ws_llc_fast_timer(struct protocol_interface_info_entry *interface, uint16_t ticks)
|
||||||
|
{
|
||||||
|
llc_data_base_t *base = ws_llc_discover_by_interface(interface);
|
||||||
|
if (!base || !base->edfe_rx_wait_timer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ticks > 0xffff / 100) {
|
||||||
|
ticks = 0xffff;
|
||||||
|
} else if (ticks == 0) {
|
||||||
|
ticks = 1;
|
||||||
|
} else {
|
||||||
|
ticks *= 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base->edfe_rx_wait_timer > ticks) {
|
||||||
|
base->edfe_rx_wait_timer -= ticks;
|
||||||
|
} else {
|
||||||
|
base->edfe_rx_wait_timer = 0;
|
||||||
|
tr_debug("EDFE Data Wait Timeout");
|
||||||
|
//MAC edfe wait data timeout
|
||||||
|
if (interface->mac_api && interface->mac_api->mlme_req) {
|
||||||
|
mlme_set_t set_req;
|
||||||
|
uint8_t value = 0;
|
||||||
|
set_req.attr = macEdfeForceStop;
|
||||||
|
set_req.attr_index = 0;
|
||||||
|
set_req.value_pointer = &value;
|
||||||
|
set_req.value_size = 1;
|
||||||
|
interface->mac_api->mlme_req(interface->mac_api, MLME_SET, &set_req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ws_llc_timer_seconds(struct protocol_interface_info_entry *interface, uint16_t seconds_update)
|
void ws_llc_timer_seconds(struct protocol_interface_info_entry *interface, uint16_t seconds_update)
|
||||||
{
|
{
|
||||||
llc_data_base_t *base = ws_llc_discover_by_interface(interface);
|
llc_data_base_t *base = ws_llc_discover_by_interface(interface);
|
||||||
|
|
|
@ -731,4 +731,14 @@ int ws_management_timing_parameters_validate(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ws_stack_info_get(int8_t interface_id, ws_stack_info_t *info_ptr)
|
||||||
|
{
|
||||||
|
protocol_interface_info_entry_t *cur;
|
||||||
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||||
|
if (!cur || !ws_info(cur) || !info_ptr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ws_bootstrap_get_info(cur, info_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAVE_WS
|
#endif // HAVE_WS
|
||||||
|
|
|
@ -95,28 +95,6 @@ void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry
|
||||||
ws_neighbor->fhss_data.uc_timing_info.ufsi = ws_utt->ufsi;
|
ws_neighbor->fhss_data.uc_timing_info.ufsi = ws_utt->ufsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ws_neighbour_channel_list_enable_all(ws_channel_mask_t *channel_info, uint16_t number_of_channels)
|
|
||||||
{
|
|
||||||
uint32_t mask;
|
|
||||||
channel_info->channel_count = number_of_channels;
|
|
||||||
for (uint8_t n = 0; n < 8; n++) {
|
|
||||||
if (number_of_channels >= 32) {
|
|
||||||
mask = 0xffffffff;
|
|
||||||
number_of_channels -= 32;
|
|
||||||
} else if (number_of_channels) {
|
|
||||||
mask = 0;
|
|
||||||
//Start bit enable to MSB
|
|
||||||
for (uint16_t i = 0; i < (number_of_channels % 32); i++) {
|
|
||||||
mask |= 1 << i;
|
|
||||||
}
|
|
||||||
number_of_channels = 0;
|
|
||||||
} else {
|
|
||||||
mask = 0;
|
|
||||||
}
|
|
||||||
channel_info->channel_mask[n] = mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ws_neighbour_excluded_mask_by_range(ws_channel_mask_t *channel_info, ws_excluded_channel_range_t *range_info, uint16_t number_of_channels)
|
static void ws_neighbour_excluded_mask_by_range(ws_channel_mask_t *channel_info, ws_excluded_channel_range_t *range_info, uint16_t number_of_channels)
|
||||||
{
|
{
|
||||||
uint16_t range_start, range_stop;
|
uint16_t range_start, range_stop;
|
||||||
|
@ -210,29 +188,34 @@ static void ws_neighbour_excluded_mask_by_mask(ws_channel_mask_t *channel_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_us_ie_t *ws_us)
|
void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_us_ie_t *ws_us, ws_hopping_schedule_t *own_shedule)
|
||||||
{
|
{
|
||||||
ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function = ws_us->channel_function;
|
ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function = ws_us->channel_function;
|
||||||
if (ws_us->channel_function == WS_FIXED_CHANNEL) {
|
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.fixed_channel = ws_us->function.zero.fixed_channel;
|
||||||
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = 1;
|
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (ws_us->channel_plan == 0) {
|
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);
|
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) {
|
} 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;
|
ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_us->plan.one.number_of_channel;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Handle excluded channel and generate activate channel list
|
//Handle excluded channel and generate activate channel list
|
||||||
if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_RANGE) {
|
if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_RANGE) {
|
||||||
ws_neighbour_channel_list_enable_all(&ws_neighbor->fhss_data.uc_channel_list, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class);
|
||||||
|
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
||||||
ws_neighbour_excluded_mask_by_range(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.range, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
ws_neighbour_excluded_mask_by_range(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.range, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
||||||
} else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_BITMASK) {
|
} else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_BITMASK) {
|
||||||
ws_neighbour_channel_list_enable_all(&ws_neighbor->fhss_data.uc_channel_list, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class);
|
||||||
|
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
||||||
ws_neighbour_excluded_mask_by_mask(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
ws_neighbour_excluded_mask_by_mask(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
||||||
} else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_NONE) {
|
} else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_NONE) {
|
||||||
if (ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels != ws_neighbor->fhss_data.uc_channel_list.channel_count) {
|
if (ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels != ws_neighbor->fhss_data.uc_channel_list.channel_count) {
|
||||||
ws_neighbour_channel_list_enable_all(&ws_neighbor->fhss_data.uc_channel_list, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class);
|
||||||
|
ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry
|
||||||
* \param ws_us Unicast schedule IE data
|
* \param ws_us Unicast schedule IE data
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_us_ie_t *ws_us);
|
void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_us_ie_t *ws_us, ws_hopping_schedule_t *own_shedule);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -39,9 +39,11 @@
|
||||||
#include "Security/protocols/sec_prot_keys.h"
|
#include "Security/protocols/sec_prot_keys.h"
|
||||||
#include "Security/protocols/key_sec_prot/key_sec_prot.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/eap_tls_sec_prot/auth_eap_tls_sec_prot.h"
|
||||||
|
#include "Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.h"
|
||||||
#include "Security/protocols/tls_sec_prot/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/fwh_sec_prot/auth_fwh_sec_prot.h"
|
||||||
#include "Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.h"
|
#include "Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.h"
|
||||||
|
#include "Security/protocols/radius_sec_prot/radius_client_sec_prot.h"
|
||||||
#include "6LoWPAN/ws/ws_cfg_settings.h"
|
#include "6LoWPAN/ws/ws_cfg_settings.h"
|
||||||
#include "6LoWPAN/ws/ws_pae_controller.h"
|
#include "6LoWPAN/ws/ws_pae_controller.h"
|
||||||
#include "6LoWPAN/ws/ws_pae_timers.h"
|
#include "6LoWPAN/ws/ws_pae_timers.h"
|
||||||
|
@ -90,14 +92,16 @@ typedef struct {
|
||||||
ws_pae_auth_nw_keys_remove *nw_keys_remove; /**< Network keys remove callback */
|
ws_pae_auth_nw_keys_remove *nw_keys_remove; /**< Network keys remove callback */
|
||||||
ws_pae_auth_nw_key_index_set *nw_key_index_set; /**< Key index set callback */
|
ws_pae_auth_nw_key_index_set *nw_key_index_set; /**< Key index set callback */
|
||||||
ws_pae_auth_nw_info_updated *nw_info_updated; /**< Security keys network info updated callback */
|
ws_pae_auth_nw_info_updated *nw_info_updated; /**< Security keys network info updated callback */
|
||||||
|
ws_pae_auth_ip_addr_get *ip_addr_get; /**< IP address get callback */
|
||||||
supp_list_t active_supp_list; /**< List of active supplicants */
|
supp_list_t active_supp_list; /**< List of active supplicants */
|
||||||
arm_event_storage_t *timer; /**< Timer */
|
arm_event_storage_t *timer; /**< Timer */
|
||||||
sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */
|
sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */
|
||||||
const sec_prot_certs_t *certs; /**< Certificates */
|
const sec_prot_certs_t *certs; /**< Certificates */
|
||||||
sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */
|
sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */
|
||||||
sec_timer_cfg_t *sec_timer_cfg; /**< Timer configuration */
|
sec_cfg_t *sec_cfg; /**< Security configuration */
|
||||||
sec_prot_cfg_t *sec_prot_cfg; /**< Protocol Configuration */
|
|
||||||
uint16_t supp_max_number; /**< Max number of stored supplicants */
|
uint16_t supp_max_number; /**< Max number of stored supplicants */
|
||||||
|
uint8_t relay_socked_msg_if_instance_id; /**< Relay socket message interface instance identifier */
|
||||||
|
uint8_t radius_socked_msg_if_instance_id; /**< Radius socket message interface instance identifier */
|
||||||
bool timer_running : 1; /**< Timer is running */
|
bool timer_running : 1; /**< Timer is running */
|
||||||
bool gtk_new_inst_req_exp : 1; /**< GTK new install required timer expired */
|
bool gtk_new_inst_req_exp : 1; /**< GTK new install required timer expired */
|
||||||
bool gtk_new_act_time_exp: 1; /**< GTK new activation time expired */
|
bool gtk_new_act_time_exp: 1; /**< GTK new activation time expired */
|
||||||
|
@ -119,22 +123,23 @@ static int8_t ws_pae_auth_timer_start(pae_auth_t *pae_auth);
|
||||||
static int8_t ws_pae_auth_timer_stop(pae_auth_t *pae_auth);
|
static int8_t ws_pae_auth_timer_stop(pae_auth_t *pae_auth);
|
||||||
static bool ws_pae_auth_timer_running(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 void ws_pae_auth_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr);
|
||||||
|
static void ws_pae_auth_kmp_service_ip_addr_get(kmp_service_t *service, kmp_api_t *kmp, uint8_t *address);
|
||||||
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_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 kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, uint8_t msg_if_instance_id, kmp_type_e type, const kmp_addr_t *addr, const void *pdu, uint16_t size);
|
||||||
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_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_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 void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
|
||||||
static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
|
static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
|
||||||
static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
|
static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry_t *supp_entry);
|
||||||
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry, sec_prot_cfg_t *prot_cfg, sec_timer_cfg_t *timer_cfg);
|
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, uint8_t socked_msg_if_instance_id, supp_entry_t *supp_entry, sec_cfg_t *sec_cfg);
|
||||||
static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp);
|
static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp);
|
||||||
|
|
||||||
static int8_t tasklet_id = -1;
|
static int8_t tasklet_id = -1;
|
||||||
static NS_LIST_DEFINE(pae_auth_list, pae_auth_t, link);
|
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 *next_gtks, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info)
|
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info)
|
||||||
{
|
{
|
||||||
if (!interface_ptr || !next_gtks || !certs || !sec_timer_cfg || !sec_prot_cfg || !sec_keys_nw_info) {
|
if (!interface_ptr || !next_gtks || !certs || !sec_cfg || !sec_keys_nw_info) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +152,6 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
memset(&pae_auth->network_name, 0, 33);
|
memset(&pae_auth->network_name, 0, 33);
|
||||||
pae_auth->pan_id = 0xffff;
|
pae_auth->pan_id = 0xffff;
|
||||||
pae_auth->interface_ptr = interface_ptr;
|
pae_auth->interface_ptr = interface_ptr;
|
||||||
|
@ -162,19 +166,21 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
|
||||||
pae_auth->next_gtks = next_gtks;
|
pae_auth->next_gtks = next_gtks;
|
||||||
pae_auth->certs = certs;
|
pae_auth->certs = certs;
|
||||||
pae_auth->sec_keys_nw_info = sec_keys_nw_info;
|
pae_auth->sec_keys_nw_info = sec_keys_nw_info;
|
||||||
pae_auth->sec_timer_cfg = sec_timer_cfg;
|
pae_auth->sec_cfg = sec_cfg;
|
||||||
pae_auth->sec_prot_cfg = sec_prot_cfg;
|
|
||||||
pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER;
|
pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER;
|
||||||
|
|
||||||
pae_auth->gtk_new_inst_req_exp = false;
|
pae_auth->gtk_new_inst_req_exp = false;
|
||||||
pae_auth->gtk_new_act_time_exp = false;
|
pae_auth->gtk_new_act_time_exp = false;
|
||||||
|
|
||||||
|
pae_auth->relay_socked_msg_if_instance_id = 0;
|
||||||
|
pae_auth->radius_socked_msg_if_instance_id = 0;
|
||||||
|
|
||||||
pae_auth->kmp_service = kmp_service_create();
|
pae_auth->kmp_service = kmp_service_create();
|
||||||
if (!pae_auth->kmp_service) {
|
if (!pae_auth->kmp_service) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kmp_service_cb_register(pae_auth->kmp_service, ws_pae_auth_kmp_incoming_ind, NULL, ws_pae_auth_kmp_service_addr_get, ws_pae_auth_kmp_service_api_get)) {
|
if (kmp_service_cb_register(pae_auth->kmp_service, ws_pae_auth_kmp_incoming_ind, NULL, ws_pae_auth_kmp_service_addr_get, ws_pae_auth_kmp_service_ip_addr_get, ws_pae_auth_kmp_service_api_get)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,10 +196,18 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auth_eap_tls_sec_prot_register(pae_auth->kmp_service) < 0) {
|
// Register radius EAP-TLS and radius client security protocols
|
||||||
|
if (radius_eap_tls_sec_prot_register(pae_auth->kmp_service) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (radius_client_sec_prot_register(pae_auth->kmp_service) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register EAP-TLS and TLS security protocols
|
||||||
|
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) {
|
if (server_tls_sec_prot_register(pae_auth->kmp_service) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +255,24 @@ int8_t ws_pae_auth_addresses_set(protocol_interface_info_entry_t *interface_ptr,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kmp_socket_if_register(pae_auth->kmp_service, local_port, remote_addr, remote_port) < 0) {
|
if (kmp_socket_if_register(pae_auth->kmp_service, &pae_auth->relay_socked_msg_if_instance_id, true, local_port, remote_addr, remote_port) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t ws_pae_auth_radius_address_set(protocol_interface_info_entry_t *interface_ptr, const uint8_t *remote_addr)
|
||||||
|
{
|
||||||
|
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, &pae_auth->radius_socked_msg_if_instance_id, false, 0, remote_addr, 1812) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +294,7 @@ int8_t ws_pae_auth_delete(protocol_interface_info_entry_t *interface_ptr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated)
|
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get)
|
||||||
{
|
{
|
||||||
if (!interface_ptr) {
|
if (!interface_ptr) {
|
||||||
return;
|
return;
|
||||||
|
@ -278,6 +309,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
|
||||||
pae_auth->nw_key_insert = nw_key_insert;
|
pae_auth->nw_key_insert = nw_key_insert;
|
||||||
pae_auth->nw_key_index_set = nw_key_index_set;
|
pae_auth->nw_key_index_set = nw_key_index_set;
|
||||||
pae_auth->nw_info_updated = nw_info_updated;
|
pae_auth->nw_info_updated = nw_info_updated;
|
||||||
|
pae_auth->ip_addr_get = ip_addr_get;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr)
|
void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr)
|
||||||
|
@ -392,7 +424,7 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int
|
||||||
// As default removes other keys than active
|
// As default removes other keys than active
|
||||||
int8_t not_removed_index = active_index;
|
int8_t not_removed_index = active_index;
|
||||||
|
|
||||||
uint32_t revocation_lifetime = ws_pae_timers_gtk_revocation_lifetime_get(pae_auth->sec_timer_cfg);
|
uint32_t revocation_lifetime = ws_pae_timers_gtk_revocation_lifetime_get(pae_auth->sec_cfg);
|
||||||
|
|
||||||
uint32_t active_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, active_index);
|
uint32_t active_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, active_index);
|
||||||
|
|
||||||
|
@ -470,8 +502,10 @@ void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr)
|
||||||
ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE);
|
ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name)
|
int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, bool updated)
|
||||||
{
|
{
|
||||||
|
(void) updated;
|
||||||
|
|
||||||
if (!interface_ptr || !network_name) {
|
if (!interface_ptr || !network_name) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -666,7 +700,7 @@ void ws_pae_auth_slow_timer(uint16_t seconds)
|
||||||
uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, i, current_time, seconds);
|
uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, i, current_time, seconds);
|
||||||
if (active_index == i) {
|
if (active_index == i) {
|
||||||
if (!pae_auth->gtk_new_inst_req_exp) {
|
if (!pae_auth->gtk_new_inst_req_exp) {
|
||||||
pae_auth->gtk_new_inst_req_exp = ws_pae_timers_gtk_new_install_required(pae_auth->sec_timer_cfg, timer_seconds);
|
pae_auth->gtk_new_inst_req_exp = ws_pae_timers_gtk_new_install_required(pae_auth->sec_cfg, timer_seconds);
|
||||||
if (pae_auth->gtk_new_inst_req_exp) {
|
if (pae_auth->gtk_new_inst_req_exp) {
|
||||||
int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->sec_keys_nw_info->gtks);
|
int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->sec_keys_nw_info->gtks);
|
||||||
if (second_index < 0) {
|
if (second_index < 0) {
|
||||||
|
@ -682,7 +716,7 @@ void ws_pae_auth_slow_timer(uint16_t seconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pae_auth->gtk_new_act_time_exp) {
|
if (!pae_auth->gtk_new_act_time_exp) {
|
||||||
pae_auth->gtk_new_act_time_exp = ws_pae_timers_gtk_new_activation_time(pae_auth->sec_timer_cfg, timer_seconds);
|
pae_auth->gtk_new_act_time_exp = ws_pae_timers_gtk_new_activation_time(pae_auth->sec_cfg, timer_seconds);
|
||||||
if (pae_auth->gtk_new_act_time_exp) {
|
if (pae_auth->gtk_new_act_time_exp) {
|
||||||
int8_t new_active_index = ws_pae_auth_new_gtk_activate(pae_auth);
|
int8_t new_active_index = ws_pae_auth_new_gtk_activate(pae_auth);
|
||||||
tr_info("GTK new activation time active index: %i, time: %"PRIu32", new index: %i, system time: %"PRIu32"", active_index, timer_seconds, new_active_index, protocol_core_monotonic_time / 10);
|
tr_info("GTK new activation time active index: %i, time: %"PRIu32", new index: %i, system time: %"PRIu32"", active_index, timer_seconds, new_active_index, protocol_core_monotonic_time / 10);
|
||||||
|
@ -737,7 +771,7 @@ static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets latest installed key lifetime and adds GTK expire offset to it
|
// Gets latest installed key lifetime and adds GTK expire offset to it
|
||||||
uint32_t lifetime = pae_auth->sec_timer_cfg->gtk_expire_offset;
|
uint32_t lifetime = pae_auth->sec_cfg->timer_cfg.gtk_expire_offset;
|
||||||
int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->sec_keys_nw_info->gtks);
|
int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->sec_keys_nw_info->gtks);
|
||||||
if (last_index >= 0) {
|
if (last_index >= 0) {
|
||||||
lifetime += sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, last_index);
|
lifetime += sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, last_index);
|
||||||
|
@ -840,6 +874,18 @@ static void ws_pae_auth_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ws_pae_auth_kmp_service_ip_addr_get(kmp_service_t *service, kmp_api_t *kmp, uint8_t *address)
|
||||||
|
{
|
||||||
|
(void) kmp;
|
||||||
|
|
||||||
|
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||||
|
if (!pae_auth) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pae_auth->ip_addr_get(pae_auth->interface_ptr, address);
|
||||||
|
}
|
||||||
|
|
||||||
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_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type)
|
||||||
{
|
{
|
||||||
(void) service;
|
(void) service;
|
||||||
|
@ -852,19 +898,26 @@ static kmp_api_t *ws_pae_auth_kmp_service_api_get(kmp_service_t *service, kmp_ap
|
||||||
return ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, type);
|
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)
|
static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, uint8_t msg_if_instance_id, kmp_type_e type, const kmp_addr_t *addr, const void *pdu, uint16_t size)
|
||||||
{
|
{
|
||||||
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||||
if (!pae_auth) {
|
if (!pae_auth) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find supplicant from list of active supplicants
|
// For radius messages
|
||||||
|
if (msg_if_instance_id == pae_auth->radius_socked_msg_if_instance_id) {
|
||||||
|
// Find KMP from list of active supplicants based on radius message
|
||||||
|
kmp_api_t *kmp_api = ws_pae_lib_supp_list_kmp_receive_check(&pae_auth->active_supp_list, pdu, size);
|
||||||
|
return kmp_api;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For relay messages find supplicant from list of active supplicants based on EUI-64
|
||||||
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));
|
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) {
|
if (!supp_entry) {
|
||||||
// Checks if active supplicant list has space for new supplicants
|
// Checks if active supplicant list has space for new supplicants
|
||||||
if (ws_pae_lib_supp_list_active_limit_reached(&pae_auth->active_supp_list, pae_auth->sec_prot_cfg->sec_max_ongoing_authentication)) {
|
if (ws_pae_lib_supp_list_active_limit_reached(&pae_auth->active_supp_list, pae_auth->sec_cfg->prot_cfg.sec_max_ongoing_authentication)) {
|
||||||
tr_debug("PAE: active limit reached, eui-64: %s", trace_array(kmp_address_eui_64_get(addr), 8));
|
tr_debug("PAE: active limit reached, eui-64: %s", trace_array(kmp_address_eui_64_get(addr), 8));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -892,14 +945,21 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_
|
||||||
// Increases waiting time for supplicant authentication
|
// Increases waiting time for supplicant authentication
|
||||||
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS);
|
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS);
|
||||||
|
|
||||||
// Get KMP for supplicant
|
kmp_type_e kmp_type_to_search = type;
|
||||||
kmp_api_t *kmp = ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, type);
|
|
||||||
|
// If radius is enabled, route EAP-TLS to radius EAP-TLS
|
||||||
|
if (pae_auth->sec_cfg->radius_cfg.radius_addr_set && type == IEEE_802_1X_MKA) {
|
||||||
|
kmp_type_to_search = RADIUS_IEEE_802_1X_MKA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for existing KMP for supplicant
|
||||||
|
kmp_api_t *kmp = ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, kmp_type_to_search);
|
||||||
if (kmp) {
|
if (kmp) {
|
||||||
return kmp;
|
return kmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new KMP for initial eapol-key
|
// Create a new KMP for initial eapol-key
|
||||||
kmp = kmp_api_create(service, type + IEEE_802_1X_INITIAL_KEY, pae_auth->sec_prot_cfg, pae_auth->sec_timer_cfg);
|
kmp = kmp_api_create(service, type + IEEE_802_1X_INITIAL_KEY, pae_auth->relay_socked_msg_if_instance_id, pae_auth->sec_cfg);
|
||||||
|
|
||||||
if (!kmp) {
|
if (!kmp) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -998,15 +1058,15 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
|
||||||
// Increases waiting time for supplicant authentication
|
// Increases waiting time for supplicant authentication
|
||||||
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS);
|
ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS);
|
||||||
|
|
||||||
if (next_type == IEEE_802_1X_MKA) {
|
if (next_type == IEEE_802_1X_MKA || next_type == RADIUS_IEEE_802_1X_MKA) {
|
||||||
/* For EAP-TLS, limits the number of ongoing negotiations. If limit
|
/* For EAP-TLS, limits the number of ongoing negotiations. If limit
|
||||||
is reached, authenticator does not initiate EAP-TLS right away.
|
is reached, authenticator does not initiate EAP-TLS right away.
|
||||||
If previous EAP-TLS negotiation completes before negotiation
|
If previous EAP-TLS negotiation completes before negotiation
|
||||||
trigger timeout, authenticator initiates EAP-TLS towards
|
trigger timeout, authenticator initiates EAP-TLS towards
|
||||||
supplicant. Otherwise supplicant must re-send initial EAPOL-Key
|
supplicant. Otherwise supplicant must re-send initial EAPOL-Key
|
||||||
to try again using its trickle schedule */
|
to try again using its trickle schedule */
|
||||||
uint16_t ongoing_eap_tls_cnt = ws_pae_lib_supp_list_kmp_count(&pae_auth->active_supp_list, IEEE_802_1X_MKA);
|
uint16_t ongoing_eap_tls_cnt = ws_pae_lib_supp_list_kmp_count(&pae_auth->active_supp_list, next_type);
|
||||||
if (ongoing_eap_tls_cnt >= pae_auth->sec_prot_cfg->sec_max_ongoing_authentication) {
|
if (ongoing_eap_tls_cnt >= pae_auth->sec_cfg->prot_cfg.sec_max_ongoing_authentication) {
|
||||||
supp_entry->retry_ticks = EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT;
|
supp_entry->retry_ticks = EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT;
|
||||||
tr_info("EAP-TLS max ongoing reached, count %i, delayed: eui-64: %s", ongoing_eap_tls_cnt, trace_array(supp_entry->addr.eui_64, 8));
|
tr_info("EAP-TLS max ongoing reached, count %i, delayed: eui-64: %s", ongoing_eap_tls_cnt, trace_array(supp_entry->addr.eui_64, 8));
|
||||||
return;
|
return;
|
||||||
|
@ -1014,12 +1074,25 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new instance
|
// Create new instance
|
||||||
kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, next_type, supp_entry, pae_auth->sec_prot_cfg, pae_auth->sec_timer_cfg);
|
kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, next_type, pae_auth->relay_socked_msg_if_instance_id, supp_entry, pae_auth->sec_cfg);
|
||||||
if (!new_kmp) {
|
if (!new_kmp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For EAP-TLS create also TLS in addition to EAP-TLS
|
// For radius EAP-TLS create also radius client in addition to EAP-TLS
|
||||||
|
if (next_type == RADIUS_IEEE_802_1X_MKA) {
|
||||||
|
if (ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, RADIUS_CLIENT_PROT) != NULL) {
|
||||||
|
// Radius client already exists, wait for it to be deleted
|
||||||
|
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Create radius client instance */
|
||||||
|
if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, RADIUS_CLIENT_PROT, pae_auth->radius_socked_msg_if_instance_id, supp_entry, pae_auth->sec_cfg) == NULL) {
|
||||||
|
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// For EAP-TLS create also TLS client in addition to EAP-TLS
|
||||||
if (next_type == IEEE_802_1X_MKA) {
|
if (next_type == IEEE_802_1X_MKA) {
|
||||||
if (ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, TLS_PROT) != NULL) {
|
if (ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, TLS_PROT) != NULL) {
|
||||||
// TLS already exists, wait for it to be deleted
|
// TLS already exists, wait for it to be deleted
|
||||||
|
@ -1027,7 +1100,7 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Create TLS instance */
|
// Create TLS instance */
|
||||||
if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, TLS_PROT, supp_entry, pae_auth->sec_prot_cfg, pae_auth->sec_timer_cfg) == NULL) {
|
if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, TLS_PROT, pae_auth->relay_socked_msg_if_instance_id, supp_entry, pae_auth->sec_cfg) == NULL) {
|
||||||
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1045,7 +1118,11 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry
|
||||||
if (sec_keys->pmk_mismatch) {
|
if (sec_keys->pmk_mismatch) {
|
||||||
sec_keys->ptk_mismatch = true;
|
sec_keys->ptk_mismatch = true;
|
||||||
// start EAP-TLS towards supplicant
|
// start EAP-TLS towards supplicant
|
||||||
next_type = IEEE_802_1X_MKA;
|
if (pae_auth->sec_cfg->radius_cfg.radius_addr_set) {
|
||||||
|
next_type = RADIUS_IEEE_802_1X_MKA;
|
||||||
|
} else {
|
||||||
|
next_type = IEEE_802_1X_MKA;
|
||||||
|
}
|
||||||
tr_info("PAE start EAP-TLS, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
tr_info("PAE start EAP-TLS, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
|
||||||
} else if (sec_keys->ptk_mismatch) {
|
} else if (sec_keys->ptk_mismatch) {
|
||||||
// start 4WH towards supplicant
|
// start 4WH towards supplicant
|
||||||
|
@ -1054,7 +1131,7 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t gtk_index = -1;
|
int8_t gtk_index = -1;
|
||||||
if (next_type != IEEE_802_1X_MKA) {
|
if (next_type != IEEE_802_1X_MKA && next_type != RADIUS_IEEE_802_1X_MKA) {
|
||||||
// Checks if GTK needs to be inserted
|
// Checks if GTK needs to be inserted
|
||||||
gtk_index = sec_prot_keys_gtk_insert_index_from_gtkl_get(sec_keys);
|
gtk_index = sec_prot_keys_gtk_insert_index_from_gtkl_get(sec_keys);
|
||||||
|
|
||||||
|
@ -1071,7 +1148,7 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry
|
||||||
* has been, trigger 4WH to update also the PTK. This prevents writing multiple
|
* has been, trigger 4WH to update also the PTK. This prevents writing multiple
|
||||||
* GTK keys to same index using same PTK.
|
* GTK keys to same index using same PTK.
|
||||||
*/
|
*/
|
||||||
if (pae_auth->sec_timer_cfg->gtk_expire_offset > SHORT_GTK_LIFETIME &&
|
if (pae_auth->sec_cfg->timer_cfg.gtk_expire_offset > SHORT_GTK_LIFETIME &&
|
||||||
sec_prot_keys_ptk_installed_gtk_hash_mismatch_check(sec_keys, gtk_index)) {
|
sec_prot_keys_ptk_installed_gtk_hash_mismatch_check(sec_keys, gtk_index)) {
|
||||||
// start 4WH towards supplicant
|
// start 4WH towards supplicant
|
||||||
next_type = IEEE_802_11_4WH;
|
next_type = IEEE_802_11_4WH;
|
||||||
|
@ -1094,15 +1171,22 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry
|
||||||
return next_type;
|
return next_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry, sec_prot_cfg_t *prot_cfg, sec_timer_cfg_t *timer_cfg)
|
static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, uint8_t socked_msg_if_instance_id, supp_entry_t *supp_entry, sec_cfg_t *sec_cfg)
|
||||||
{
|
{
|
||||||
// Create KMP instance for new authentication
|
// Create KMP instance for new authentication
|
||||||
kmp_api_t *kmp = kmp_api_create(service, type, prot_cfg, timer_cfg);
|
kmp_api_t *kmp = kmp_api_create(service, type, socked_msg_if_instance_id, sec_cfg);
|
||||||
|
|
||||||
if (!kmp) {
|
if (!kmp) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
if (ws_pae_lib_kmp_list_add(&supp_entry->kmp_list, kmp) == NULL) {
|
||||||
kmp_api_delete(kmp);
|
kmp_api_delete(kmp);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1135,7 +1219,7 @@ static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp)
|
||||||
pae_auth_t *pae_auth = NULL;
|
pae_auth_t *pae_auth = NULL;
|
||||||
supp_entry_t *retry_supp = NULL;
|
supp_entry_t *retry_supp = NULL;
|
||||||
// When EAP-TLS completes check if there are other supplicants that have requested it lately
|
// When EAP-TLS completes check if there are other supplicants that have requested it lately
|
||||||
if (kmp_api_type_get(kmp) == IEEE_802_1X_MKA) {
|
if (kmp_api_type_get(kmp) == IEEE_802_1X_MKA || kmp_api_type_get(kmp) == RADIUS_IEEE_802_1X_MKA) {
|
||||||
kmp_service_t *service = kmp_api_service_get(kmp);
|
kmp_service_t *service = kmp_api_service_get(kmp);
|
||||||
pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
pae_auth = ws_pae_auth_by_kmp_service_get(service);
|
||||||
if (pae_auth) {
|
if (pae_auth) {
|
||||||
|
|
|
@ -46,15 +46,14 @@
|
||||||
* \param next_gtks next group keys to be used
|
* \param next_gtks next group keys to be used
|
||||||
* \param cert_chain certificate chain
|
* \param cert_chain certificate chain
|
||||||
* \param timer_settings timer settings
|
* \param timer_settings timer settings
|
||||||
* \param sec_timer_cfg timer configuration
|
* \param sec_cfg security configuration
|
||||||
* \param sec_prot_cfg protocol configuration
|
|
||||||
* \param sec_keys_nw_info security keys network information
|
* \param sec_keys_nw_info security keys network information
|
||||||
*
|
*
|
||||||
* \return < 0 failure
|
* \return < 0 failure
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info);
|
int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_auth_addresses_set set relay addresses
|
* ws_pae_auth_addresses_set set relay addresses
|
||||||
|
@ -70,6 +69,18 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
|
||||||
*/
|
*/
|
||||||
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);
|
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_radius_address_set set radius address
|
||||||
|
*
|
||||||
|
* \param interface_ptr interface
|
||||||
|
* \param remote_addr remote address
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t ws_pae_auth_radius_address_set(protocol_interface_info_entry_t *interface_ptr, const uint8_t *remote_addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_auth_delete deletes PAE authenticator
|
* ws_pae_auth_delete deletes PAE authenticator
|
||||||
*
|
*
|
||||||
|
@ -174,12 +185,13 @@ void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr);
|
||||||
* \param interface_ptr interface
|
* \param interface_ptr interface
|
||||||
* \param pan_id PAD ID
|
* \param pan_id PAD ID
|
||||||
* \param network_name network name
|
* \param network_name network name
|
||||||
|
* \param updated data has been updated
|
||||||
*
|
*
|
||||||
* \return < 0 failure
|
* \return < 0 failure
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
|
int8_t ws_pae_auth_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, bool updated);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_auth_gtk_hash_set GTK hash set callback
|
* ws_pae_auth_gtk_hash_set GTK hash set callback
|
||||||
|
@ -227,6 +239,15 @@ typedef void ws_pae_auth_nw_key_index_set(protocol_interface_info_entry_t *inter
|
||||||
*/
|
*/
|
||||||
typedef void ws_pae_auth_nw_info_updated(protocol_interface_info_entry_t *interface_ptr);
|
typedef void ws_pae_auth_nw_info_updated(protocol_interface_info_entry_t *interface_ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ws_pae_auth_ip_addr_get gets IP addressing information related to KMP
|
||||||
|
*
|
||||||
|
* \param interface_ptr interface
|
||||||
|
* \param address IP address
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef void ws_pae_auth_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_auth_cb_register register PAE authenticator callbacks
|
* ws_pae_auth_cb_register register PAE authenticator callbacks
|
||||||
*
|
*
|
||||||
|
@ -235,17 +256,18 @@ typedef void ws_pae_auth_nw_info_updated(protocol_interface_info_entry_t *interf
|
||||||
* \param nw_key_insert network key index callback
|
* \param nw_key_insert network key index callback
|
||||||
* \param nw_key_index_set network send key index callback
|
* \param nw_key_index_set network send key index callback
|
||||||
* \param nw_info_updated network keys updated callback
|
* \param nw_info_updated network keys updated callback
|
||||||
|
* \param ip_addr_get IP addressing information callback
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated);
|
void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define ws_pae_auth_init(interface_ptr, gtks, next_gtks, certs, sec_timer_cfg, sec_prot_cfg) 1
|
#define ws_pae_auth_init(interface_ptr, next_gtks, certs, sec_cfg, sec_keys_nw_info) 1
|
||||||
#define ws_pae_auth_timing_adjust(timing)
|
#define ws_pae_auth_timing_adjust(timing)
|
||||||
#define ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) 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_delete NULL
|
||||||
#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set, nw_info_updated) {(void) hash_set;}
|
#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set, nw_info_updated, ip_addr_get) {(void) hash_set;}
|
||||||
#define ws_pae_auth_start(interface_ptr)
|
#define ws_pae_auth_start(interface_ptr)
|
||||||
#define ws_pae_auth_gtks_updated NULL
|
#define ws_pae_auth_gtks_updated NULL
|
||||||
#define ws_pae_auth_nw_key_index_update NULL
|
#define ws_pae_auth_nw_key_index_update NULL
|
||||||
|
@ -256,6 +278,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
|
||||||
#define ws_pae_auth_forced_gc(interface_ptr)
|
#define ws_pae_auth_forced_gc(interface_ptr)
|
||||||
#define ws_pae_auth_fast_timer NULL
|
#define ws_pae_auth_fast_timer NULL
|
||||||
#define ws_pae_auth_slow_timer NULL
|
#define ws_pae_auth_slow_timer NULL
|
||||||
|
#define ws_pae_auth_radius_address_set(interface_ptr, remote_addr) -1
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ typedef int8_t ws_pae_br_addr_read(protocol_interface_info_entry_t *interface_pt
|
||||||
typedef void ws_pae_gtks_updated(protocol_interface_info_entry_t *interface_ptr);
|
typedef void ws_pae_gtks_updated(protocol_interface_info_entry_t *interface_ptr);
|
||||||
typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
|
typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
|
||||||
typedef int8_t ws_pae_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
typedef int8_t ws_pae_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
|
||||||
typedef int8_t ws_pae_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
|
typedef int8_t ws_pae_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, bool updated);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t gtk[GTK_LEN]; /**< GTK key */
|
uint8_t gtk[GTK_LEN]; /**< GTK key */
|
||||||
|
@ -75,8 +75,7 @@ typedef struct {
|
||||||
uint16_t frame_cnt_store_timer; /**< Timer to check if storing of frame counter value is needed */
|
uint16_t frame_cnt_store_timer; /**< Timer to check if storing of frame counter value is needed */
|
||||||
uint32_t frame_cnt_store_force_timer; /**< Timer to force storing of frame counter, if no other updates */
|
uint32_t frame_cnt_store_force_timer; /**< Timer to force storing of frame counter, if no other updates */
|
||||||
frame_counters_t frame_counters; /**< Frame counters */
|
frame_counters_t frame_counters; /**< Frame counters */
|
||||||
sec_timer_cfg_t sec_timer_cfg; /**< Timer configuration (configuration set values) */
|
sec_cfg_t sec_cfg; /**< Security configuration (configuration set values) */
|
||||||
sec_prot_cfg_t sec_prot_cfg; /**< Configuration */
|
|
||||||
uint32_t restart_cnt; /**< Re-start counter */
|
uint32_t restart_cnt; /**< Re-start counter */
|
||||||
protocol_interface_info_entry_t *interface_ptr; /**< List link entry */
|
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_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */
|
||||||
|
@ -88,6 +87,7 @@ typedef struct {
|
||||||
ws_pae_controller_pan_ver_increment *pan_ver_increment; /**< PAN version increment callback */
|
ws_pae_controller_pan_ver_increment *pan_ver_increment; /**< PAN version increment callback */
|
||||||
ws_pae_controller_nw_info_updated *nw_info_updated; /**< Network information updated callback */
|
ws_pae_controller_nw_info_updated *nw_info_updated; /**< Network information updated callback */
|
||||||
ws_pae_controller_auth_next_target *auth_next_target; /**< Authentication next target callback */
|
ws_pae_controller_auth_next_target *auth_next_target; /**< Authentication next target callback */
|
||||||
|
ws_pae_controller_ip_addr_get *ip_addr_get; /**< IP address get callback */
|
||||||
ws_pae_delete *pae_delete; /**< PAE delete callback */
|
ws_pae_delete *pae_delete; /**< PAE delete callback */
|
||||||
ws_pae_timer *pae_fast_timer; /**< PAE fast timer callback */
|
ws_pae_timer *pae_fast_timer; /**< PAE fast timer callback */
|
||||||
ws_pae_timer *pae_slow_timer; /**< PAE slow timer callback */
|
ws_pae_timer *pae_slow_timer; /**< PAE slow timer callback */
|
||||||
|
@ -102,6 +102,7 @@ typedef struct {
|
||||||
bool gtkhash_set : 1; /**< GTK hashes are set */
|
bool gtkhash_set : 1; /**< GTK hashes are set */
|
||||||
bool key_index_set : 1; /**< NW key index is set */
|
bool key_index_set : 1; /**< NW key index is set */
|
||||||
bool frame_counter_read : 1; /**< Frame counters has been read */
|
bool frame_counter_read : 1; /**< Frame counters has been read */
|
||||||
|
bool auth_started : 1; /**< Authenticator has been started */
|
||||||
} pae_controller_t;
|
} pae_controller_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -112,12 +113,15 @@ typedef struct {
|
||||||
|
|
||||||
static void ws_pae_controller_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_keys_nw_info, sec_prot_gtk_keys_t *gtks);
|
static void ws_pae_controller_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_keys_nw_info, sec_prot_gtk_keys_t *gtks);
|
||||||
static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entry_t *interface_ptr);
|
static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entry_t *interface_ptr);
|
||||||
|
#ifdef HAVE_PAE_AUTH
|
||||||
|
static void ws_pae_controller_auth_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address);
|
||||||
|
#endif
|
||||||
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
|
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
|
||||||
static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry);
|
static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry);
|
||||||
static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry);
|
static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry);
|
||||||
static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool use_threshold);
|
static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool use_threshold);
|
||||||
static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_t *tlv_entry);
|
static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_t *tlv_entry);
|
||||||
static int8_t ws_pae_controller_nvm_frame_counter_read(uint32_t *restart_cnt, uint64_t *stored_time, frame_counters_t *counters);
|
static int8_t ws_pae_controller_nvm_frame_counter_read(uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters);
|
||||||
static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id);
|
static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id);
|
||||||
static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
|
static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
|
||||||
static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
|
static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
|
||||||
|
@ -147,6 +151,8 @@ pae_controller_config_t pae_controller_config = {
|
||||||
.ext_cert_valid_enabled = false
|
.ext_cert_valid_enabled = false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sec_radius_cfg_t *pae_controller_radius_settings;
|
||||||
|
|
||||||
int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr)
|
int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr)
|
||||||
{
|
{
|
||||||
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||||
|
@ -211,11 +217,28 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pae_controller_radius_settings) {
|
||||||
|
// If either address or password is set, both must be set
|
||||||
|
if (controller->sec_cfg.radius_cfg.radius_addr_set || controller->sec_cfg.radius_cfg.radius_shared_secret_len > 0) {
|
||||||
|
if (!controller->sec_cfg.radius_cfg.radius_addr_set) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (controller->sec_cfg.radius_cfg.radius_shared_secret_len == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ws_pae_auth_radius_address_set(interface_ptr, controller->sec_cfg.radius_cfg.radius_addr) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pae_controller_config.node_limit_set) {
|
if (pae_controller_config.node_limit_set) {
|
||||||
ws_pae_auth_node_limit_set(controller->interface_ptr, pae_controller_config.node_limit);
|
ws_pae_auth_node_limit_set(controller->interface_ptr, pae_controller_config.node_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set, ws_pae_controller_nw_info_updated_check);
|
ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set, ws_pae_controller_nw_info_updated_check, ws_pae_controller_auth_ip_addr_get);
|
||||||
|
|
||||||
|
controller->auth_started = true;
|
||||||
|
|
||||||
ws_pae_auth_start(interface_ptr);
|
ws_pae_auth_start(interface_ptr);
|
||||||
|
|
||||||
|
@ -245,6 +268,21 @@ int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t ws_pae_controller_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_ip_addr_get *ip_addr_get)
|
||||||
|
{
|
||||||
|
if (!interface_ptr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||||
|
if (!controller) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->ip_addr_get = ip_addr_get;
|
||||||
|
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)
|
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) {
|
if (!interface_ptr) {
|
||||||
|
@ -276,7 +314,7 @@ static void ws_pae_controller_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_key
|
||||||
sec_keys_nw_info->updated = false;
|
sec_keys_nw_info->updated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name)
|
int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, uint16_t pan_version, char *network_name)
|
||||||
{
|
{
|
||||||
(void) pan_id;
|
(void) pan_id;
|
||||||
(void) network_name;
|
(void) network_name;
|
||||||
|
@ -290,20 +328,27 @@ int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool updated = false;
|
||||||
|
|
||||||
// Network name has been modified
|
// Network name has been modified
|
||||||
if (network_name && strncmp(controller->sec_keys_nw_info.network_name, network_name, 33) != 0) {
|
if (network_name && strcmp(controller->sec_keys_nw_info.network_name, network_name) != 0) {
|
||||||
strncpy(controller->sec_keys_nw_info.network_name, network_name, 32);
|
strncpy(controller->sec_keys_nw_info.network_name, network_name, 32);
|
||||||
controller->sec_keys_nw_info.updated = true;
|
controller->sec_keys_nw_info.updated = true;
|
||||||
|
updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PAN ID has been modified
|
// PAN ID has been modified
|
||||||
if (pan_id != 0xffff && pan_id != controller->sec_keys_nw_info.new_pan_id) {
|
if (pan_id != 0xffff && pan_id != controller->sec_keys_nw_info.new_pan_id) {
|
||||||
controller->sec_keys_nw_info.new_pan_id = pan_id;
|
controller->sec_keys_nw_info.new_pan_id = pan_id;
|
||||||
controller->sec_keys_nw_info.updated = true;
|
controller->sec_keys_nw_info.updated = true;
|
||||||
|
updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store pan version
|
||||||
|
controller->sec_keys_nw_info.pan_version = pan_version;
|
||||||
|
|
||||||
if (controller->pae_nw_info_set) {
|
if (controller->pae_nw_info_set) {
|
||||||
controller->pae_nw_info_set(interface_ptr, pan_id, network_name);
|
controller->pae_nw_info_set(interface_ptr, pan_id, network_name, updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -327,6 +372,22 @@ static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PAE_AUTH
|
||||||
|
static void ws_pae_controller_auth_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address)
|
||||||
|
{
|
||||||
|
if (!interface_ptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
|
||||||
|
if (!controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller->ip_addr_get(interface_ptr, address);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid)
|
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid)
|
||||||
{
|
{
|
||||||
if (!interface_ptr) {
|
if (!interface_ptr) {
|
||||||
|
@ -606,8 +667,7 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
|
||||||
controller->nw_info_updated = NULL;
|
controller->nw_info_updated = NULL;
|
||||||
controller->auth_next_target = NULL;
|
controller->auth_next_target = NULL;
|
||||||
|
|
||||||
memset(&controller->sec_timer_cfg, 0, sizeof(ws_sec_timer_cfg_t));
|
memset(&controller->sec_cfg, 0, sizeof(sec_cfg_t));
|
||||||
memset(&controller->sec_prot_cfg, 0, sizeof(sec_prot_cfg_t));
|
|
||||||
|
|
||||||
ws_pae_controller_data_init(controller);
|
ws_pae_controller_data_init(controller);
|
||||||
|
|
||||||
|
@ -624,24 +684,28 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sec_prot_cfg) {
|
if (sec_prot_cfg) {
|
||||||
controller->sec_prot_cfg.sec_prot_trickle_params.Imin = sec_prot_cfg->sec_prot_trickle_imin * 10;
|
controller->sec_cfg.prot_cfg.sec_prot_trickle_params.Imin = sec_prot_cfg->sec_prot_trickle_imin * 10;
|
||||||
controller->sec_prot_cfg.sec_prot_trickle_params.Imax = sec_prot_cfg->sec_prot_trickle_imax * 10;
|
controller->sec_cfg.prot_cfg.sec_prot_trickle_params.Imax = sec_prot_cfg->sec_prot_trickle_imax * 10;
|
||||||
controller->sec_prot_cfg.sec_prot_trickle_params.k = 0;
|
controller->sec_cfg.prot_cfg.sec_prot_trickle_params.k = 0;
|
||||||
controller->sec_prot_cfg.sec_prot_trickle_params.TimerExpirations = sec_prot_cfg->sec_prot_trickle_timer_exp;
|
controller->sec_cfg.prot_cfg.sec_prot_trickle_params.TimerExpirations = sec_prot_cfg->sec_prot_trickle_timer_exp;
|
||||||
controller->sec_prot_cfg.sec_prot_retry_timeout = sec_prot_cfg->sec_prot_retry_timeout * 10;
|
controller->sec_cfg.prot_cfg.sec_prot_retry_timeout = sec_prot_cfg->sec_prot_retry_timeout * 10;
|
||||||
|
|
||||||
controller->sec_prot_cfg.sec_max_ongoing_authentication = sec_prot_cfg->sec_max_ongoing_authentication;
|
controller->sec_cfg.prot_cfg.sec_max_ongoing_authentication = sec_prot_cfg->sec_max_ongoing_authentication;
|
||||||
|
|
||||||
controller->sec_prot_cfg.initial_key_retry_delay = sec_prot_cfg->initial_key_retry_delay;
|
controller->sec_cfg.prot_cfg.initial_key_retry_delay = sec_prot_cfg->initial_key_retry_delay;
|
||||||
controller->sec_prot_cfg.initial_key_trickle_params.Imin = sec_prot_cfg->initial_key_imin;
|
controller->sec_cfg.prot_cfg.initial_key_trickle_params.Imin = sec_prot_cfg->initial_key_imin;
|
||||||
controller->sec_prot_cfg.initial_key_trickle_params.Imax = sec_prot_cfg->initial_key_imax;
|
controller->sec_cfg.prot_cfg.initial_key_trickle_params.Imax = sec_prot_cfg->initial_key_imax;
|
||||||
controller->sec_prot_cfg.initial_key_trickle_params.k = 0;
|
controller->sec_cfg.prot_cfg.initial_key_trickle_params.k = 0;
|
||||||
controller->sec_prot_cfg.initial_key_trickle_params.TimerExpirations = 2;
|
controller->sec_cfg.prot_cfg.initial_key_trickle_params.TimerExpirations = 2;
|
||||||
controller->sec_prot_cfg.initial_key_retry_cnt = sec_prot_cfg->initial_key_retry_cnt;
|
controller->sec_cfg.prot_cfg.initial_key_retry_cnt = sec_prot_cfg->initial_key_retry_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sec_timer_cfg) {
|
if (sec_timer_cfg) {
|
||||||
ws_pae_timers_settings_init(&controller->sec_timer_cfg, sec_timer_cfg);
|
ws_pae_timers_settings_init(&controller->sec_cfg.timer_cfg, sec_timer_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pae_controller_radius_settings) {
|
||||||
|
controller->sec_cfg.radius_cfg = *pae_controller_radius_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -676,6 +740,7 @@ static void ws_pae_controller_data_init(pae_controller_t *controller)
|
||||||
controller->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL;
|
controller->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL;
|
||||||
controller->frame_cnt_store_force_timer = FRAME_COUNTER_STORE_FORCE_INTERVAL;
|
controller->frame_cnt_store_force_timer = FRAME_COUNTER_STORE_FORCE_INTERVAL;
|
||||||
controller->restart_cnt = 0;
|
controller->restart_cnt = 0;
|
||||||
|
controller->auth_started = false;
|
||||||
ws_pae_controller_frame_counter_reset(&controller->frame_counters);
|
ws_pae_controller_frame_counter_reset(&controller->frame_counters);
|
||||||
sec_prot_keys_gtks_init(&controller->gtks);
|
sec_prot_keys_gtks_init(&controller->gtks);
|
||||||
sec_prot_keys_gtks_init(&controller->next_gtks);
|
sec_prot_keys_gtks_init(&controller->next_gtks);
|
||||||
|
@ -696,7 +761,7 @@ static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller)
|
||||||
uint64_t stored_time = 0;
|
uint64_t stored_time = 0;
|
||||||
|
|
||||||
// Read frame counters
|
// Read frame counters
|
||||||
if (ws_pae_controller_nvm_frame_counter_read(&controller->restart_cnt, &stored_time, &controller->frame_counters) >= 0) {
|
if (ws_pae_controller_nvm_frame_counter_read(&controller->restart_cnt, &stored_time, &controller->sec_keys_nw_info.pan_version, &controller->frame_counters) >= 0) {
|
||||||
// Current time is not valid
|
// Current time is not valid
|
||||||
if (ws_pae_current_time_set(stored_time) < 0) {
|
if (ws_pae_current_time_set(stored_time) < 0) {
|
||||||
ret_value = -1;
|
ret_value = -1;
|
||||||
|
@ -704,6 +769,9 @@ static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller)
|
||||||
// This is used to ensure that PMK replay counters are fresh after each re-start.
|
// This is used to ensure that PMK replay counters are fresh after each re-start.
|
||||||
controller->restart_cnt++;
|
controller->restart_cnt++;
|
||||||
|
|
||||||
|
// Increments PAN version to ensure that it is fresh
|
||||||
|
controller->sec_keys_nw_info.pan_version += PAN_VERSION_STORAGE_READ_INCREMENT;
|
||||||
|
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
// Checks frame counters
|
// Checks frame counters
|
||||||
for (uint8_t index = 0; index < GTK_NUM; index++) {
|
for (uint8_t index = 0; index < GTK_NUM; index++) {
|
||||||
|
@ -720,7 +788,7 @@ static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller)
|
||||||
}
|
}
|
||||||
if (updated) {
|
if (updated) {
|
||||||
// Writes incremented frame counters
|
// Writes incremented frame counters
|
||||||
ws_pae_nvm_store_frame_counter_tlv_create((nvm_tlv_t *) &controller->pae_nvm_buffer, controller->restart_cnt, &controller->frame_counters);
|
ws_pae_nvm_store_frame_counter_tlv_create((nvm_tlv_t *) &controller->pae_nvm_buffer, controller->restart_cnt, controller->sec_keys_nw_info.pan_version, &controller->frame_counters);
|
||||||
ws_pae_controller_nvm_frame_counter_write((nvm_tlv_t *) &controller->pae_nvm_buffer);
|
ws_pae_controller_nvm_frame_counter_write((nvm_tlv_t *) &controller->pae_nvm_buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -792,7 +860,7 @@ int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_pt
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ws_pae_supp_init(controller->interface_ptr, &controller->certs, &controller->sec_timer_cfg, &controller->sec_prot_cfg, &controller->sec_keys_nw_info) < 0) {
|
if (ws_pae_supp_init(controller->interface_ptr, &controller->certs, &controller->sec_cfg, &controller->sec_keys_nw_info) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,7 +871,7 @@ int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_pt
|
||||||
controller->pae_br_addr_read = ws_pae_supp_border_router_addr_read;
|
controller->pae_br_addr_read = ws_pae_supp_border_router_addr_read;
|
||||||
controller->pae_gtk_hash_update = ws_pae_supp_gtk_hash_update;
|
controller->pae_gtk_hash_update = ws_pae_supp_gtk_hash_update;
|
||||||
controller->pae_nw_key_index_update = ws_pae_supp_nw_key_index_update;
|
controller->pae_nw_key_index_update = ws_pae_supp_nw_key_index_update;
|
||||||
controller->pae_nw_info_set = NULL;
|
controller->pae_nw_info_set = ws_pae_supp_nw_info_set;
|
||||||
|
|
||||||
ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, controller->auth_next_target, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set, ws_pae_controller_gtk_hash_ptr_get, ws_pae_controller_nw_info_updated_check);
|
ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, controller->auth_next_target, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set, ws_pae_controller_gtk_hash_ptr_get, ws_pae_controller_nw_info_updated_check);
|
||||||
|
|
||||||
|
@ -822,7 +890,7 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ws_pae_auth_init(controller->interface_ptr, &controller->next_gtks, &controller->certs, &controller->sec_timer_cfg, &controller->sec_prot_cfg, &controller->sec_keys_nw_info) < 0) {
|
if (ws_pae_auth_init(controller->interface_ptr, &controller->next_gtks, &controller->certs, &controller->sec_cfg, &controller->sec_keys_nw_info) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -855,7 +923,7 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt
|
||||||
/* If network information i.e pan_id and network name exists updates bootstrap with it,
|
/* If network information i.e pan_id and network name exists updates bootstrap with it,
|
||||||
(in case already configured by application then no changes are made) */
|
(in case already configured by application then no changes are made) */
|
||||||
if (controller->nw_info_updated) {
|
if (controller->nw_info_updated) {
|
||||||
controller->nw_info_updated(interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name);
|
controller->nw_info_updated(interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.pan_version, controller->sec_keys_nw_info.network_name);
|
||||||
}
|
}
|
||||||
if (!read_gtks_to || sec_prot_keys_gtk_count(read_gtks_to) == 0) {
|
if (!read_gtks_to || sec_prot_keys_gtk_count(read_gtks_to) == 0) {
|
||||||
// Key material invalid or GTKs are expired, delete GTKs from NVM
|
// Key material invalid or GTKs are expired, delete GTKs from NVM
|
||||||
|
@ -1103,6 +1171,130 @@ int8_t ws_pae_controller_certificate_revocation_list_remove(const arm_cert_revoc
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t ws_pae_controller_radius_address_set(int8_t interface_id, const uint8_t *address)
|
||||||
|
{
|
||||||
|
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||||
|
|
||||||
|
// If remote address is not set, clear radius information
|
||||||
|
if (!address) {
|
||||||
|
if (pae_controller_radius_settings != NULL) {
|
||||||
|
pae_controller_radius_settings->radius_addr_set = false;
|
||||||
|
}
|
||||||
|
if (controller) {
|
||||||
|
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pae_controller_radius_settings == NULL) {
|
||||||
|
pae_controller_radius_settings = ns_dyn_mem_alloc(sizeof(sec_radius_cfg_t));
|
||||||
|
if (!pae_controller_radius_settings) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(pae_controller_radius_settings, 0, sizeof(sec_radius_cfg_t));
|
||||||
|
}
|
||||||
|
memcpy(pae_controller_radius_settings->radius_addr, address, 16);
|
||||||
|
pae_controller_radius_settings->radius_addr_set = true;
|
||||||
|
|
||||||
|
if (controller) {
|
||||||
|
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
|
||||||
|
if (ws_pae_auth_radius_address_set(controller->interface_ptr, controller->sec_cfg.radius_cfg.radius_addr) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t ws_pae_controller_radius_address_get(int8_t interface_id, uint8_t *address)
|
||||||
|
{
|
||||||
|
(void) interface_id;
|
||||||
|
|
||||||
|
if (address == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pae_controller_radius_settings == NULL || !pae_controller_radius_settings->radius_addr_set) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(address, pae_controller_radius_settings->radius_addr, 16);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t ws_pae_controller_radius_shared_secret_set(int8_t interface_id, const uint16_t shared_secret_len, const uint8_t *shared_secret)
|
||||||
|
{
|
||||||
|
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
|
||||||
|
|
||||||
|
// If shared secret is not set, clear radius information
|
||||||
|
if (shared_secret_len == 0 || !shared_secret) {
|
||||||
|
if (pae_controller_radius_settings != NULL) {
|
||||||
|
memset(pae_controller_radius_settings->radius_shared_secret, 0, pae_controller_radius_settings->radius_shared_secret_len);
|
||||||
|
pae_controller_radius_settings->radius_shared_secret_len = 0;
|
||||||
|
}
|
||||||
|
if (controller) {
|
||||||
|
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pae_controller_radius_settings == NULL) {
|
||||||
|
pae_controller_radius_settings = ns_dyn_mem_alloc(sizeof(sec_radius_cfg_t));
|
||||||
|
if (!pae_controller_radius_settings) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(pae_controller_radius_settings, 0, sizeof(sec_radius_cfg_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pae_controller_radius_settings->radius_shared_secret != NULL &&
|
||||||
|
pae_controller_radius_settings->radius_shared_secret_len != shared_secret_len) {
|
||||||
|
ns_dyn_mem_free(pae_controller_radius_settings->radius_shared_secret);
|
||||||
|
pae_controller_radius_settings->radius_shared_secret = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pae_controller_radius_settings->radius_shared_secret == NULL) {
|
||||||
|
pae_controller_radius_settings->radius_shared_secret = ns_dyn_mem_alloc(shared_secret_len);
|
||||||
|
if (pae_controller_radius_settings->radius_shared_secret == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pae_controller_radius_settings->radius_shared_secret, shared_secret, shared_secret_len);
|
||||||
|
pae_controller_radius_settings->radius_shared_secret_len = shared_secret_len;
|
||||||
|
|
||||||
|
if (controller) {
|
||||||
|
ws_pae_controller_configure(controller->interface_ptr, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t ws_pae_controller_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret_len, uint8_t *shared_secret)
|
||||||
|
{
|
||||||
|
(void) interface_id;
|
||||||
|
|
||||||
|
if (shared_secret_len == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t length = 0;
|
||||||
|
if (pae_controller_radius_settings != NULL) {
|
||||||
|
length = pae_controller_radius_settings->radius_shared_secret_len;
|
||||||
|
if (shared_secret != NULL) {
|
||||||
|
if (length > *shared_secret_len) {
|
||||||
|
length = *shared_secret_len;
|
||||||
|
}
|
||||||
|
if (length > 0 && pae_controller_radius_settings->radius_shared_secret != NULL) {
|
||||||
|
memcpy(shared_secret, pae_controller_radius_settings->radius_shared_secret, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*shared_secret_len = length;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
|
int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
|
||||||
{
|
{
|
||||||
if (!eui_64) {
|
if (!eui_64) {
|
||||||
|
@ -1165,7 +1357,7 @@ int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[GTK_NUM])
|
||||||
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
for (uint8_t i = 0; i < GTK_NUM; i++) {
|
||||||
if (gtk[i]) {
|
if (gtk[i]) {
|
||||||
uint32_t lifetime = sec_prot_keys_gtk_install_order_last_lifetime_get(&controller->gtks);
|
uint32_t lifetime = sec_prot_keys_gtk_install_order_last_lifetime_get(&controller->gtks);
|
||||||
lifetime += controller->sec_timer_cfg.gtk_expire_offset;
|
lifetime += controller->sec_cfg.timer_cfg.gtk_expire_offset;
|
||||||
if (sec_prot_keys_gtk_set(&controller->gtks, i, gtk[i], lifetime) >= 0) {
|
if (sec_prot_keys_gtk_set(&controller->gtks, i, gtk[i], lifetime) >= 0) {
|
||||||
controller->gtks_set = true;
|
controller->gtks_set = true;
|
||||||
tr_info("GTK set index: %i, lifetime %"PRIu32", system time: %"PRIu32"", i, lifetime, protocol_core_monotonic_time / 10);
|
tr_info("GTK set index: %i, lifetime %"PRIu32", system time: %"PRIu32"", i, lifetime, protocol_core_monotonic_time / 10);
|
||||||
|
@ -1446,7 +1638,7 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool
|
||||||
if (update_needed || entry->frame_cnt_store_force_timer == 0) {
|
if (update_needed || entry->frame_cnt_store_force_timer == 0) {
|
||||||
tr_debug("Write frame counters: system time %"PRIu32"", protocol_core_monotonic_time / 10);
|
tr_debug("Write frame counters: system time %"PRIu32"", protocol_core_monotonic_time / 10);
|
||||||
// Writes modified frame counters
|
// Writes modified frame counters
|
||||||
ws_pae_nvm_store_frame_counter_tlv_create((nvm_tlv_t *) &entry->pae_nvm_buffer, entry->restart_cnt, &entry->frame_counters);
|
ws_pae_nvm_store_frame_counter_tlv_create((nvm_tlv_t *) &entry->pae_nvm_buffer, entry->restart_cnt, entry->sec_keys_nw_info.pan_version, &entry->frame_counters);
|
||||||
ws_pae_controller_nvm_frame_counter_write((nvm_tlv_t *) &entry->pae_nvm_buffer);
|
ws_pae_controller_nvm_frame_counter_write((nvm_tlv_t *) &entry->pae_nvm_buffer);
|
||||||
|
|
||||||
// Reset force interval when ever values are stored
|
// Reset force interval when ever values are stored
|
||||||
|
@ -1454,7 +1646,7 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int8_t ws_pae_controller_nvm_frame_counter_read(uint32_t *restart_cnt, uint64_t *stored_time, frame_counters_t *counters)
|
static int8_t ws_pae_controller_nvm_frame_counter_read(uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters)
|
||||||
{
|
{
|
||||||
nvm_tlv_t *tlv = ws_pae_nvm_store_generic_tlv_allocate_and_create(
|
nvm_tlv_t *tlv = ws_pae_nvm_store_generic_tlv_allocate_and_create(
|
||||||
PAE_NVM_FRAME_COUNTER_TAG, PAE_NVM_FRAME_COUNTER_LEN);
|
PAE_NVM_FRAME_COUNTER_TAG, PAE_NVM_FRAME_COUNTER_LEN);
|
||||||
|
@ -1467,7 +1659,7 @@ static int8_t ws_pae_controller_nvm_frame_counter_read(uint32_t *restart_cnt, ui
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ws_pae_nvm_store_frame_counter_tlv_read(tlv, restart_cnt, stored_time, counters) < 0) {
|
if (ws_pae_nvm_store_frame_counter_tlv_read(tlv, restart_cnt, stored_time, pan_version, counters) < 0) {
|
||||||
ws_pae_nvm_store_generic_tlv_free(tlv);
|
ws_pae_nvm_store_generic_tlv_free(tlv);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,18 +232,69 @@ int8_t ws_pae_controller_certificate_revocation_list_add(const arm_cert_revocati
|
||||||
*/
|
*/
|
||||||
int8_t ws_pae_controller_certificate_revocation_list_remove(const arm_cert_revocation_list_entry_s *crl);
|
int8_t ws_pae_controller_certificate_revocation_list_remove(const arm_cert_revocation_list_entry_s *crl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ws_pae_controller_radius_address_set set radius address
|
||||||
|
*
|
||||||
|
* \param interface_id interface identifier
|
||||||
|
* \param address address
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t ws_pae_controller_radius_address_set(int8_t interface_id, const uint8_t *address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ws_pae_controller_radius_address_set get radius address
|
||||||
|
*
|
||||||
|
* \param interface_id interface identifier
|
||||||
|
* \param address address buffer where to write address, must have space at least for 39 characters and NUL terminator
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t ws_pae_controller_radius_address_get(int8_t interface_id, uint8_t *address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ws_pae_controller_radius_shared_secret_set set radius shared secret
|
||||||
|
*
|
||||||
|
* \param interface_id interface identifier
|
||||||
|
* \param shared_secret_len shared secret length
|
||||||
|
* \param shared_secret shared secret
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t ws_pae_controller_radius_shared_secret_set(int8_t interface_id, const uint16_t shared_secret_len, const uint8_t *shared_secret);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ws_pae_controller_radius_shared_secret_get get radius shared secret
|
||||||
|
*
|
||||||
|
* \param interface_id interface identifier
|
||||||
|
* \param shared_secret_len On call, shared secret buffer length, on return shared secret length
|
||||||
|
* \param shared_secret shared secret
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t ws_pae_controller_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret_len, uint8_t *shared_secret);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_controller_nw_info_set set network information
|
* ws_pae_controller_nw_info_set set network information
|
||||||
*
|
*
|
||||||
* \param interface_ptr interface
|
* \param interface_ptr interface
|
||||||
* \param pan_id PAD ID
|
* \param pan_id PAD ID
|
||||||
|
* \param pan_version PAN version
|
||||||
* \param network_name network name
|
* \param network_name network name
|
||||||
*
|
*
|
||||||
* \return < 0 failure
|
* \return < 0 failure
|
||||||
* \return >= 0 success
|
* \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);
|
int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, uint16_t pan_version, char *network_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_controller_nw_key_valid network key is valid i.e. used successfully on bootstrap
|
* ws_pae_controller_nw_key_valid network key is valid i.e. used successfully on bootstrap
|
||||||
|
@ -518,13 +569,14 @@ typedef void ws_pae_controller_pan_ver_increment(protocol_interface_info_entry_t
|
||||||
*
|
*
|
||||||
* \param interface_ptr interface
|
* \param interface_ptr interface
|
||||||
* \param pan_id PAN ID
|
* \param pan_id PAN ID
|
||||||
|
* \param pan_version PAN version
|
||||||
* \param network_name network name
|
* \param network_name network name
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
|
typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, uint16_t pan_version, char *network_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_controller_cb_register register PEA controller callbacks
|
* ws_pae_controller_cb_register register controller callbacks
|
||||||
*
|
*
|
||||||
* \param interface_ptr interface
|
* \param interface_ptr interface
|
||||||
* \param completed authentication completed callback
|
* \param completed authentication completed callback
|
||||||
|
@ -543,6 +595,30 @@ typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t *
|
||||||
*/
|
*/
|
||||||
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated);
|
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ws_pae_controller_ip_addr_get gets IP addressing information
|
||||||
|
*
|
||||||
|
* \param interface_ptr interface
|
||||||
|
* \param address IP address
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef int8_t ws_pae_controller_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ws_pae_controller_auth_cb_register register authenticator callbacks
|
||||||
|
*
|
||||||
|
* \param interface_ptr interface
|
||||||
|
* \param ip_addr_get IP address get callback
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t ws_pae_controller_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_ip_addr_get *ip_addr_get);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_controller_fast_timer PAE controller fast timer call
|
* ws_pae_controller_fast_timer PAE controller fast timer call
|
||||||
*
|
*
|
||||||
|
|
|
@ -419,6 +419,19 @@ uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)
|
||||||
return kmp_count;
|
return kmp_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const void *pdu, uint16_t size)
|
||||||
|
{
|
||||||
|
ns_list_foreach(supp_entry_t, entry, supp_list) {
|
||||||
|
ns_list_foreach(kmp_entry_t, kmp_entry, &entry->kmp_list) {
|
||||||
|
if (kmp_api_receive_check(kmp_entry->kmp, pdu, size)) {
|
||||||
|
return kmp_entry->kmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list)
|
supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list)
|
||||||
{
|
{
|
||||||
supp_entry_t *retry_supp = NULL;
|
supp_entry_t *retry_supp = NULL;
|
||||||
|
|
|
@ -366,6 +366,18 @@ bool ws_pae_lib_supp_list_active_limit_reached(supp_list_t *active_supp_list, ui
|
||||||
*/
|
*/
|
||||||
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type);
|
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ws_pae_lib_supp_list_kmp_receive_check check if received message is for this KMP in a list of supplicants
|
||||||
|
*
|
||||||
|
* \param supp_list list of supplicants
|
||||||
|
* \param pdu pdu
|
||||||
|
* \param size pdu size
|
||||||
|
*
|
||||||
|
* \return KMP api for the received message
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const void *pdu, uint16_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_lib_supp_list_entry_retry_timer_get checks if some supplicant has retry timer running
|
* ws_pae_lib_supp_list_entry_retry_timer_get checks if some supplicant has retry timer running
|
||||||
*
|
*
|
||||||
|
|
|
@ -281,7 +281,7 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t restart_cnt, frame_counters_t *counters)
|
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t restart_cnt, uint16_t pan_version, frame_counters_t *counters)
|
||||||
{
|
{
|
||||||
tlv_entry->tag = PAE_NVM_FRAME_COUNTER_TAG;
|
tlv_entry->tag = PAE_NVM_FRAME_COUNTER_TAG;
|
||||||
tlv_entry->len = PAE_NVM_FRAME_COUNTER_LEN;
|
tlv_entry->len = PAE_NVM_FRAME_COUNTER_LEN;
|
||||||
|
@ -293,6 +293,8 @@ void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t re
|
||||||
uint64_t stored_time = ws_pae_current_time_get();
|
uint64_t stored_time = ws_pae_current_time_get();
|
||||||
tlv = common_write_64_bit(stored_time, tlv);
|
tlv = common_write_64_bit(stored_time, tlv);
|
||||||
|
|
||||||
|
tlv = common_write_16_bit(pan_version, tlv);
|
||||||
|
|
||||||
for (uint8_t index = 0; index < GTK_NUM; index++) {
|
for (uint8_t index = 0; index < GTK_NUM; index++) {
|
||||||
if (!counters->counter[index].set) {
|
if (!counters->counter[index].set) {
|
||||||
*tlv++ = PAE_NVM_FIELD_NOT_SET;
|
*tlv++ = PAE_NVM_FIELD_NOT_SET;
|
||||||
|
@ -309,7 +311,7 @@ void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t re
|
||||||
tr_debug("NVM FRAME COUNTER write");
|
tr_debug("NVM FRAME COUNTER write");
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, frame_counters_t *counters)
|
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters)
|
||||||
{
|
{
|
||||||
if (!tlv_entry || !counters) {
|
if (!tlv_entry || !counters) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -327,6 +329,9 @@ int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_t *tlv_entry, uint32_t *r
|
||||||
*stored_time = common_read_64_bit(tlv);
|
*stored_time = common_read_64_bit(tlv);
|
||||||
tlv += 8;
|
tlv += 8;
|
||||||
|
|
||||||
|
*pan_version = common_read_16_bit(tlv);
|
||||||
|
tlv += 2;
|
||||||
|
|
||||||
for (uint8_t index = 0; index < GTK_NUM; index++) {
|
for (uint8_t index = 0; index < GTK_NUM; index++) {
|
||||||
// Frame counter not set
|
// Frame counter not set
|
||||||
if (*tlv++ == PAE_NVM_FIELD_NOT_SET) {
|
if (*tlv++ == PAE_NVM_FIELD_NOT_SET) {
|
||||||
|
|
|
@ -41,8 +41,8 @@
|
||||||
// PTK EUI-64 set (1) + PTK EUI-64 (8) + PMK set (1) + PMK lifetime (4) + PMK (32) + PMK replay counter (8) + PTK set (1) + PTK lifetime (4) + PTK (48)
|
// PTK EUI-64 set (1) + PTK EUI-64 (8) + PMK set (1) + PMK lifetime (4) + PMK (32) + PMK replay counter (8) + PTK set (1) + PTK lifetime (4) + PTK (48)
|
||||||
#define PAE_NVM_KEYS_LEN 1 + 8 + 1 + 4 + PMK_LEN + 8 + 1 + 4 + PTK_LEN
|
#define PAE_NVM_KEYS_LEN 1 + 8 + 1 + 4 + PMK_LEN + 8 + 1 + 4 + PTK_LEN
|
||||||
|
|
||||||
// restart counter + stored time + (frame counter set (1) + GTK (16) + frame counter (4)) * 4
|
// restart counter + stored time + pan version + (frame counter set (1) + GTK (16) + frame counter (4)) * 4
|
||||||
#define PAE_NVM_FRAME_COUNTER_LEN 4 + 8 + (1 + GTK_LEN + 4) * GTK_NUM
|
#define PAE_NVM_FRAME_COUNTER_LEN 4 + 8 + 2 + (1 + GTK_LEN + 4) * GTK_NUM
|
||||||
|
|
||||||
#define PAE_NVM_DEFAULT_BUFFER_SIZE sizeof(nvm_tlv_t) + PAE_NVM_NW_INFO_LEN
|
#define PAE_NVM_DEFAULT_BUFFER_SIZE sizeof(nvm_tlv_t) + PAE_NVM_NW_INFO_LEN
|
||||||
|
|
||||||
|
@ -119,10 +119,11 @@ int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_t *tlv_entry, sec_prot_keys_t *sec
|
||||||
*
|
*
|
||||||
* \param tlv_entry TLV buffer pointer
|
* \param tlv_entry TLV buffer pointer
|
||||||
* \param restart_cnt re-start counter
|
* \param restart_cnt re-start counter
|
||||||
|
* \param pan_version PAN version
|
||||||
* \param counters frame counters
|
* \param counters frame counters
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t restart_cnt, frame_counters_t *counters);
|
void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t restart_cnt, uint16_t pan_version, frame_counters_t *counters);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_nvm_store_frame_counter_tlv_read read from NVM frame counter TLV
|
* ws_pae_nvm_store_frame_counter_tlv_read read from NVM frame counter TLV
|
||||||
|
@ -130,13 +131,14 @@ void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_t *tlv_entry, uint32_t re
|
||||||
* \param tlv_entry TLV
|
* \param tlv_entry TLV
|
||||||
* \param restart_cnt re-start counter
|
* \param restart_cnt re-start counter
|
||||||
* \param stored_time stored timestampt
|
* \param stored_time stored timestampt
|
||||||
|
* \param pan_version PAN version
|
||||||
* \param counters frame counters
|
* \param counters frame counters
|
||||||
*
|
*
|
||||||
* \return < 0 failure
|
* \return < 0 failure
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, frame_counters_t *counters);
|
int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_t *tlv_entry, uint32_t *restart_cnt, uint64_t *stored_time, uint16_t *pan_version, frame_counters_t *counters);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_nvm_store_key_storage_index_tlv_create create NVM key storage index TLV
|
* ws_pae_nvm_store_key_storage_index_tlv_create create NVM key storage index TLV
|
||||||
|
|
|
@ -100,8 +100,7 @@ typedef struct {
|
||||||
uint8_t new_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap after bootstrap start */
|
uint8_t new_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap after bootstrap start */
|
||||||
uint8_t comp_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap after bootstrap completed */
|
uint8_t comp_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap after bootstrap completed */
|
||||||
sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */
|
sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */
|
||||||
sec_timer_cfg_t *sec_timer_cfg; /**< Timer configuration */
|
sec_cfg_t *sec_cfg; /**< Security configuration */
|
||||||
sec_prot_cfg_t *sec_prot_cfg; /**< Protocol Configuration */
|
|
||||||
uint8_t nw_keys_used_cnt; /**< How many times bootstrap has been tried with current keys */
|
uint8_t nw_keys_used_cnt; /**< How many times bootstrap has been tried with current keys */
|
||||||
uint8_t initial_key_retry_cnt; /**< initial EAPOL-Key retry counter */
|
uint8_t initial_key_retry_cnt; /**< initial EAPOL-Key retry counter */
|
||||||
bool auth_trickle_running : 1; /**< Initial EAPOL-Key Trickle timer running */
|
bool auth_trickle_running : 1; /**< Initial EAPOL-Key Trickle timer running */
|
||||||
|
@ -126,6 +125,7 @@ static void ws_pae_supp_free(pae_supp_t *pae_supp);
|
||||||
static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, auth_result_e result);
|
static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, auth_result_e result);
|
||||||
static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp);
|
static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp);
|
||||||
static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp);
|
static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp);
|
||||||
|
static int8_t ws_pae_supp_network_name_compare(char *name1, char *name2);
|
||||||
static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id, char *dest_network_name);
|
static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id, char *dest_network_name);
|
||||||
static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp);
|
static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp);
|
||||||
static pae_supp_t *ws_pae_supp_get(protocol_interface_info_entry_t *interface_ptr);
|
static pae_supp_t *ws_pae_supp_get(protocol_interface_info_entry_t *interface_ptr);
|
||||||
|
@ -142,7 +142,7 @@ static int8_t ws_pae_supp_timer_stop(pae_supp_t *pae_supp);
|
||||||
static bool ws_pae_supp_timer_running(pae_supp_t *pae_supp);
|
static bool ws_pae_supp_timer_running(pae_supp_t *pae_supp);
|
||||||
static void ws_pae_supp_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr);
|
static void ws_pae_supp_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_supp_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type);
|
static kmp_api_t *ws_pae_supp_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type);
|
||||||
static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr);
|
static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, const void *pdu, uint16_t size);
|
||||||
static kmp_api_t *ws_pae_supp_kmp_tx_status_ind(kmp_service_t *service, uint8_t instance_id);
|
static kmp_api_t *ws_pae_supp_kmp_tx_status_ind(kmp_service_t *service, uint8_t instance_id);
|
||||||
static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp);
|
static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp);
|
||||||
static int8_t ws_pae_supp_eapol_pdu_address_check(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
|
static int8_t ws_pae_supp_eapol_pdu_address_check(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
|
||||||
|
@ -200,7 +200,7 @@ int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr,
|
||||||
|
|
||||||
/* Network name or PAN ID has changed, delete key data associated with border router
|
/* Network name or PAN ID has changed, delete key data associated with border router
|
||||||
i.e PMK, PTK, EA-IE data (border router EUI-64) */
|
i.e PMK, PTK, EA-IE data (border router EUI-64) */
|
||||||
if (strcmp(pae_supp->sec_keys_nw_info->network_name, dest_network_name) != 0 ||
|
if (ws_pae_supp_network_name_compare(pae_supp->sec_keys_nw_info->network_name, dest_network_name) != 0 ||
|
||||||
(pae_supp->sec_keys_nw_info->key_pan_id != 0xFFFF && pae_supp->sec_keys_nw_info->key_pan_id != dest_pan_id)) {
|
(pae_supp->sec_keys_nw_info->key_pan_id != 0xFFFF && pae_supp->sec_keys_nw_info->key_pan_id != dest_pan_id)) {
|
||||||
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
|
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
|
||||||
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
|
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
|
||||||
|
@ -286,8 +286,9 @@ int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr,
|
||||||
|
|
||||||
/* If border router EUI-64 received on bootstrap complete does not match to
|
/* If border router EUI-64 received on bootstrap complete does not match to
|
||||||
EUI-64 stored with keys, delete keys */
|
EUI-64 stored with keys, delete keys */
|
||||||
if (memcmp(ptk_eui_64, pae_supp->comp_br_eui_64, 8) != 0) {
|
if (!ptk_eui_64 || memcmp(ptk_eui_64, pae_supp->comp_br_eui_64, 8) != 0) {
|
||||||
tr_warn("Delete keys: PTK EUI-64 %s does not match to BR EUI-64 %s", tr_array(ptk_eui_64, 8), tr_array(pae_supp->comp_br_eui_64, 8));
|
tr_warn("Delete keys: PTK EUI-64 %s does not match to BR EUI-64 %s",
|
||||||
|
ptk_eui_64 ? tr_array(ptk_eui_64, 8) : "", tr_array(pae_supp->comp_br_eui_64, 8));
|
||||||
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
|
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
|
||||||
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
|
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
|
||||||
sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys);
|
sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys);
|
||||||
|
@ -349,7 +350,7 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt
|
||||||
// Starts supplicant timer
|
// Starts supplicant timer
|
||||||
ws_pae_supp_timer_start(pae_supp);
|
ws_pae_supp_timer_start(pae_supp);
|
||||||
|
|
||||||
tr_info("GTK update start imin: %i, imax: %i, max mismatch: %i, tr time: %i", pae_supp->sec_timer_cfg->gtk_request_imin, pae_supp->sec_timer_cfg->gtk_request_imax, pae_supp->sec_timer_cfg->gtk_max_mismatch, pae_supp->auth_trickle_timer.t);
|
tr_info("GTK update start imin: %i, imax: %i, max mismatch: %i, tr time: %i", pae_supp->sec_cfg->timer_cfg.gtk_request_imin, pae_supp->sec_cfg->timer_cfg.gtk_request_imax, pae_supp->sec_cfg->timer_cfg.gtk_max_mismatch, pae_supp->auth_trickle_timer.t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,6 +489,14 @@ static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int8_t ws_pae_supp_network_name_compare(char *name1, char *name2)
|
||||||
|
{
|
||||||
|
if (strlen(name1) == strlen(name2) && strcmp(name1, name2) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id, char *dest_network_name)
|
static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id, char *dest_network_name)
|
||||||
{
|
{
|
||||||
// Checks how many times authentication has been tried with current network keys
|
// Checks how many times authentication has been tried with current network keys
|
||||||
|
@ -506,7 +515,7 @@ static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan
|
||||||
/* Checks if keys match to network name and PAN ID and that needed keys exists (PMK,
|
/* Checks if keys match to network name and PAN ID and that needed keys exists (PMK,
|
||||||
PTK and a GTK), and calls inserts function that will update the network keys as
|
PTK and a GTK), and calls inserts function that will update the network keys as
|
||||||
needed */
|
needed */
|
||||||
if ((strcmp(dest_network_name, pae_supp->sec_keys_nw_info->network_name) == 0 &&
|
if ((ws_pae_supp_network_name_compare(dest_network_name, pae_supp->sec_keys_nw_info->network_name) == 0 &&
|
||||||
pan_id == pae_supp->sec_keys_nw_info->key_pan_id) &&
|
pan_id == pae_supp->sec_keys_nw_info->key_pan_id) &&
|
||||||
(sec_prot_keys_gtk_count(pae_supp->sec_keys_nw_info->gtks) > 0) &&
|
(sec_prot_keys_gtk_count(pae_supp->sec_keys_nw_info->gtks) > 0) &&
|
||||||
(sec_prot_keys_pmk_get(&pae_supp->entry.sec_keys) != NULL) &&
|
(sec_prot_keys_pmk_get(&pae_supp->entry.sec_keys) != NULL) &&
|
||||||
|
@ -523,6 +532,31 @@ static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t ws_pae_supp_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, bool updated)
|
||||||
|
{
|
||||||
|
(void) pan_id;
|
||||||
|
(void) network_name;
|
||||||
|
|
||||||
|
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
|
||||||
|
if (!pae_supp) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updated) {
|
||||||
|
tr_info("Delete old keys, new PAN ID: %i network name: %s", pan_id, network_name);
|
||||||
|
// Delete pair wise keys
|
||||||
|
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
|
||||||
|
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
|
||||||
|
sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys);
|
||||||
|
// Delete GTKs
|
||||||
|
sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info->gtks);
|
||||||
|
sec_prot_keys_gtks_updated_set(pae_supp->sec_keys_nw_info->gtks);
|
||||||
|
ws_pae_supp_nvm_update(pae_supp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_auth_next_target *auth_next_target, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set, ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get, ws_pae_supp_nw_info_updated *nw_info_updated)
|
void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_auth_next_target *auth_next_target, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set, ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get, ws_pae_supp_nw_info_updated *nw_info_updated)
|
||||||
{
|
{
|
||||||
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
|
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
|
||||||
|
@ -538,7 +572,7 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
|
||||||
pae_supp->nw_info_updated = nw_info_updated;
|
pae_supp->nw_info_updated = nw_info_updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info)
|
int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info)
|
||||||
{
|
{
|
||||||
if (!interface_ptr) {
|
if (!interface_ptr) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -564,8 +598,7 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
|
||||||
pae_supp->nw_keys_used_cnt = 0;
|
pae_supp->nw_keys_used_cnt = 0;
|
||||||
pae_supp->initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
|
pae_supp->initial_key_retry_cnt = DEFAULT_INITIAL_KEY_RETRY_COUNT;
|
||||||
pae_supp->sec_keys_nw_info = sec_keys_nw_info;
|
pae_supp->sec_keys_nw_info = sec_keys_nw_info;
|
||||||
pae_supp->sec_timer_cfg = sec_timer_cfg;
|
pae_supp->sec_cfg = sec_cfg;
|
||||||
pae_supp->sec_prot_cfg = sec_prot_cfg;
|
|
||||||
pae_supp->auth_trickle_running = false;
|
pae_supp->auth_trickle_running = false;
|
||||||
pae_supp->auth_requested = false;
|
pae_supp->auth_requested = false;
|
||||||
pae_supp->timer_running = false;
|
pae_supp->timer_running = false;
|
||||||
|
@ -587,7 +620,7 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kmp_service_cb_register(pae_supp->kmp_service, ws_pae_supp_kmp_incoming_ind, ws_pae_supp_kmp_tx_status_ind, ws_pae_supp_kmp_service_addr_get, ws_pae_supp_kmp_service_api_get) < 0) {
|
if (kmp_service_cb_register(pae_supp->kmp_service, ws_pae_supp_kmp_incoming_ind, ws_pae_supp_kmp_tx_status_ind, ws_pae_supp_kmp_service_addr_get, NULL, ws_pae_supp_kmp_service_api_get) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -896,13 +929,13 @@ static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp)
|
||||||
* There are two retries. Minimum time that sequence takes before authentication failure
|
* There are two retries. Minimum time that sequence takes before authentication failure
|
||||||
* is 22 minutes and maximum is 124 minutes.
|
* is 22 minutes and maximum is 124 minutes.
|
||||||
*/
|
*/
|
||||||
pae_supp->auth_trickle_params = pae_supp->sec_prot_cfg->initial_key_trickle_params;
|
pae_supp->auth_trickle_params = pae_supp->sec_cfg->prot_cfg.initial_key_trickle_params;
|
||||||
pae_supp->initial_key_retry_timer = pae_supp->sec_prot_cfg->initial_key_retry_delay;
|
pae_supp->initial_key_retry_timer = pae_supp->sec_cfg->prot_cfg.initial_key_retry_delay;
|
||||||
|
|
||||||
trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
|
trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
|
||||||
tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t);
|
tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t);
|
||||||
pae_supp->auth_trickle_running = true;
|
pae_supp->auth_trickle_running = true;
|
||||||
pae_supp->initial_key_retry_cnt = pae_supp->sec_prot_cfg->initial_key_retry_cnt;
|
pae_supp->initial_key_retry_cnt = pae_supp->sec_cfg->prot_cfg.initial_key_retry_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp)
|
static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp)
|
||||||
|
@ -920,8 +953,8 @@ static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pa
|
||||||
static void ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp_t *pae_supp, uint8_t timer_expirations)
|
static void ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp_t *pae_supp, uint8_t timer_expirations)
|
||||||
{
|
{
|
||||||
// Starts trickle for the key update
|
// Starts trickle for the key update
|
||||||
pae_supp->auth_trickle_params.Imin = pae_supp->sec_timer_cfg->gtk_request_imin;
|
pae_supp->auth_trickle_params.Imin = pae_supp->sec_cfg->timer_cfg.gtk_request_imin;
|
||||||
pae_supp->auth_trickle_params.Imax = pae_supp->sec_timer_cfg->gtk_request_imax;
|
pae_supp->auth_trickle_params.Imax = pae_supp->sec_cfg->timer_cfg.gtk_request_imax;
|
||||||
pae_supp->auth_trickle_params.k = 0;
|
pae_supp->auth_trickle_params.k = 0;
|
||||||
pae_supp->auth_trickle_params.TimerExpirations = timer_expirations;
|
pae_supp->auth_trickle_params.TimerExpirations = timer_expirations;
|
||||||
|
|
||||||
|
@ -1078,8 +1111,12 @@ static kmp_api_t *ws_pae_supp_kmp_service_api_get(kmp_service_t *service, kmp_ap
|
||||||
return ws_pae_lib_kmp_list_type_get(&pae_supp->entry.kmp_list, type);
|
return ws_pae_lib_kmp_list_type_get(&pae_supp->entry.kmp_list, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr)
|
static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, const void *pdu, uint16_t size)
|
||||||
{
|
{
|
||||||
|
(void) instance_id;
|
||||||
|
(void) pdu;
|
||||||
|
(void) size;
|
||||||
|
|
||||||
// Should be MKA, 4WH or GKH and never initial EAPOL-key for supplicant
|
// Should be MKA, 4WH or GKH and never initial EAPOL-key for supplicant
|
||||||
if (type > IEEE_802_1X_INITIAL_KEY) {
|
if (type > IEEE_802_1X_INITIAL_KEY) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1138,7 +1175,7 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_
|
||||||
static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp)
|
static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp)
|
||||||
{
|
{
|
||||||
// Create new instance
|
// Create new instance
|
||||||
kmp_api_t *kmp = kmp_api_create(service, type, pae_supp->sec_prot_cfg, pae_supp->sec_timer_cfg);
|
kmp_api_t *kmp = kmp_api_create(service, type, 0, pae_supp->sec_cfg);
|
||||||
if (!kmp) {
|
if (!kmp) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,15 +38,14 @@
|
||||||
*
|
*
|
||||||
* \param interface_ptr interface
|
* \param interface_ptr interface
|
||||||
* \param cert_chain certificate chain
|
* \param cert_chain certificate chain
|
||||||
* \param sec_timer_cfg timer configuration
|
* \param sec_cfg security configuration
|
||||||
* \param sec_prot_cfg protocol configuration
|
|
||||||
* \param sec_keys_nw_info security keys network information
|
* \param sec_keys_nw_info security keys network information
|
||||||
*
|
*
|
||||||
* \return < 0 failure
|
* \return < 0 failure
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, sec_timer_cfg_t *sec_timer_cfg, sec_prot_cfg_t *sec_prot_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info);
|
int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_supp_delete deletes PAE supplicant
|
* ws_pae_supp_delete deletes PAE supplicant
|
||||||
|
@ -173,6 +172,20 @@ int8_t ws_pae_supp_gtks_set(protocol_interface_info_entry_t *interface_ptr, sec_
|
||||||
*/
|
*/
|
||||||
int8_t ws_pae_supp_eapol_target_remove(protocol_interface_info_entry_t *interface_ptr);
|
int8_t ws_pae_supp_eapol_target_remove(protocol_interface_info_entry_t *interface_ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ws_pae_auth_nw_info_set set network information
|
||||||
|
*
|
||||||
|
* \param interface_ptr interface
|
||||||
|
* \param pan_id PAD ID
|
||||||
|
* \param network_name network name
|
||||||
|
* \param updated data has been updated
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t ws_pae_supp_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, bool updated);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_supp_nw_key_index_set network send key index set callback
|
* ws_pae_supp_nw_key_index_set network send key index set callback
|
||||||
*
|
*
|
||||||
|
|
|
@ -144,9 +144,9 @@ static void ws_pae_timers_calculate(sec_timer_cfg_t *timer_settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ws_pae_timers_gtk_new_install_required(sec_timer_cfg_t *timer_settings, uint32_t seconds)
|
bool ws_pae_timers_gtk_new_install_required(sec_cfg_t *sec_cfg, uint32_t seconds)
|
||||||
{
|
{
|
||||||
uint32_t gtk_new_install_req_seconds = timer_settings->gtk_expire_offset - timer_settings->gtk_new_install_req * timer_settings->gtk_expire_offset / 100;
|
uint32_t gtk_new_install_req_seconds = sec_cfg->timer_cfg.gtk_expire_offset - sec_cfg->timer_cfg.gtk_new_install_req * sec_cfg->timer_cfg.gtk_expire_offset / 100;
|
||||||
|
|
||||||
if (seconds < gtk_new_install_req_seconds) {
|
if (seconds < gtk_new_install_req_seconds) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -155,9 +155,9 @@ bool ws_pae_timers_gtk_new_install_required(sec_timer_cfg_t *timer_settings, uin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ws_pae_timers_gtk_new_activation_time(sec_timer_cfg_t *timer_settings, uint32_t seconds)
|
bool ws_pae_timers_gtk_new_activation_time(sec_cfg_t *sec_cfg, uint32_t seconds)
|
||||||
{
|
{
|
||||||
uint32_t gtk_gtk_new_activation_time_seconds = timer_settings->gtk_expire_offset / timer_settings->gtk_new_act_time;
|
uint32_t gtk_gtk_new_activation_time_seconds = sec_cfg->timer_cfg.gtk_expire_offset / sec_cfg->timer_cfg.gtk_new_act_time;
|
||||||
|
|
||||||
if (seconds < gtk_gtk_new_activation_time_seconds) {
|
if (seconds < gtk_gtk_new_activation_time_seconds) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -166,9 +166,9 @@ bool ws_pae_timers_gtk_new_activation_time(sec_timer_cfg_t *timer_settings, uint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ws_pae_timers_gtk_revocation_lifetime_get(sec_timer_cfg_t *timer_settings)
|
uint32_t ws_pae_timers_gtk_revocation_lifetime_get(sec_cfg_t *sec_cfg)
|
||||||
{
|
{
|
||||||
return timer_settings->gtk_expire_offset / timer_settings->revocat_lifetime_reduct;
|
return sec_cfg->timer_cfg.gtk_expire_offset / sec_cfg->timer_cfg.revocat_lifetime_reduct;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_WS */
|
#endif /* HAVE_WS */
|
||||||
|
|
|
@ -53,35 +53,35 @@ void ws_pae_timers_gtk_time_settings_set(sec_timer_cfg_t *timer_settings, uint8_
|
||||||
/**
|
/**
|
||||||
* ws_pae_timers_gtk_new_install_required GTK new install required check
|
* ws_pae_timers_gtk_new_install_required GTK new install required check
|
||||||
*
|
*
|
||||||
* \param timer_settings timer settings
|
* \param sec_cfg security configuration
|
||||||
* \param seconds elapsed seconds
|
* \param seconds elapsed seconds
|
||||||
*
|
*
|
||||||
* \return true new GTK install required expired
|
* \return true new GTK install required expired
|
||||||
* \return false GTK install not required
|
* \return false GTK install not required
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool ws_pae_timers_gtk_new_install_required(sec_timer_cfg_t *timer_settings, uint32_t seconds);
|
bool ws_pae_timers_gtk_new_install_required(sec_cfg_t *sec_cfg, uint32_t seconds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_timers_gtk_new_activation_time GTK new activation time
|
* ws_pae_timers_gtk_new_activation_time GTK new activation time
|
||||||
*
|
*
|
||||||
* \param timer_settings timer settings
|
* \param sec_cfg security configuration
|
||||||
* \param seconds elapsed seconds
|
* \param seconds elapsed seconds
|
||||||
*
|
*
|
||||||
* \return true GTK new activation time expired
|
* \return true GTK new activation time expired
|
||||||
* \return false GTK new activation time not expired
|
* \return false GTK new activation time not expired
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool ws_pae_timers_gtk_new_activation_time(sec_timer_cfg_t *timer_settings, uint32_t seconds);
|
bool ws_pae_timers_gtk_new_activation_time(sec_cfg_t *sec_cfg, uint32_t seconds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ws_pae_timers_gtk_revocation_lifetime_get GTK revocation lifetime get
|
* ws_pae_timers_gtk_revocation_lifetime_get GTK revocation lifetime get
|
||||||
*
|
*
|
||||||
* \param timer_settings timer settings
|
* \param sec_cfg security configuration
|
||||||
*
|
*
|
||||||
* \return GTK revocation lifetime
|
* \return GTK revocation lifetime
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
uint32_t ws_pae_timers_gtk_revocation_lifetime_get(sec_timer_cfg_t *timer_settings);
|
uint32_t ws_pae_timers_gtk_revocation_lifetime_get(sec_cfg_t *sec_cfg);
|
||||||
|
|
||||||
#endif /* WS_PAE_TIMERS_H_ */
|
#endif /* WS_PAE_TIMERS_H_ */
|
||||||
|
|
|
@ -18,12 +18,13 @@
|
||||||
#include "nsconfig.h"
|
#include "nsconfig.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ns_list.h>
|
#include "ns_list.h"
|
||||||
#include <nsdynmemLIB.h>
|
#include "nsdynmemLIB.h"
|
||||||
#include <net_ws_test.h>
|
#include "net_ws_test.h"
|
||||||
#include "fhss_config.h"
|
#include "fhss_config.h"
|
||||||
#include "ws_management_api.h"
|
#include "ws_management_api.h"
|
||||||
#include "mac_api.h"
|
#include "mac_api.h"
|
||||||
|
#include "6LoWPAN/MAC/mac_helper.h"
|
||||||
#include "NWK_INTERFACE/Include/protocol.h"
|
#include "NWK_INTERFACE/Include/protocol.h"
|
||||||
#include "6LoWPAN/MAC/mac_helper.h"
|
#include "6LoWPAN/MAC/mac_helper.h"
|
||||||
#include "6LoWPAN/ws/ws_config.h"
|
#include "6LoWPAN/ws/ws_config.h"
|
||||||
|
@ -150,4 +151,17 @@ int ws_test_next_gtk_set(int8_t interface_id, uint8_t *gtk[4])
|
||||||
return ws_pae_controller_next_gtk_update(interface_id, gtk);
|
return ws_pae_controller_next_gtk_update(interface_id, gtk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ws_test_6lowpan_fragmentation_mtu_size_set(int8_t interface_id, uint16_t mtu_size)
|
||||||
|
{
|
||||||
|
protocol_interface_info_entry_t *cur;
|
||||||
|
|
||||||
|
cur = protocol_stack_interface_info_get_by_id(interface_id);
|
||||||
|
if (!cur || !ws_info(cur)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_6lowpan_fragmentation_mtu_size_override = mtu_size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAVE_WS
|
#endif // HAVE_WS
|
||||||
|
|
|
@ -859,6 +859,40 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf)
|
||||||
} else {
|
} else {
|
||||||
ipv6_route_delete(prefix_ptr, prefix_length, cur->id, buf->src_sa.address, ROUTE_RADV);
|
ipv6_route_delete(prefix_ptr, prefix_length, cur->id, buf->src_sa.address, ROUTE_RADV);
|
||||||
}
|
}
|
||||||
|
} else if (type == ICMPV6_OPT_DNS_SEARCH_LIST) {
|
||||||
|
|
||||||
|
if (length < 8) {
|
||||||
|
tr_warn("Invalid RA DNS search list opt corrupt");
|
||||||
|
goto next_option; // invalid not accepted
|
||||||
|
}
|
||||||
|
uint32_t dns_lifetime = common_read_32_bit(dptr + 2); // 2 x reserved
|
||||||
|
uint8_t *dns_search_list = dptr + 6;
|
||||||
|
uint8_t dns_search_list_len = length - 8; // Length includes type and length
|
||||||
|
|
||||||
|
tr_info("DNS Search List: %s Lifetime: %lu", trace_array(dns_search_list, dns_search_list_len), (unsigned long) dns_lifetime);
|
||||||
|
// TODO Add DNS server to DNS information storage.
|
||||||
|
// dns_search_list_storage(cur, buf->src_sa.address, dns_search_list, dns_search_list_len, dns_lifetime);
|
||||||
|
(void)dns_search_list;
|
||||||
|
(void)dns_search_list_len;
|
||||||
|
(void)dns_lifetime;
|
||||||
|
|
||||||
|
} else if (type == ICMPV6_OPT_RECURSIVE_DNS_SERVER) {
|
||||||
|
uint8_t dns_length = length / 8;
|
||||||
|
|
||||||
|
if (dns_length < 3) {
|
||||||
|
tr_warn("Invalid RA DNS server opt corrupt");
|
||||||
|
goto next_option; // invalid not accepted
|
||||||
|
}
|
||||||
|
uint8_t dns_count = (dns_length - 1) / 2;
|
||||||
|
uint32_t dns_lifetime = common_read_32_bit(dptr + 2); // 2 x reserved
|
||||||
|
for (int n = 0; n < dns_count; n++) {
|
||||||
|
uint8_t *dns_srv_addr = dptr + 6 + n * 16;
|
||||||
|
tr_info("DNS Server: %s Lifetime: %lu", trace_ipv6(dns_srv_addr), (unsigned long) dns_lifetime);
|
||||||
|
// TODO Add DNS server to DNS information storage.
|
||||||
|
// dns_server_storage(cur, buf->src_sa.address, dns_srv_addr, dns_lifetime);
|
||||||
|
(void)dns_srv_addr;
|
||||||
|
(void)dns_lifetime;
|
||||||
|
}
|
||||||
} else if (type == ICMPV6_OPT_6LOWPAN_CONTEXT) {
|
} else if (type == ICMPV6_OPT_6LOWPAN_CONTEXT) {
|
||||||
nd_ra_process_lowpan_context_option(cur, dptr - 2);
|
nd_ra_process_lowpan_context_option(cur, dptr - 2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,8 @@
|
||||||
#define ICMPV6_OPT_REDIRECTED_HDR 4
|
#define ICMPV6_OPT_REDIRECTED_HDR 4
|
||||||
#define ICMPV6_OPT_MTU 5
|
#define ICMPV6_OPT_MTU 5
|
||||||
#define ICMPV6_OPT_ROUTE_INFO 24
|
#define ICMPV6_OPT_ROUTE_INFO 24
|
||||||
|
#define ICMPV6_OPT_RECURSIVE_DNS_SERVER 25
|
||||||
|
#define ICMPV6_OPT_DNS_SEARCH_LIST 31
|
||||||
#define ICMPV6_OPT_ADDR_REGISTRATION 33
|
#define ICMPV6_OPT_ADDR_REGISTRATION 33
|
||||||
#define ICMPV6_OPT_6LOWPAN_CONTEXT 34
|
#define ICMPV6_OPT_6LOWPAN_CONTEXT 34
|
||||||
#define ICMPV6_OPT_AUTHORITATIVE_BORDER_RTR 35
|
#define ICMPV6_OPT_AUTHORITATIVE_BORDER_RTR 35
|
||||||
|
|
|
@ -142,6 +142,7 @@ extern const uint8_t ADDR_ALL_MPL_FORWARDERS[16]; // ff03::fc
|
||||||
extern const uint8_t ADDR_ALL_DHCP_RELAY_AGENTS_AND_SERVERS[16]; // ff02::1:2
|
extern const uint8_t ADDR_ALL_DHCP_RELAY_AGENTS_AND_SERVERS[16]; // ff02::1:2
|
||||||
extern const uint8_t ADDR_LOOPBACK[16]; // ::1
|
extern const uint8_t ADDR_LOOPBACK[16]; // ::1
|
||||||
extern const uint8_t ADDR_UNSPECIFIED[16]; // ::
|
extern const uint8_t ADDR_UNSPECIFIED[16]; // ::
|
||||||
|
extern const uint8_t ADDR_6TO4[16]; // 2002::
|
||||||
|
|
||||||
/* Don't bother having another 8 zero bytes for this - reuse ADDR_UNSPECIFIED */
|
/* Don't bother having another 8 zero bytes for this - reuse ADDR_UNSPECIFIED */
|
||||||
#define ADDR_EUI64_ZERO ADDR_UNSPECIFIED
|
#define ADDR_EUI64_ZERO ADDR_UNSPECIFIED
|
||||||
|
|
|
@ -124,6 +124,7 @@ typedef struct buffer_options {
|
||||||
bool need_predecessor: 1; /*!< Used as an indicator that predecessor address needed */
|
bool need_predecessor: 1; /*!< Used as an indicator that predecessor address needed */
|
||||||
bool multicast_loop: 1; /*!< We want loopback if we're a group member (TX), or this IS the loopback if RX */
|
bool multicast_loop: 1; /*!< We want loopback if we're a group member (TX), or this IS the loopback if RX */
|
||||||
bool mpl_permitted: 1; /*!< MPL will be used if enabled on interface and scope >=3 */
|
bool mpl_permitted: 1; /*!< MPL will be used if enabled on interface and scope >=3 */
|
||||||
|
bool edfe_mode: 1; /*!< Use Extended Directed Frame Exchange pattern in MAC layer */
|
||||||
#ifndef NO_IP_FRAGMENT_TX
|
#ifndef NO_IP_FRAGMENT_TX
|
||||||
bool ipv6_dontfrag: 1; /*!< Don't IPv6 fragment (RFC 3542) */
|
bool ipv6_dontfrag: 1; /*!< Don't IPv6 fragment (RFC 3542) */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -177,6 +177,7 @@ typedef struct inet_pcb_s {
|
||||||
bool recvpktinfo: 1;
|
bool recvpktinfo: 1;
|
||||||
bool recvhoplimit: 1;
|
bool recvhoplimit: 1;
|
||||||
bool recvtclass: 1;
|
bool recvtclass: 1;
|
||||||
|
bool edfe_mode: 1;
|
||||||
int_least24_t flow_label;
|
int_least24_t flow_label;
|
||||||
NS_LIST_HEAD(inet_group_t, link) mc_groups;
|
NS_LIST_HEAD(inet_group_t, link) mc_groups;
|
||||||
} inet_pcb_t;
|
} inet_pcb_t;
|
||||||
|
|
|
@ -81,6 +81,7 @@ const uint8_t ADDR_ALL_DHCP_RELAY_AGENTS_AND_SERVERS[16] = { 0xff, 0x02, [13] =
|
||||||
const uint8_t ADDR_IPV4_MAPPED_PREFIX[12] = { [10] = 0xff, 0xff };
|
const uint8_t ADDR_IPV4_MAPPED_PREFIX[12] = { [10] = 0xff, 0xff };
|
||||||
const uint8_t ADDR_LOOPBACK[16] = { [15] = 1 };
|
const uint8_t ADDR_LOOPBACK[16] = { [15] = 1 };
|
||||||
const uint8_t ADDR_UNSPECIFIED[16] = { 0 }; /* Note a few bits of code check for pointer equality with ADDR_UNSPECIFIED */
|
const uint8_t ADDR_UNSPECIFIED[16] = { 0 }; /* Note a few bits of code check for pointer equality with ADDR_UNSPECIFIED */
|
||||||
|
const uint8_t ADDR_6TO4[16] = { 0x20, 0x02 }; /*Can be used as global address*/
|
||||||
#define ADDR_IPV4_COMPATIBLE ADDR_LOOPBACK /* First 96 bits match...*/
|
#define ADDR_IPV4_COMPATIBLE ADDR_LOOPBACK /* First 96 bits match...*/
|
||||||
|
|
||||||
#define ADDR_MULTICAST_LINK_PREFIX ADDR_LINK_LOCAL_ALL_NODES /* ff02::xx */
|
#define ADDR_MULTICAST_LINK_PREFIX ADDR_LINK_LOCAL_ALL_NODES /* ff02::xx */
|
||||||
|
|
|
@ -401,6 +401,8 @@ inet_pcb_t *socket_inet_pcb_allocate(void)
|
||||||
inet_pcb->recvhoplimit = false;
|
inet_pcb->recvhoplimit = false;
|
||||||
inet_pcb->recvpktinfo = false;
|
inet_pcb->recvpktinfo = false;
|
||||||
inet_pcb->recvtclass = false;
|
inet_pcb->recvtclass = false;
|
||||||
|
inet_pcb->edfe_mode = false;
|
||||||
|
|
||||||
inet_pcb->link_layer_security = -1;
|
inet_pcb->link_layer_security = -1;
|
||||||
#ifndef NO_IPV6_PMTUD
|
#ifndef NO_IPV6_PMTUD
|
||||||
inet_pcb->use_min_mtu = -1;
|
inet_pcb->use_min_mtu = -1;
|
||||||
|
@ -1134,6 +1136,7 @@ int16_t socket_buffer_sendmsg(int8_t sid, buffer_t *buf, const struct ns_msghdr
|
||||||
buf->options.ipv6_use_min_mtu = inet_pcb->use_min_mtu;
|
buf->options.ipv6_use_min_mtu = inet_pcb->use_min_mtu;
|
||||||
buf->options.ipv6_dontfrag = inet_pcb->dontfrag;
|
buf->options.ipv6_dontfrag = inet_pcb->dontfrag;
|
||||||
buf->options.multicast_loop = inet_pcb->multicast_loop;
|
buf->options.multicast_loop = inet_pcb->multicast_loop;
|
||||||
|
buf->options.edfe_mode = inet_pcb->edfe_mode;
|
||||||
|
|
||||||
/* Set default remote address from PCB */
|
/* Set default remote address from PCB */
|
||||||
if (inet_pcb->remote_port != 0 && !addr_ipv6_equal(inet_pcb->remote_address, ns_in6addr_any)) {
|
if (inet_pcb->remote_port != 0 && !addr_ipv6_equal(inet_pcb->remote_address, ns_in6addr_any)) {
|
||||||
|
|
|
@ -140,3 +140,11 @@ int8_t mac_cca_threshold_update(protocol_interface_rf_mac_setup_s *rf_ptr, uint8
|
||||||
tr_debug("Channel %u CCA threshold to %i", channel, rf_ptr->cca_threshold->ch_thresholds[channel]);
|
tr_debug("Channel %u CCA threshold to %i", channel, rf_ptr->cca_threshold->ch_thresholds[channel]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mac_cca_threshold_s *mac_get_cca_threshold_table(protocol_interface_rf_mac_setup_s *rf_ptr)
|
||||||
|
{
|
||||||
|
if (!rf_ptr->cca_threshold) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return rf_ptr->cca_threshold;
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ int8_t mac_cca_thr_deinit(protocol_interface_rf_mac_setup_s *rf_ptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read CCA threshold of specific channel.
|
* @brief Read CCA threshold of specific channel.
|
||||||
|
* @param rf_ptr Pointer to MAC instance.
|
||||||
* @param channel Channel.
|
* @param channel Channel.
|
||||||
* @return CCA threshold (dBm), CCA_FAILED_DBM Feature not enabled.
|
* @return CCA threshold (dBm), CCA_FAILED_DBM Feature not enabled.
|
||||||
*/
|
*/
|
||||||
|
@ -56,10 +57,18 @@ int8_t mac_cca_thr_get_dbm(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t ch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update CCA threshold of specific channel.
|
* @brief Update CCA threshold of specific channel.
|
||||||
|
* @param rf_ptr Pointer to MAC instance.
|
||||||
* @param channel Channel.
|
* @param channel Channel.
|
||||||
* @param dbm CCA threshold (dBm).
|
* @param dbm CCA threshold (dBm).
|
||||||
* @return 0 Updated, negative Already using this value.
|
* @return 0 Updated, negative Already using this value.
|
||||||
*/
|
*/
|
||||||
int8_t mac_cca_threshold_update(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int8_t dbm);
|
int8_t mac_cca_threshold_update(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int8_t dbm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get pointer to CCA threshold table.
|
||||||
|
* @param rf_ptr Pointer to MAC instance.
|
||||||
|
* @return CCA threshold table.
|
||||||
|
*/
|
||||||
|
mac_cca_threshold_s *mac_get_cca_threshold_table(protocol_interface_rf_mac_setup_s *rf_ptr);
|
||||||
|
|
||||||
#endif /* MAC_CCA_THRESHOLD_H_ */
|
#endif /* MAC_CCA_THRESHOLD_H_ */
|
||||||
|
|
|
@ -98,6 +98,8 @@ typedef struct mac_pre_build_frame {
|
||||||
bool asynch_request: 1;
|
bool asynch_request: 1;
|
||||||
bool message_builded: 1;
|
bool message_builded: 1;
|
||||||
bool DSN_allocated: 1;
|
bool DSN_allocated: 1;
|
||||||
|
bool ExtendedFrameExchange: 1;
|
||||||
|
bool WaitResponse: 1;
|
||||||
unsigned security_mic_len: 5; //Max possible lengths 0, 4, 8, 16 bytes
|
unsigned security_mic_len: 5; //Max possible lengths 0, 4, 8, 16 bytes
|
||||||
unsigned priority: 2;
|
unsigned priority: 2;
|
||||||
struct mac_pre_build_frame *next; //Pointer for queue purpose
|
struct mac_pre_build_frame *next; //Pointer for queue purpose
|
||||||
|
|
|
@ -147,6 +147,25 @@ typedef struct mac_mcps_data_conf_fail_s {
|
||||||
uint8_t status; /**< Status of the failing MSDU transmission */
|
uint8_t status; /**< Status of the failing MSDU transmission */
|
||||||
} mac_mcps_data_conf_fail_t;
|
} mac_mcps_data_conf_fail_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum mac_edfe_frame_state {
|
||||||
|
MAC_EDFE_FRAME_IDLE = 0,
|
||||||
|
MAC_EDFE_FRAME_CONNECTING,
|
||||||
|
MAC_EDFE_FRAME_CONNECTED,
|
||||||
|
MAC_EDFE_FRAME_TX_RESPONSE,
|
||||||
|
MAC_EDFE_FRAME_TX_FINAL_FRAME,
|
||||||
|
MAC_EDFE_FRAME_WAIT_DATA,
|
||||||
|
MAC_EDFE_FRAME_WAIT_RESPONSE
|
||||||
|
} mac_edfe_frame_state_e;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct mac_mcps_edfe_info_s {
|
||||||
|
mac_edfe_frame_state_e state;
|
||||||
|
uint8_t PeerAddr[8];
|
||||||
|
struct mac_pre_build_frame edfe_response_buffer;
|
||||||
|
} mac_mcps_edfe_frame_info_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct protocol_interface_rf_mac_setup {
|
typedef struct protocol_interface_rf_mac_setup {
|
||||||
int8_t mac_interface_id;
|
int8_t mac_interface_id;
|
||||||
bool macUpState: 1;
|
bool macUpState: 1;
|
||||||
|
@ -154,7 +173,10 @@ typedef struct protocol_interface_rf_mac_setup {
|
||||||
bool beaconSrcAddressModeLong: 1; //This force beacon src to mac64 otherwise shortAdressValid will define type
|
bool beaconSrcAddressModeLong: 1; //This force beacon src to mac64 otherwise shortAdressValid will define type
|
||||||
bool secFrameCounterPerKey: 1;
|
bool secFrameCounterPerKey: 1;
|
||||||
bool mac_extension_enabled: 1;
|
bool mac_extension_enabled: 1;
|
||||||
|
bool mac_edfe_enabled: 1; // Indicate when EFDE exchange is possible
|
||||||
bool mac_ack_tx_active: 1;
|
bool mac_ack_tx_active: 1;
|
||||||
|
bool mac_edfe_tx_active: 1;
|
||||||
|
bool mac_edfe_response_tx_active: 1;
|
||||||
bool mac_frame_pending: 1;
|
bool mac_frame_pending: 1;
|
||||||
/* MAC Capability Information */
|
/* MAC Capability Information */
|
||||||
bool macCapRxOnIdle: 1;
|
bool macCapRxOnIdle: 1;
|
||||||
|
@ -279,6 +301,7 @@ typedef struct protocol_interface_rf_mac_setup {
|
||||||
struct mac_cca_threshold *cca_threshold;
|
struct mac_cca_threshold *cca_threshold;
|
||||||
//beacon_join_priority_tx_cb *beacon_join_priority_tx_cb_ptr;
|
//beacon_join_priority_tx_cb *beacon_join_priority_tx_cb_ptr;
|
||||||
struct mac_statistics_s *mac_statistics;
|
struct mac_statistics_s *mac_statistics;
|
||||||
|
mac_mcps_edfe_frame_info_t *mac_edfe_info;
|
||||||
/* FHSS API*/
|
/* FHSS API*/
|
||||||
struct fhss_api *fhss_api;
|
struct fhss_api *fhss_api;
|
||||||
} protocol_interface_rf_mac_setup_s;
|
} protocol_interface_rf_mac_setup_s;
|
||||||
|
|
|
@ -87,9 +87,16 @@ int mac_set_channel(const fhss_api_t *fhss_api, uint8_t channel_number)
|
||||||
if (!mac_setup) {
|
if (!mac_setup) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mac_setup->mac_ack_tx_active || (mac_setup->active_pd_data_request && (mac_setup->active_pd_data_request->asynch_request || mac_setup->timer_mac_event == MAC_TIMER_ACK))) {
|
if (mac_setup->mac_ack_tx_active || (mac_setup->active_pd_data_request && (mac_setup->active_pd_data_request->asynch_request || mac_setup->timer_mac_event == MAC_TIMER_ACK))) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//EDFE packet check if active tx or frame change session open for example wait data
|
||||||
|
if (mac_setup->mac_edfe_enabled && (mac_setup->mac_edfe_tx_active || mac_setup->mac_edfe_info->state > MAC_EDFE_FRAME_CONNECTING)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return mac_mlme_rf_channel_change(mac_setup, channel_number);
|
return mac_mlme_rf_channel_change(mac_setup, channel_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -197,6 +197,18 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set
|
||||||
uint8_t status = MLME_SUCCESS;
|
uint8_t status = MLME_SUCCESS;
|
||||||
mac_pre_build_frame_t *buffer = NULL;
|
mac_pre_build_frame_t *buffer = NULL;
|
||||||
|
|
||||||
|
if (rf_mac_setup->mac_edfe_enabled && data_req->ExtendedFrameExchange) {
|
||||||
|
if (rf_mac_setup->mac_edfe_info->state != MAC_EDFE_FRAME_IDLE) {
|
||||||
|
tr_debug("Accept only 1 active Efde Data request push");
|
||||||
|
status = MLME_UNSUPPORTED_LEGACY;
|
||||||
|
goto verify_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_req->DstAddrMode != MAC_ADDR_MODE_64_BIT) {
|
||||||
|
status = MLME_INVALID_PARAMETER;
|
||||||
|
goto verify_status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!rf_mac_setup->mac_security_enabled) {
|
if (!rf_mac_setup->mac_security_enabled) {
|
||||||
if (data_req->Key.SecurityLevel) {
|
if (data_req->Key.SecurityLevel) {
|
||||||
|
@ -254,7 +266,13 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set
|
||||||
|
|
||||||
buffer->upper_layer_request = true;
|
buffer->upper_layer_request = true;
|
||||||
buffer->fcf_dsn.frametype = FC_DATA_FRAME;
|
buffer->fcf_dsn.frametype = FC_DATA_FRAME;
|
||||||
buffer->fcf_dsn.ackRequested = data_req->TxAckReq;
|
buffer->ExtendedFrameExchange = data_req->ExtendedFrameExchange;
|
||||||
|
buffer->WaitResponse = data_req->TxAckReq;
|
||||||
|
if (data_req->ExtendedFrameExchange) {
|
||||||
|
buffer->fcf_dsn.ackRequested = false;
|
||||||
|
} else {
|
||||||
|
buffer->fcf_dsn.ackRequested = data_req->TxAckReq;
|
||||||
|
}
|
||||||
|
|
||||||
buffer->mac_header_length_with_security = 3;
|
buffer->mac_header_length_with_security = 3;
|
||||||
mac_header_security_parameter_set(&buffer->aux_header, &data_req->Key);
|
mac_header_security_parameter_set(&buffer->aux_header, &data_req->Key);
|
||||||
|
@ -336,6 +354,7 @@ void mcps_sap_data_req_handler_ext(protocol_interface_rf_mac_setup_s *rf_mac_set
|
||||||
buffer->mac_payload = data_req->msdu;
|
buffer->mac_payload = data_req->msdu;
|
||||||
buffer->mac_payload_length = data_req->msduLength;
|
buffer->mac_payload_length = data_req->msduLength;
|
||||||
//check that header + payload length is not bigger than MAC MTU
|
//check that header + payload length is not bigger than MAC MTU
|
||||||
|
|
||||||
if (data_req->InDirectTx) {
|
if (data_req->InDirectTx) {
|
||||||
mac_indirect_queue_write(rf_mac_setup, buffer);
|
mac_indirect_queue_write(rf_mac_setup, buffer);
|
||||||
} else {
|
} else {
|
||||||
|
@ -550,8 +569,14 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme
|
||||||
//READ SRC Address
|
//READ SRC Address
|
||||||
|
|
||||||
uint16_t SrcPANId = mac_header_get_src_panid(&b->fcf_dsn, mac_header_message_start_pointer(b), rf_mac_setup->pan_id);
|
uint16_t SrcPANId = mac_header_get_src_panid(&b->fcf_dsn, mac_header_message_start_pointer(b), rf_mac_setup->pan_id);
|
||||||
mac_header_get_src_address(&b->fcf_dsn, mac_header_message_start_pointer(b), neighbour_validation.address);
|
|
||||||
neighbour_validation.addr_type = b->fcf_dsn.SrcAddrMode;
|
if (b->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_NONE && rf_mac_setup->mac_edfe_enabled && rf_mac_setup->mac_edfe_info->state > MAC_EDFE_FRAME_CONNECTING) {
|
||||||
|
memcpy(neighbour_validation.address, rf_mac_setup->mac_edfe_info->PeerAddr, 8);
|
||||||
|
neighbour_validation.addr_type = MAC_ADDR_MODE_64_BIT;
|
||||||
|
} else {
|
||||||
|
mac_header_get_src_address(&b->fcf_dsn, mac_header_message_start_pointer(b), neighbour_validation.address);
|
||||||
|
neighbour_validation.addr_type = b->fcf_dsn.SrcAddrMode;
|
||||||
|
}
|
||||||
neighbour_validation.keyId = security_params->KeyIndex;
|
neighbour_validation.keyId = security_params->KeyIndex;
|
||||||
|
|
||||||
// Get A Key description
|
// Get A Key description
|
||||||
|
@ -708,6 +733,7 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte
|
||||||
memset(data_ind, 0, sizeof(mcps_data_ind_t));
|
memset(data_ind, 0, sizeof(mcps_data_ind_t));
|
||||||
//Parse data
|
//Parse data
|
||||||
data_ind->DSN = buf->fcf_dsn.DSN;
|
data_ind->DSN = buf->fcf_dsn.DSN;
|
||||||
|
data_ind->DSN_suppressed = buf->fcf_dsn.sequenceNumberSuppress;
|
||||||
data_ind->DstAddrMode = buf->fcf_dsn.DstAddrMode;
|
data_ind->DstAddrMode = buf->fcf_dsn.DstAddrMode;
|
||||||
mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), data_ind->DstAddr);
|
mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), data_ind->DstAddr);
|
||||||
data_ind->SrcAddrMode = buf->fcf_dsn.SrcAddrMode;
|
data_ind->SrcAddrMode = buf->fcf_dsn.SrcAddrMode;
|
||||||
|
@ -722,6 +748,10 @@ static int8_t mac_data_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inte
|
||||||
data_ind->timestamp = buf->timestamp;
|
data_ind->timestamp = buf->timestamp;
|
||||||
/* Parse security part */
|
/* Parse security part */
|
||||||
mac_header_security_components_read(buf, &data_ind->Key);
|
mac_header_security_components_read(buf, &data_ind->Key);
|
||||||
|
if (data_ind->SrcAddrMode == MAC_ADDR_MODE_NONE && rf_mac_setup->mac_edfe_enabled && rf_mac_setup->mac_edfe_info->state > MAC_EDFE_FRAME_CONNECTING) {
|
||||||
|
memcpy(data_ind->SrcAddr, rf_mac_setup->mac_edfe_info->PeerAddr, 8);
|
||||||
|
data_ind->SrcAddrMode = MAC_ADDR_MODE_64_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
buf->neigh_info = mac_sec_mib_device_description_get(rf_mac_setup, data_ind->SrcAddr, data_ind->SrcAddrMode, data_ind->SrcPANId);
|
buf->neigh_info = mac_sec_mib_device_description_get(rf_mac_setup, data_ind->SrcAddr, data_ind->SrcAddrMode, data_ind->SrcPANId);
|
||||||
if (buf->fcf_dsn.securityEnabled) {
|
if (buf->fcf_dsn.securityEnabled) {
|
||||||
|
@ -795,7 +825,7 @@ static void mac_lib_res_no_data_to_req(mac_pre_parsed_frame_t *buffer, protocol_
|
||||||
|
|
||||||
buf->fcf_dsn.securityEnabled = buffer->fcf_dsn.securityEnabled;
|
buf->fcf_dsn.securityEnabled = buffer->fcf_dsn.securityEnabled;
|
||||||
buf->fcf_dsn.intraPan = true;
|
buf->fcf_dsn.intraPan = true;
|
||||||
buf->fcf_dsn.ackRequested = true;
|
buf->WaitResponse = buf->fcf_dsn.ackRequested = true;
|
||||||
buf->mac_header_length_with_security = 3;
|
buf->mac_header_length_with_security = 3;
|
||||||
//Check PanID presents at header
|
//Check PanID presents at header
|
||||||
buf->fcf_dsn.DstPanPresents = mac_dst_panid_present(&buf->fcf_dsn);
|
buf->fcf_dsn.DstPanPresents = mac_dst_panid_present(&buf->fcf_dsn);
|
||||||
|
@ -1061,8 +1091,17 @@ void mac_mcps_trig_buffer_from_queue(protocol_interface_rf_mac_setup_s *rf_mac_s
|
||||||
buffer = mcps_sap_pd_req_queue_read(rf_mac_setup, is_bc_queue, false);
|
buffer = mcps_sap_pd_req_queue_read(rf_mac_setup, is_bc_queue, false);
|
||||||
|
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
|
//Here
|
||||||
|
if (buffer->ExtendedFrameExchange) {
|
||||||
|
//Update here state and store peer
|
||||||
|
memcpy(rf_mac_setup->mac_edfe_info->PeerAddr, buffer->DstAddr, 8);
|
||||||
|
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_CONNECTING;
|
||||||
|
}
|
||||||
rf_mac_setup->active_pd_data_request = buffer;
|
rf_mac_setup->active_pd_data_request = buffer;
|
||||||
if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) {
|
if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) {
|
||||||
|
if (buffer->ExtendedFrameExchange) {
|
||||||
|
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||||
|
}
|
||||||
rf_mac_setup->active_pd_data_request = NULL;
|
rf_mac_setup->active_pd_data_request = NULL;
|
||||||
mac_mcps_asynch_finish(rf_mac_setup, buffer);
|
mac_mcps_asynch_finish(rf_mac_setup, buffer);
|
||||||
mcps_data_confirm_handle(rf_mac_setup, buffer, NULL);
|
mcps_data_confirm_handle(rf_mac_setup, buffer, NULL);
|
||||||
|
@ -1079,15 +1118,24 @@ static int8_t mac_ack_sap_rx_handler(mac_pre_parsed_frame_t *buf, protocol_inter
|
||||||
{
|
{
|
||||||
//allocate Data ind primitiv and parse packet to that
|
//allocate Data ind primitiv and parse packet to that
|
||||||
mlme_security_t key;
|
mlme_security_t key;
|
||||||
|
uint8_t srcAddressMode;
|
||||||
uint8_t SrcAddr[8]; /**< Source address */
|
uint8_t SrcAddr[8]; /**< Source address */
|
||||||
memset(SrcAddr, 0, 8);
|
memset(SrcAddr, 0, 8);
|
||||||
memset(&key, 0, sizeof(mlme_security_t));
|
memset(&key, 0, sizeof(mlme_security_t));
|
||||||
mac_header_get_src_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), SrcAddr);
|
srcAddressMode = buf->fcf_dsn.SrcAddrMode;
|
||||||
|
if (buf->fcf_dsn.SrcAddrMode) {
|
||||||
|
mac_header_get_src_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), SrcAddr);
|
||||||
|
} else {
|
||||||
|
if (rf_mac_setup->mac_edfe_enabled && (buf->fcf_dsn.frametype == FC_DATA_FRAME && !buf->fcf_dsn.ackRequested)) {
|
||||||
|
memcpy(SrcAddr, rf_mac_setup->mac_edfe_info->PeerAddr, 8);
|
||||||
|
srcAddressMode = MAC_ADDR_MODE_64_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
uint16_t pan_id = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id);
|
uint16_t pan_id = mac_header_get_src_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), rf_mac_setup->pan_id);
|
||||||
/* Parse security part */
|
/* Parse security part */
|
||||||
mac_header_security_components_read(buf, &key);
|
mac_header_security_components_read(buf, &key);
|
||||||
|
|
||||||
buf->neigh_info = mac_sec_mib_device_description_get(rf_mac_setup, SrcAddr, buf->fcf_dsn.SrcAddrMode, pan_id);
|
buf->neigh_info = mac_sec_mib_device_description_get(rf_mac_setup, SrcAddr, srcAddressMode, pan_id);
|
||||||
if (buf->fcf_dsn.securityEnabled) {
|
if (buf->fcf_dsn.securityEnabled) {
|
||||||
uint8_t status = mac_data_interface_decrypt_packet(buf, &key);
|
uint8_t status = mac_data_interface_decrypt_packet(buf, &key);
|
||||||
if (status != MLME_SUCCESS) {
|
if (status != MLME_SUCCESS) {
|
||||||
|
@ -1426,6 +1474,22 @@ static void mac_data_interface_internal_tx_confirm_handle(protocol_interface_rf_
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool mcps_buffer_edfe_data_failure(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer)
|
||||||
|
{
|
||||||
|
if (!rf_ptr->mac_edfe_enabled || !buffer->ExtendedFrameExchange) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rf_ptr->mac_edfe_info->state > MAC_EDFE_FRAME_CONNECTING) {
|
||||||
|
//Set to idle
|
||||||
|
tr_debug("Edfe Data send fail");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer, mac_pre_parsed_frame_t *ack_buf)
|
static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer, mac_pre_parsed_frame_t *ack_buf)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1434,7 +1498,7 @@ static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr,
|
||||||
mcps_data_conf_t confirm;
|
mcps_data_conf_t confirm;
|
||||||
if (rf_ptr->fhss_api && !buffer->asynch_request) {
|
if (rf_ptr->fhss_api && !buffer->asynch_request) {
|
||||||
// FHSS checks if this failed buffer needs to be pushed back to TX queue and retransmitted
|
// FHSS checks if this failed buffer needs to be pushed back to TX queue and retransmitted
|
||||||
if ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL)) {
|
if (!mcps_buffer_edfe_data_failure(rf_ptr, buffer) && ((rf_ptr->mac_tx_result == MAC_TX_FAIL) || (rf_ptr->mac_tx_result == MAC_CCA_FAIL))) {
|
||||||
if (rf_ptr->fhss_api->data_tx_fail(rf_ptr->fhss_api, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), rf_ptr->mac_tx_start_channel) == true) {
|
if (rf_ptr->fhss_api->data_tx_fail(rf_ptr->fhss_api, buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), rf_ptr->mac_tx_start_channel) == true) {
|
||||||
|
|
||||||
if (rf_ptr->mac_tx_result == MAC_TX_FAIL) {
|
if (rf_ptr->mac_tx_result == MAC_TX_FAIL) {
|
||||||
|
@ -1447,6 +1511,11 @@ static void mcps_data_confirm_handle(protocol_interface_rf_mac_setup_s *rf_ptr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rf_ptr->mac_edfe_enabled && buffer->ExtendedFrameExchange) {
|
||||||
|
rf_ptr->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
confirm.cca_retries = rf_ptr->mac_tx_status.cca_cnt + buffer->fhss_cca_retry_count;
|
confirm.cca_retries = rf_ptr->mac_tx_status.cca_cnt + buffer->fhss_cca_retry_count;
|
||||||
confirm.tx_retries = rf_ptr->mac_tx_status.retry + buffer->fhss_retry_count;
|
confirm.tx_retries = rf_ptr->mac_tx_status.retry + buffer->fhss_retry_count;
|
||||||
|
@ -1622,7 +1691,11 @@ static int8_t mcps_generic_packet_build(protocol_interface_rf_mac_setup_s *rf_pt
|
||||||
|
|
||||||
tx_buf->len = frame_length;
|
tx_buf->len = frame_length;
|
||||||
uint8_t *mhr_start = ptr;
|
uint8_t *mhr_start = ptr;
|
||||||
buffer->tx_time = mcps_generic_backoff_calc(rf_ptr);
|
if (buffer->ExtendedFrameExchange && buffer->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_NONE) {
|
||||||
|
buffer->tx_time = mac_mcps_sap_get_phy_timestamp(rf_ptr) + 300; //Send 300 us later
|
||||||
|
} else {
|
||||||
|
buffer->tx_time = mcps_generic_backoff_calc(rf_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
ptr = mac_generic_packet_write(rf_ptr, ptr, buffer);
|
ptr = mac_generic_packet_write(rf_ptr, ptr, buffer);
|
||||||
|
|
||||||
|
@ -1716,6 +1789,86 @@ int8_t mcps_generic_ack_data_request_init(protocol_interface_rf_mac_setup_s *rf_
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t mcps_generic_edfe_frame_init(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_edfe_response_t *response)
|
||||||
|
{
|
||||||
|
//Data Here
|
||||||
|
mac_pre_build_frame_t *buffer;
|
||||||
|
if (response->wait_response) {
|
||||||
|
buffer = rf_ptr->active_pd_data_request;
|
||||||
|
buffer->message_builded = false;
|
||||||
|
} else {
|
||||||
|
buffer = &rf_ptr->enhanced_ack_buffer;
|
||||||
|
memset(buffer, 0, sizeof(mac_pre_build_frame_t));
|
||||||
|
buffer->fcf_dsn.frametype = FC_DATA_FRAME;
|
||||||
|
buffer->fcf_dsn.frameVersion = fcf->frameVersion;
|
||||||
|
buffer->fcf_dsn.DstPanPresents = fcf->DstPanPresents;
|
||||||
|
buffer->fcf_dsn.DstAddrMode = response->DstAddrMode;
|
||||||
|
buffer->DstPANId = mac_header_get_src_panid(fcf, data_ptr, rf_ptr->pan_id);
|
||||||
|
buffer->SrcPANId = mac_header_get_dst_panid(fcf, data_ptr, rf_ptr->pan_id);
|
||||||
|
memcpy(buffer->DstAddr, response->Address, 8);
|
||||||
|
}
|
||||||
|
buffer->fcf_dsn.intraPan = response->PanIdSuppressed;
|
||||||
|
buffer->fcf_dsn.SrcAddrMode = response->SrcAddrMode;
|
||||||
|
buffer->fcf_dsn.SrcPanPresents = response->SrcAddrMode;
|
||||||
|
buffer->fcf_dsn.framePending = false;
|
||||||
|
buffer->fcf_dsn.sequenceNumberSuppress = fcf->sequenceNumberSuppress;
|
||||||
|
|
||||||
|
buffer->WaitResponse = response->wait_response;
|
||||||
|
buffer->ExtendedFrameExchange = true;
|
||||||
|
|
||||||
|
if (buffer->fcf_dsn.sequenceNumberSuppress) {
|
||||||
|
buffer->mac_header_length_with_security = 2;
|
||||||
|
} else {
|
||||||
|
buffer->mac_header_length_with_security = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->mac_header_length_with_security += mac_header_address_length(&buffer->fcf_dsn);
|
||||||
|
|
||||||
|
//Security
|
||||||
|
buffer->fcf_dsn.securityEnabled = fcf->securityEnabled;
|
||||||
|
if (buffer->fcf_dsn.securityEnabled) {
|
||||||
|
//Read Security AUX headers
|
||||||
|
const uint8_t *ptr = data_ptr;
|
||||||
|
ptr += mac_header_off_set_to_aux_header(fcf);
|
||||||
|
//Start parsing AUX header
|
||||||
|
mlme_security_t aux_parse;
|
||||||
|
mac_header_security_aux_header_parse(ptr, &aux_parse);
|
||||||
|
buffer->aux_header.KeyIdMode = aux_parse.KeyIdMode;
|
||||||
|
buffer->aux_header.KeyIndex = aux_parse.KeyIndex;
|
||||||
|
buffer->aux_header.securityLevel = aux_parse.SecurityLevel;
|
||||||
|
memcpy(buffer->aux_header.Keysource, aux_parse.Keysource, 8);
|
||||||
|
|
||||||
|
buffer->security_mic_len = mac_security_mic_length_get(buffer->aux_header.securityLevel);
|
||||||
|
buffer->fcf_dsn.frameVersion = MAC_FRAME_VERSION_2006;
|
||||||
|
buffer->mac_header_length_with_security += mac_header_security_aux_header_length(buffer->aux_header.securityLevel, buffer->aux_header.KeyIdMode);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ie_header_length = 0;
|
||||||
|
uint16_t ie_payload_length = 0;
|
||||||
|
|
||||||
|
if (!mac_ie_vector_length_validate(response->ie_response.headerIeVectorList, response->ie_response.headerIovLength, &ie_header_length)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mac_ie_vector_length_validate(response->ie_response.payloadIeVectorList, response->ie_response.payloadIovLength, &ie_payload_length)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->ie_elements.headerIeVectorList = response->ie_response.headerIeVectorList;
|
||||||
|
buffer->ie_elements.headerIovLength = response->ie_response.headerIovLength;
|
||||||
|
buffer->ie_elements.payloadIeVectorList = response->ie_response.payloadIeVectorList;
|
||||||
|
buffer->ie_elements.payloadIovLength = response->ie_response.payloadIovLength;
|
||||||
|
buffer->headerIeLength = ie_header_length;
|
||||||
|
buffer->payloadsIeLength = ie_payload_length;
|
||||||
|
buffer->mac_payload = NULL;
|
||||||
|
buffer->mac_payload_length = 0;
|
||||||
|
|
||||||
|
//This will prepare MHR length with Header IE
|
||||||
|
mac_header_information_elements_preparation(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool init_build)
|
int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool init_build)
|
||||||
{
|
{
|
||||||
|
@ -1854,8 +2007,11 @@ static int8_t mcps_generic_packet_rebuild(protocol_interface_rf_mac_setup_s *rf_
|
||||||
|
|
||||||
tx_buf->len = frame_length;
|
tx_buf->len = frame_length;
|
||||||
uint8_t *mhr_start = ptr;
|
uint8_t *mhr_start = ptr;
|
||||||
|
if (buffer->ExtendedFrameExchange && buffer->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_NONE) {
|
||||||
buffer->tx_time = mcps_generic_backoff_calc(rf_ptr);
|
buffer->tx_time = mac_mcps_sap_get_phy_timestamp(rf_ptr) + 300; //Send 300 us later
|
||||||
|
} else {
|
||||||
|
buffer->tx_time = mcps_generic_backoff_calc(rf_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
ptr = mac_generic_packet_write(rf_ptr, ptr, buffer);
|
ptr = mac_generic_packet_write(rf_ptr, ptr, buffer);
|
||||||
|
|
||||||
|
@ -1884,15 +2040,39 @@ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, m
|
||||||
cca_enabled = false;
|
cca_enabled = false;
|
||||||
rf_ptr->mac_ack_tx_active = true;
|
rf_ptr->mac_ack_tx_active = true;
|
||||||
} else {
|
} else {
|
||||||
if (rf_ptr->mac_ack_tx_active) {
|
if (buffer->ExtendedFrameExchange) {
|
||||||
mac_csma_backoff_start(rf_ptr);
|
if (buffer->fcf_dsn.SrcAddrMode) {
|
||||||
platform_exit_critical();
|
cca_enabled = true;
|
||||||
return -1;
|
} else {
|
||||||
|
//Response
|
||||||
|
if (!buffer->WaitResponse) {
|
||||||
|
//Response
|
||||||
|
if (rf_ptr->mac_ack_tx_active) {
|
||||||
|
mac_csma_backoff_start(rf_ptr);
|
||||||
|
platform_exit_critical();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rf_ptr->mac_edfe_response_tx_active = true;
|
||||||
|
} else {
|
||||||
|
rf_ptr->mac_edfe_response_tx_active = false;
|
||||||
|
}
|
||||||
|
cca_enabled = false;
|
||||||
|
rf_ptr->mac_edfe_tx_active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (rf_ptr->mac_ack_tx_active) {
|
||||||
|
mac_csma_backoff_start(rf_ptr);
|
||||||
|
platform_exit_critical();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cca_enabled = true;
|
||||||
}
|
}
|
||||||
cca_enabled = true;
|
|
||||||
}
|
}
|
||||||
// Use double CCA check with FHSS for data packets only
|
// Use double CCA check with FHSS for data packets only
|
||||||
if (rf_ptr->fhss_api && !rf_ptr->mac_ack_tx_active && !rf_ptr->active_pd_data_request->asynch_request) {
|
if (rf_ptr->fhss_api && !rf_ptr->mac_ack_tx_active && !rf_ptr->mac_edfe_tx_active && !rf_ptr->active_pd_data_request->asynch_request) {
|
||||||
if ((buffer->tx_time - (rf_ptr->multi_cca_interval * (rf_ptr->number_of_csma_ca_periods - 1))) > mac_mcps_sap_get_phy_timestamp(rf_ptr)) {
|
if ((buffer->tx_time - (rf_ptr->multi_cca_interval * (rf_ptr->number_of_csma_ca_periods - 1))) > mac_mcps_sap_get_phy_timestamp(rf_ptr)) {
|
||||||
buffer->csma_periods_left = rf_ptr->number_of_csma_ca_periods - 1;
|
buffer->csma_periods_left = rf_ptr->number_of_csma_ca_periods - 1;
|
||||||
buffer->tx_time -= (rf_ptr->multi_cca_interval * (rf_ptr->number_of_csma_ca_periods - 1));
|
buffer->tx_time -= (rf_ptr->multi_cca_interval * (rf_ptr->number_of_csma_ca_periods - 1));
|
||||||
|
@ -1900,10 +2080,13 @@ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, m
|
||||||
}
|
}
|
||||||
mac_pd_sap_set_phy_tx_time(rf_ptr, buffer->tx_time, cca_enabled);
|
mac_pd_sap_set_phy_tx_time(rf_ptr, buffer->tx_time, cca_enabled);
|
||||||
if (mac_plme_cca_req(rf_ptr) != 0) {
|
if (mac_plme_cca_req(rf_ptr) != 0) {
|
||||||
if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) {
|
if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK || (buffer->ExtendedFrameExchange && rf_ptr->mac_edfe_response_tx_active)) {
|
||||||
|
//ACK or EFDE Response
|
||||||
rf_ptr->mac_ack_tx_active = false;
|
rf_ptr->mac_ack_tx_active = false;
|
||||||
// For Ack, stop the active TX process
|
// For Ack, stop the active TX process
|
||||||
rf_ptr->macTxProcessActive = false;
|
rf_ptr->macTxProcessActive = false;
|
||||||
|
rf_ptr->mac_edfe_tx_active = false;
|
||||||
|
rf_ptr->mac_edfe_response_tx_active = false;
|
||||||
// If MAC had TX process active before Ack transmission,
|
// If MAC had TX process active before Ack transmission,
|
||||||
// the TX process has to be restarted in case the Ack transmission failed.
|
// the TX process has to be restarted in case the Ack transmission failed.
|
||||||
if (rf_ptr->active_pd_data_request) {
|
if (rf_ptr->active_pd_data_request) {
|
||||||
|
@ -1925,7 +2108,6 @@ static int8_t mcps_pd_data_request(protocol_interface_rf_mac_setup_s *rf_ptr, ma
|
||||||
{
|
{
|
||||||
rf_ptr->macTxRequestAck = false;
|
rf_ptr->macTxRequestAck = false;
|
||||||
|
|
||||||
|
|
||||||
memset(&(rf_ptr->mac_tx_status), 0, sizeof(mac_tx_status_t));
|
memset(&(rf_ptr->mac_tx_status), 0, sizeof(mac_tx_status_t));
|
||||||
rf_ptr->mac_cca_retry = 0;
|
rf_ptr->mac_cca_retry = 0;
|
||||||
rf_ptr->mac_tx_retry = 0;
|
rf_ptr->mac_tx_retry = 0;
|
||||||
|
@ -1934,8 +2116,8 @@ static int8_t mcps_pd_data_request(protocol_interface_rf_mac_setup_s *rf_ptr, ma
|
||||||
if (mcps_generic_packet_build(rf_ptr, buffer) != 0) {
|
if (mcps_generic_packet_build(rf_ptr, buffer) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rf_ptr->macTxRequestAck = buffer->fcf_dsn.ackRequested;
|
rf_ptr->macTxRequestAck = buffer->WaitResponse;
|
||||||
if (!rf_ptr->mac_ack_tx_active) {
|
if (!rf_ptr->mac_ack_tx_active && !rf_ptr->mac_edfe_tx_active) {
|
||||||
return mcps_pd_data_cca_trig(rf_ptr, buffer);
|
return mcps_pd_data_cca_trig(rf_ptr, buffer);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1943,6 +2125,24 @@ static int8_t mcps_pd_data_request(protocol_interface_rf_mac_setup_s *rf_ptr, ma
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t mcps_edfe_data_request(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer)
|
||||||
|
{
|
||||||
|
rf_ptr->macTxRequestAck = false;
|
||||||
|
memset(&(rf_ptr->mac_tx_status), 0, sizeof(mac_tx_status_t));
|
||||||
|
rf_ptr->mac_cca_retry = 0;
|
||||||
|
rf_ptr->mac_tx_retry = 0;
|
||||||
|
rf_ptr->mac_tx_start_channel = rf_ptr->mac_channel;
|
||||||
|
buffer->aux_header.frameCounter = 0xffffffff;
|
||||||
|
mac_csma_param_init(rf_ptr);
|
||||||
|
if (mcps_generic_packet_build(rf_ptr, buffer) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rf_ptr->macTxRequestAck = buffer->WaitResponse;//buffer->fcf_dsn.ackRequested;
|
||||||
|
|
||||||
|
return mcps_pd_data_cca_trig(rf_ptr, buffer);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int8_t mcps_pd_data_rebuild(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer)
|
int8_t mcps_pd_data_rebuild(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer)
|
||||||
{
|
{
|
||||||
if (mcps_generic_packet_rebuild(rf_ptr, buffer) != 0) {
|
if (mcps_generic_packet_rebuild(rf_ptr, buffer) != 0) {
|
||||||
|
@ -1955,7 +2155,10 @@ int8_t mcps_pd_data_rebuild(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_b
|
||||||
|
|
||||||
bool mac_is_ack_request_set(mac_pre_build_frame_t *buffer)
|
bool mac_is_ack_request_set(mac_pre_build_frame_t *buffer)
|
||||||
{
|
{
|
||||||
return buffer->fcf_dsn.ackRequested;
|
if (buffer->fcf_dsn.ackRequested || buffer->WaitResponse) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mac_convert_frame_type_to_fhss(uint8_t frame_type)
|
int mac_convert_frame_type_to_fhss(uint8_t frame_type)
|
||||||
|
@ -1979,11 +2182,20 @@ void mcps_sap_pd_req_queue_write(protocol_interface_rf_mac_setup_s *rf_mac_setup
|
||||||
if ((rf_mac_setup->macBroadcastDisabled == true) && !mac_is_ack_request_set(buffer)) {
|
if ((rf_mac_setup->macBroadcastDisabled == true) && !mac_is_ack_request_set(buffer)) {
|
||||||
goto push_to_queue;
|
goto push_to_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (buffer->ExtendedFrameExchange) {
|
||||||
|
//Update here state and store peer
|
||||||
|
memcpy(rf_mac_setup->mac_edfe_info->PeerAddr, buffer->DstAddr, 8);
|
||||||
|
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_CONNECTING;
|
||||||
|
}
|
||||||
if (rf_mac_setup->fhss_api && (buffer->asynch_request == false)) {
|
if (rf_mac_setup->fhss_api && (buffer->asynch_request == false)) {
|
||||||
uint16_t frame_length = buffer->mac_payload_length + buffer->headerIeLength + buffer->payloadsIeLength;
|
uint16_t frame_length = buffer->mac_payload_length + buffer->headerIeLength + buffer->payloadsIeLength;
|
||||||
if (rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer),
|
if (rf_mac_setup->fhss_api->check_tx_conditions(rf_mac_setup->fhss_api, !mac_is_ack_request_set(buffer),
|
||||||
buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), frame_length,
|
buffer->msduHandle, mac_convert_frame_type_to_fhss(buffer->fcf_dsn.frametype), frame_length,
|
||||||
rf_mac_setup->dev_driver->phy_driver->phy_header_length, rf_mac_setup->dev_driver->phy_driver->phy_tail_length) == false) {
|
rf_mac_setup->dev_driver->phy_driver->phy_header_length, rf_mac_setup->dev_driver->phy_driver->phy_tail_length) == false) {
|
||||||
|
if (buffer->ExtendedFrameExchange) {
|
||||||
|
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||||
|
}
|
||||||
goto push_to_queue;
|
goto push_to_queue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1992,10 +2204,16 @@ void mcps_sap_pd_req_queue_write(protocol_interface_rf_mac_setup_s *rf_mac_setup
|
||||||
if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) {
|
if (mcps_pd_data_request(rf_mac_setup, buffer) != 0) {
|
||||||
rf_mac_setup->mac_tx_result = MAC_TX_PRECOND_FAIL;
|
rf_mac_setup->mac_tx_result = MAC_TX_PRECOND_FAIL;
|
||||||
rf_mac_setup->macTxRequestAck = false;
|
rf_mac_setup->macTxRequestAck = false;
|
||||||
|
if (buffer->ExtendedFrameExchange) {
|
||||||
|
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||||
|
}
|
||||||
if (mcps_sap_pd_confirm(rf_mac_setup) != 0) {
|
if (mcps_sap_pd_confirm(rf_mac_setup) != 0) {
|
||||||
// can't send event, try calling error handler directly
|
// can't send event, try calling error handler directly
|
||||||
rf_mac_setup->mac_mcps_data_conf_fail.msduHandle = buffer->msduHandle;
|
rf_mac_setup->mac_mcps_data_conf_fail.msduHandle = buffer->msduHandle;
|
||||||
rf_mac_setup->mac_mcps_data_conf_fail.status = buffer->status;
|
rf_mac_setup->mac_mcps_data_conf_fail.status = buffer->status;
|
||||||
|
if (buffer->ExtendedFrameExchange) {
|
||||||
|
rf_mac_setup->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||||
|
}
|
||||||
mcps_sap_prebuild_frame_buffer_free(buffer);
|
mcps_sap_prebuild_frame_buffer_free(buffer);
|
||||||
rf_mac_setup->active_pd_data_request = NULL;
|
rf_mac_setup->active_pd_data_request = NULL;
|
||||||
mac_pd_data_confirm_failure_handle(rf_mac_setup);
|
mac_pd_data_confirm_failure_handle(rf_mac_setup);
|
||||||
|
@ -2133,12 +2351,6 @@ void mcps_sap_pre_parsed_frame_buffer_free(mac_pre_parsed_frame_t *buf)
|
||||||
|
|
||||||
mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data_ptr, uint16_t frame_length)
|
mac_pre_parsed_frame_t *mcps_sap_pre_parsed_frame_buffer_get(const uint8_t *data_ptr, uint16_t frame_length)
|
||||||
{
|
{
|
||||||
// check that system has enough space to handle the new packet
|
|
||||||
if (!ns_monitor_packet_allocation_allowed()) {
|
|
||||||
// stack can not handle new packets for routing
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mac_pre_parsed_frame_t *buffer = ns_dyn_mem_temporary_alloc(sizeof(mac_pre_parsed_frame_t) + frame_length);
|
mac_pre_parsed_frame_t *buffer = ns_dyn_mem_temporary_alloc(sizeof(mac_pre_parsed_frame_t) + frame_length);
|
||||||
|
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct arm_phy_sap_msg_s;
|
||||||
struct mcps_purge_s;
|
struct mcps_purge_s;
|
||||||
struct mcps_data_req_ie_list;
|
struct mcps_data_req_ie_list;
|
||||||
struct channel_list_s;
|
struct channel_list_s;
|
||||||
|
struct mcps_enhanced_frame_response_s;
|
||||||
|
|
||||||
/** Address types */
|
/** Address types */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -133,8 +134,12 @@ uint8_t mcps_sap_purge_reg_handler(struct protocol_interface_rf_mac_setup *rf_ma
|
||||||
|
|
||||||
int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_build_frame_t *buffer);
|
int8_t mcps_pd_data_rebuild(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_build_frame_t *buffer);
|
||||||
|
|
||||||
|
int8_t mcps_edfe_data_request(struct protocol_interface_rf_mac_setup *rf_ptr, mac_pre_build_frame_t *buffer);
|
||||||
|
|
||||||
int8_t mcps_generic_ack_data_request_init(struct protocol_interface_rf_mac_setup *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_ack_data_payload_t *ack_payload);
|
int8_t mcps_generic_ack_data_request_init(struct protocol_interface_rf_mac_setup *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const mcps_ack_data_payload_t *ack_payload);
|
||||||
|
|
||||||
|
int8_t mcps_generic_edfe_frame_init(struct protocol_interface_rf_mac_setup *rf_ptr, const mac_fcf_sequence_t *fcf, const uint8_t *data_ptr, const struct mcps_edfe_response_s *response);
|
||||||
|
|
||||||
int8_t mcps_generic_ack_build(struct protocol_interface_rf_mac_setup *rf_ptr, bool init_build);
|
int8_t mcps_generic_ack_build(struct protocol_interface_rf_mac_setup *rf_ptr, bool init_build);
|
||||||
|
|
||||||
int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage);
|
int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage);
|
||||||
|
|
|
@ -512,6 +512,10 @@ static int8_t mac_mlme_boolean_set(protocol_interface_rf_mac_setup_s *rf_mac_set
|
||||||
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_ACCEPT_ANY_BEACON, (uint8_t *)&value);
|
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_ACCEPT_ANY_BEACON, (uint8_t *)&value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case macEdfeForceStop:
|
||||||
|
return mac_data_edfe_force_stop(rf_mac_setup);
|
||||||
|
|
||||||
case macAcceptByPassUnknowDevice:
|
case macAcceptByPassUnknowDevice:
|
||||||
rf_mac_setup->mac_security_bypass_unknow_device = value;
|
rf_mac_setup->mac_security_bypass_unknow_device = value;
|
||||||
break;
|
break;
|
||||||
|
@ -807,6 +811,11 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
|
||||||
memcpy(rf_mac_setup->coord_long_address, set_req->value_pointer, 8);
|
memcpy(rf_mac_setup->coord_long_address, set_req->value_pointer, 8);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
case macSetDataWhitening:
|
||||||
|
pu8 = (uint8_t *) set_req->value_pointer;
|
||||||
|
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_DATA_WHITENING, pu8);
|
||||||
|
tr_debug("%s data whitening", *pu8 == (bool) true ? "Enable" : "Disable");
|
||||||
|
return 0;
|
||||||
case macCCAThresholdStart:
|
case macCCAThresholdStart:
|
||||||
pu8 = (uint8_t *) set_req->value_pointer;
|
pu8 = (uint8_t *) set_req->value_pointer;
|
||||||
mac_cca_thr_init(rf_mac_setup, *pu8, *((int8_t *)pu8 + 1), *((int8_t *)pu8 + 2), *((int8_t *)pu8 + 3));
|
mac_cca_thr_init(rf_mac_setup, *pu8, *((int8_t *)pu8 + 1), *((int8_t *)pu8 + 2), *((int8_t *)pu8 + 3));
|
||||||
|
@ -869,7 +878,7 @@ int8_t mac_mlme_get_req(struct protocol_interface_rf_mac_setup *rf_mac_setup, ml
|
||||||
if (!get_req || !rf_mac_setup) {
|
if (!get_req || !rf_mac_setup) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
mac_cca_threshold_s *cca_thr_table = NULL;
|
||||||
switch (get_req->attr) {
|
switch (get_req->attr) {
|
||||||
case macDeviceTable:
|
case macDeviceTable:
|
||||||
get_req->value_pointer = mac_sec_mib_device_description_get_attribute_index(rf_mac_setup, get_req->attr_index);
|
get_req->value_pointer = mac_sec_mib_device_description_get_attribute_index(rf_mac_setup, get_req->attr_index);
|
||||||
|
@ -899,6 +908,12 @@ int8_t mac_mlme_get_req(struct protocol_interface_rf_mac_setup *rf_mac_setup, ml
|
||||||
get_req->value_size = 4;
|
get_req->value_size = 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case macCCAThreshold:
|
||||||
|
cca_thr_table = mac_get_cca_threshold_table(rf_mac_setup);
|
||||||
|
get_req->value_size = cca_thr_table->number_of_channels;
|
||||||
|
get_req->value_pointer = cca_thr_table->ch_thresholds;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
get_req->status = MLME_UNSUPPORTED_ATTRIBUTE;
|
get_req->status = MLME_UNSUPPORTED_ATTRIBUTE;
|
||||||
break;
|
break;
|
||||||
|
@ -1706,6 +1721,7 @@ void mac_mlme_poll_req(protocol_interface_rf_mac_setup_s *cur, const mlme_poll_t
|
||||||
}
|
}
|
||||||
|
|
||||||
buf->fcf_dsn.frametype = FC_CMD_FRAME;
|
buf->fcf_dsn.frametype = FC_CMD_FRAME;
|
||||||
|
buf->WaitResponse = true;
|
||||||
buf->fcf_dsn.ackRequested = true;
|
buf->fcf_dsn.ackRequested = true;
|
||||||
buf->fcf_dsn.intraPan = true;
|
buf->fcf_dsn.intraPan = true;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
|
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
|
||||||
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
|
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
|
||||||
#include "MAC/rf_driver_storage.h"
|
#include "MAC/rf_driver_storage.h"
|
||||||
|
#include "Core/include/ns_monitor.h"
|
||||||
|
#include "ns_trace.h"
|
||||||
|
|
||||||
|
#define TRACE_GROUP "mPDs"
|
||||||
|
|
||||||
/* Define TX Timeot Period */
|
/* Define TX Timeot Period */
|
||||||
// Hardcoded to 1200ms. Should be changed dynamic: (FHSS) channel retries needs longer timeout
|
// Hardcoded to 1200ms. Should be changed dynamic: (FHSS) channel retries needs longer timeout
|
||||||
|
@ -148,6 +152,8 @@ static void mac_tx_done_state_set(protocol_interface_rf_mac_setup_s *rf_ptr, mac
|
||||||
}
|
}
|
||||||
rf_ptr->macRfRadioTxActive = false;
|
rf_ptr->macRfRadioTxActive = false;
|
||||||
rf_ptr->macTxProcessActive = false;
|
rf_ptr->macTxProcessActive = false;
|
||||||
|
rf_ptr->mac_edfe_response_tx_active = false;
|
||||||
|
rf_ptr->mac_edfe_tx_active = false;
|
||||||
mcps_sap_pd_confirm(rf_ptr);
|
mcps_sap_pd_confirm(rf_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +181,7 @@ int8_t mac_plme_cca_req(protocol_interface_rf_mac_setup_s *rf_mac_setup)
|
||||||
|
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
if (rf_mac_setup->mac_ack_tx_active) {
|
if (rf_mac_setup->mac_ack_tx_active || (rf_mac_setup->mac_edfe_tx_active && rf_mac_setup->mac_edfe_response_tx_active)) {
|
||||||
buffer = tx_buf->enhanced_ack_buf;
|
buffer = tx_buf->enhanced_ack_buf;
|
||||||
length = tx_buf->ack_len;
|
length = tx_buf->ack_len;
|
||||||
} else {
|
} else {
|
||||||
|
@ -371,6 +377,9 @@ static void mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr, uint
|
||||||
|
|
||||||
static void mac_sap_no_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr)
|
static void mac_sap_no_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr)
|
||||||
{
|
{
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
tr_info("%u no_ack", mac_mcps_sap_get_phy_timestamp(rf_ptr));
|
||||||
|
#endif
|
||||||
rf_ptr->macRfRadioTxActive = false;
|
rf_ptr->macRfRadioTxActive = false;
|
||||||
if (rf_ptr->mac_tx_retry < rf_ptr->mac_mlme_retry_max) {
|
if (rf_ptr->mac_tx_retry < rf_ptr->mac_mlme_retry_max) {
|
||||||
rf_ptr->mac_cca_retry = 0;
|
rf_ptr->mac_cca_retry = 0;
|
||||||
|
@ -424,6 +433,17 @@ static void mac_data_ack_tx_finish(protocol_interface_rf_mac_setup_s *rf_ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t mac_data_edfe_force_stop(protocol_interface_rf_mac_setup_s *rf_ptr)
|
||||||
|
{
|
||||||
|
if (!rf_ptr->mac_edfe_enabled || rf_ptr->mac_edfe_info->state != MAC_EDFE_FRAME_WAIT_DATA) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//Set to idle
|
||||||
|
rf_ptr->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||||
|
mac_data_ack_tx_finish(rf_ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry)
|
static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -436,6 +456,9 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
||||||
if (rf_ptr->mac_ack_tx_active) {
|
if (rf_ptr->mac_ack_tx_active) {
|
||||||
//Accept direct non crypted acks and crypted only if neighbor is at list
|
//Accept direct non crypted acks and crypted only if neighbor is at list
|
||||||
if (rf_ptr->ack_tx_possible) {
|
if (rf_ptr->ack_tx_possible) {
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
tr_info("%u TX_start %u", mac_mcps_sap_get_phy_timestamp(rf_ptr), rf_ptr->mac_channel);
|
||||||
|
#endif
|
||||||
return PHY_TX_ALLOWED;
|
return PHY_TX_ALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,7 +470,14 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
||||||
return PHY_TX_NOT_ALLOWED;
|
return PHY_TX_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rf_ptr->mac_edfe_tx_active) {
|
||||||
|
return PHY_TX_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request)) {
|
if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request)) {
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
tr_info("%u TX_start %u", mac_mcps_sap_get_phy_timestamp(rf_ptr), rf_ptr->mac_channel);
|
||||||
|
#endif
|
||||||
rf_ptr->active_pd_data_request->initial_tx_channel = rf_ptr->mac_channel;
|
rf_ptr->active_pd_data_request->initial_tx_channel = rf_ptr->mac_channel;
|
||||||
int8_t channel_cca_threshold = mac_cca_thr_get_dbm(rf_ptr, rf_ptr->mac_channel);
|
int8_t channel_cca_threshold = mac_cca_thr_get_dbm(rf_ptr, rf_ptr->mac_channel);
|
||||||
if (CCA_FAILED_DBM != channel_cca_threshold) {
|
if (CCA_FAILED_DBM != channel_cca_threshold) {
|
||||||
|
@ -495,14 +525,34 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
||||||
return PHY_RESTART_CSMA;
|
return PHY_RESTART_CSMA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
tr_info("%u TX_start %u", mac_mcps_sap_get_phy_timestamp(rf_ptr), rf_ptr->mac_channel);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rf_ptr->mac_ack_tx_active) {
|
if (rf_ptr->mac_ack_tx_active) {
|
||||||
mac_data_ack_tx_finish(rf_ptr);
|
mac_data_ack_tx_finish(rf_ptr);
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
tr_info("%u TX_done", mac_mcps_sap_get_phy_timestamp(rf_ptr));
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
if (rf_ptr->mac_edfe_tx_active) {
|
||||||
|
if (rf_ptr->mac_edfe_response_tx_active) {
|
||||||
|
//Stop process here
|
||||||
|
rf_ptr->mac_edfe_response_tx_active = false;
|
||||||
|
rf_ptr->mac_edfe_tx_active = false;
|
||||||
|
if ((status == PHY_LINK_TX_DONE || status == PHY_LINK_TX_SUCCESS) && rf_ptr->mac_edfe_info->state == MAC_EDFE_FRAME_TX_FINAL_FRAME) {
|
||||||
|
//Set to idle
|
||||||
|
rf_ptr->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||||
|
}
|
||||||
|
mac_data_ack_tx_finish(rf_ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Do not update CCA count when Ack is received, it was already updated with PHY_LINK_TX_SUCCESS event
|
// Do not update CCA count when Ack is received, it was already updated with PHY_LINK_TX_SUCCESS event
|
||||||
// Do not update CCA count when CCA_OK is received, PHY_LINK_TX_SUCCESS will update it
|
// Do not update CCA count when CCA_OK is received, PHY_LINK_TX_SUCCESS will update it
|
||||||
if ((status != PHY_LINK_TX_DONE) && (status != PHY_LINK_TX_DONE_PENDING) && (status != PHY_LINK_CCA_OK)) {
|
if ((status != PHY_LINK_TX_DONE) && (status != PHY_LINK_TX_DONE_PENDING) && (status != PHY_LINK_CCA_OK)) {
|
||||||
|
@ -510,6 +560,11 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r
|
||||||
* PHY_LINK_TX_FAIL either happened during transmission or when waiting Ack -> we must use the CCA count given by PHY.
|
* PHY_LINK_TX_FAIL either happened during transmission or when waiting Ack -> we must use the CCA count given by PHY.
|
||||||
*/
|
*/
|
||||||
if ((cca_retry == 0) && (status != PHY_LINK_TX_FAIL)) {
|
if ((cca_retry == 0) && (status != PHY_LINK_TX_FAIL)) {
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
if (status != PHY_LINK_CCA_FAIL) {
|
||||||
|
tr_info("%u TX_done", mac_mcps_sap_get_phy_timestamp(rf_ptr));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
cca_retry = 1;
|
cca_retry = 1;
|
||||||
}
|
}
|
||||||
rf_ptr->mac_tx_status.cca_cnt += cca_retry;
|
rf_ptr->mac_tx_status.cca_cnt += cca_retry;
|
||||||
|
@ -671,7 +726,9 @@ static int8_t mac_pd_sap_validate_fcf(protocol_interface_rf_mac_setup_s *rf_ptr,
|
||||||
switch (fcf_read->frametype) {
|
switch (fcf_read->frametype) {
|
||||||
case FC_DATA_FRAME:
|
case FC_DATA_FRAME:
|
||||||
if (fcf_read->SrcAddrMode == MAC_ADDR_MODE_NONE) {
|
if (fcf_read->SrcAddrMode == MAC_ADDR_MODE_NONE) {
|
||||||
return -1;
|
if (fcf_read->DstAddrMode == MAC_ADDR_MODE_NONE || fcf_read->frameVersion != MAC_FRAME_VERSION_2015) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
} else if (fcf_read->DstAddrMode == MAC_ADDR_MODE_NONE && fcf_read->frameVersion != MAC_FRAME_VERSION_2015) {
|
} else if (fcf_read->DstAddrMode == MAC_ADDR_MODE_NONE && fcf_read->frameVersion != MAC_FRAME_VERSION_2015) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -821,13 +878,44 @@ static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr,
|
||||||
return mcps_generic_ack_build(rf_ptr, true);
|
return mcps_generic_ack_build(rf_ptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int8_t mac_pd_sap_generate_edfe_response(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind, mcps_edfe_response_t *response)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (rf_ptr->mac_ack_tx_active) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rf_ptr->mac_edfe_info->state == MAC_EDFE_FRAME_CONNECTED && rf_ptr->macRfRadioTxActive && rf_ptr->active_pd_data_request) {
|
||||||
|
timer_mac_stop(rf_ptr);
|
||||||
|
rf_ptr->macRfRadioTxActive = false;
|
||||||
|
rf_ptr->macTxProcessActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mcps_generic_edfe_frame_init(rf_ptr, fcf_read, pd_data_ind->data_ptr, response)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response->wait_response) {
|
||||||
|
return mcps_edfe_data_request(rf_ptr, rf_ptr->active_pd_data_request);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mcps_generic_ack_build(rf_ptr, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static mac_pre_parsed_frame_t *mac_pd_sap_allocate_receive_buffer(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind)
|
static mac_pre_parsed_frame_t *mac_pd_sap_allocate_receive_buffer(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind)
|
||||||
{
|
{
|
||||||
|
// Unless receiving Ack, check that system has enough space to handle the new packet
|
||||||
|
if (fcf_read->frametype != FC_ACK_FRAME) {
|
||||||
|
if (!ns_monitor_packet_allocation_allowed()) {
|
||||||
|
// stack can not handle new packets for routing
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
mac_pre_parsed_frame_t *buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len);
|
mac_pre_parsed_frame_t *buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Copy Pre Parsed values
|
//Copy Pre Parsed values
|
||||||
buffer->fcf_dsn = *fcf_read;
|
buffer->fcf_dsn = *fcf_read;
|
||||||
buffer->timestamp = mac_pd_sap_get_phy_rx_time(rf_ptr);
|
buffer->timestamp = mac_pd_sap_get_phy_rx_time(rf_ptr);
|
||||||
|
@ -922,6 +1010,10 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
|
||||||
if (pd_data_ind->data_len < 3) {
|
if (pd_data_ind->data_len < 3) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
tr_info("%u RX_start", mac_pd_sap_get_phy_rx_time(rf_ptr));
|
||||||
|
tr_info("%u RX_done", mac_mcps_sap_get_phy_timestamp(rf_ptr));
|
||||||
|
#endif
|
||||||
mac_cca_threshold_event_send(rf_ptr, rf_ptr->mac_channel, pd_data_ind->dbm);
|
mac_cca_threshold_event_send(rf_ptr, rf_ptr->mac_channel, pd_data_ind->dbm);
|
||||||
mac_fcf_sequence_t fcf_read;
|
mac_fcf_sequence_t fcf_read;
|
||||||
const uint8_t *ptr = mac_header_parse_fcf_dsn(&fcf_read, pd_data_ind->data_ptr);
|
const uint8_t *ptr = mac_header_parse_fcf_dsn(&fcf_read, pd_data_ind->data_ptr);
|
||||||
|
@ -953,6 +1045,77 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (rf_ptr->mac_edfe_enabled && !fcf_read.ackRequested && fcf_read.frameVersion == MAC_FRAME_VERSION_2015 && buffer->fcf_dsn.frametype == FC_DATA_FRAME) {
|
||||||
|
mcps_edfe_response_t response;
|
||||||
|
mac_api_t *mac_api = get_sw_mac_api(rf_ptr);
|
||||||
|
response.ie_elements.payloadIeList = buffer->payloadsIePtr;
|
||||||
|
response.ie_elements.payloadIeListLength = buffer->payloadsIeLength;
|
||||||
|
response.ie_elements.headerIeList = buffer->headerIePtr;
|
||||||
|
response.ie_elements.headerIeListLength = buffer->headerIeLength;
|
||||||
|
response.DstAddrMode = buffer->fcf_dsn.DstAddrMode;
|
||||||
|
response.SrcAddrMode = buffer->fcf_dsn.SrcAddrMode;
|
||||||
|
response.rssi = pd_data_ind->dbm;
|
||||||
|
if (buffer->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_64_BIT) {
|
||||||
|
mac_header_get_src_address(&fcf_read, pd_data_ind->data_ptr, response.Address);
|
||||||
|
} else {
|
||||||
|
memcpy(response.Address, rf_ptr->mac_edfe_info->PeerAddr, 8);
|
||||||
|
}
|
||||||
|
if (rf_ptr->mac_edfe_info->state == MAC_EDFE_FRAME_CONNECTING && rf_ptr->active_pd_data_request) {
|
||||||
|
response.message_handle = rf_ptr->active_pd_data_request->msduHandle;
|
||||||
|
response.use_message_handle_to_discover = true;
|
||||||
|
} else {
|
||||||
|
response.use_message_handle_to_discover = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mac_api->edfe_ind_cb(mac_api, &response);
|
||||||
|
|
||||||
|
response.DstAddrMode = MAC_ADDR_MODE_64_BIT;
|
||||||
|
switch (response.edfe_message_status) {
|
||||||
|
|
||||||
|
case MCPS_EDFE_RESPONSE_FRAME:
|
||||||
|
if (buffer->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_64_BIT) {
|
||||||
|
memcpy(rf_ptr->mac_edfe_info->PeerAddr, response.Address, 8);
|
||||||
|
}
|
||||||
|
rf_ptr->mac_edfe_info->state = MAC_EDFE_FRAME_WAIT_DATA;
|
||||||
|
if (mac_pd_sap_generate_edfe_response(rf_ptr, &fcf_read, pd_data_ind, &response)) {
|
||||||
|
goto ERROR_HANDLER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MCPS_EDFE_TX_FRAME:
|
||||||
|
rf_ptr->mac_edfe_info->state = MAC_EDFE_FRAME_CONNECTED;
|
||||||
|
if (mac_pd_sap_generate_edfe_response(rf_ptr, &fcf_read, pd_data_ind, &response)) {
|
||||||
|
goto ERROR_HANDLER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MCPS_EDFE_FINAL_FRAME_TX:
|
||||||
|
if (mac_pd_sap_generate_edfe_response(rf_ptr, &fcf_read, pd_data_ind, &response)) {
|
||||||
|
goto ERROR_HANDLER;
|
||||||
|
}
|
||||||
|
rf_ptr->mac_edfe_info->state = MAC_EDFE_FRAME_TX_FINAL_FRAME;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MCPS_EDFE_FINAL_FRAME_RX:
|
||||||
|
//Mark session closed
|
||||||
|
rf_ptr->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||||
|
rf_ptr->mac_edfe_tx_active = false;
|
||||||
|
if (mac_data_interface_tx_done_by_ack_cb(rf_ptr, buffer)) {
|
||||||
|
mcps_sap_pre_parsed_frame_buffer_free(buffer);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case MCPS_EDFE_MALFORMED_FRAME:
|
||||||
|
goto ERROR_HANDLER;
|
||||||
|
|
||||||
|
case MCPS_EDFE_NORMAL_FRAME:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
|
|
|
@ -59,4 +59,6 @@ void mac_csma_backoff_start(struct protocol_interface_rf_mac_setup *rf_mac_setup
|
||||||
*/
|
*/
|
||||||
void mac_pd_sap_state_machine(struct protocol_interface_rf_mac_setup *rf_mac_setup);
|
void mac_pd_sap_state_machine(struct protocol_interface_rf_mac_setup *rf_mac_setup);
|
||||||
|
|
||||||
|
int8_t mac_data_edfe_force_stop(struct protocol_interface_rf_mac_setup *rf_ptr);
|
||||||
|
|
||||||
#endif /* MAC_PD_SAP_H_ */
|
#endif /* MAC_PD_SAP_H_ */
|
||||||
|
|
|
@ -54,6 +54,7 @@ static int8_t ns_sw_mac_initialize(mac_api_t *api, mcps_data_confirm *mcps_data_
|
||||||
mcps_data_indication *mcps_data_ind_cb, mcps_purge_confirm *purge_conf_cb,
|
mcps_data_indication *mcps_data_ind_cb, mcps_purge_confirm *purge_conf_cb,
|
||||||
mlme_confirm *mlme_conf_callback, mlme_indication *mlme_ind_callback, int8_t parent_id);
|
mlme_confirm *mlme_conf_callback, mlme_indication *mlme_ind_callback, int8_t parent_id);
|
||||||
static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication_ext *data_ind_cb, mcps_data_confirm_ext *data_cnf_cb, mcps_ack_data_req_ext *ack_data_req_cb);
|
static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication_ext *data_ind_cb, mcps_data_confirm_ext *data_cnf_cb, mcps_ack_data_req_ext *ack_data_req_cb);
|
||||||
|
static int8_t ns_sw_mac_api_enable_edfe_ext(mac_api_t *api, mcps_edfe_handler *edfe_ind_cb);
|
||||||
|
|
||||||
static void mlme_req(const mac_api_t *api, mlme_primitive id, const void *data);
|
static void mlme_req(const mac_api_t *api, mlme_primitive id, const void *data);
|
||||||
static void mcps_req(const mac_api_t *api, const mcps_data_req_t *data);
|
static void mcps_req(const mac_api_t *api, const mcps_data_req_t *data);
|
||||||
|
@ -67,6 +68,7 @@ static int8_t sw_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_li
|
||||||
static int8_t sw_mac_net_phy_config_parser(int8_t driver_id, const uint8_t *data, uint16_t length);
|
static int8_t sw_mac_net_phy_config_parser(int8_t driver_id, const uint8_t *data, uint16_t length);
|
||||||
static int8_t sw_mac_storage_decription_sizes_get(const mac_api_t *api, mac_description_storage_size_t *buffer);
|
static int8_t sw_mac_storage_decription_sizes_get(const mac_api_t *api, mac_description_storage_size_t *buffer);
|
||||||
|
|
||||||
|
|
||||||
static int8_t sw_mac_storage_decription_sizes_get(const mac_api_t *api, mac_description_storage_size_t *buffer)
|
static int8_t sw_mac_storage_decription_sizes_get(const mac_api_t *api, mac_description_storage_size_t *buffer)
|
||||||
{
|
{
|
||||||
if (!api || !buffer || api != mac_store.mac_api) {
|
if (!api || !buffer || api != mac_store.mac_api) {
|
||||||
|
@ -127,6 +129,7 @@ mac_api_t *ns_sw_mac_create(int8_t rf_driver_id, mac_description_storage_size_t
|
||||||
|
|
||||||
this->mac_initialize = &ns_sw_mac_initialize;
|
this->mac_initialize = &ns_sw_mac_initialize;
|
||||||
this->mac_mcps_extension_enable = &ns_sw_mac_api_enable_mcps_ext;
|
this->mac_mcps_extension_enable = &ns_sw_mac_api_enable_mcps_ext;
|
||||||
|
this->mac_mcps_edfe_enable = &ns_sw_mac_api_enable_edfe_ext;
|
||||||
this->mlme_req = &mlme_req;
|
this->mlme_req = &mlme_req;
|
||||||
this->mcps_data_req = &mcps_req;
|
this->mcps_data_req = &mcps_req;
|
||||||
this->mcps_data_req_ext = &mcps_req_ext;
|
this->mcps_data_req_ext = &mcps_req_ext;
|
||||||
|
@ -314,6 +317,33 @@ static int8_t ns_sw_mac_api_enable_mcps_ext(mac_api_t *api, mcps_data_indication
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int8_t ns_sw_mac_api_enable_edfe_ext(mac_api_t *api, mcps_edfe_handler *edfe_ind_cb)
|
||||||
|
{
|
||||||
|
//TODO: Find from linked list instead
|
||||||
|
if (api != mac_store.mac_api) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mac_api_t *cur = mac_store.mac_api;
|
||||||
|
|
||||||
|
if (!mac_store.setup->mac_extension_enabled) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cur->edfe_ind_cb = edfe_ind_cb;
|
||||||
|
if (edfe_ind_cb) {
|
||||||
|
ns_dyn_mem_free(mac_store.setup->mac_edfe_info);
|
||||||
|
mac_store.setup->mac_edfe_info = ns_dyn_mem_alloc(sizeof(mac_mcps_edfe_frame_info_t));
|
||||||
|
if (!mac_store.setup->mac_edfe_info) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
mac_store.setup->mac_edfe_info->state = MAC_EDFE_FRAME_IDLE;
|
||||||
|
mac_store.setup->mac_edfe_enabled = true;
|
||||||
|
} else {
|
||||||
|
mac_store.setup->mac_edfe_enabled = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
mac_api_t *get_sw_mac_api(protocol_interface_rf_mac_setup_s *setup)
|
mac_api_t *get_sw_mac_api(protocol_interface_rf_mac_setup_s *setup)
|
||||||
{
|
{
|
||||||
if (!mac_store.mac_api || mac_store.mac_api->parent_id == -1 || mac_store.setup != setup) {
|
if (!mac_store.mac_api || mac_store.mac_api->parent_id == -1 || mac_store.setup != setup) {
|
||||||
|
|
|
@ -498,6 +498,7 @@ static void mpl_buffer_transmit(mpl_domain_t *domain, mpl_buffered_message_t *me
|
||||||
memcpy(buf->src_sa.address, message->message + IPV6_HDROFF_SRC_ADDR, 16);
|
memcpy(buf->src_sa.address, message->message + IPV6_HDROFF_SRC_ADDR, 16);
|
||||||
|
|
||||||
ipv6_transmit_multicast_on_interface(buf, domain->interface);
|
ipv6_transmit_multicast_on_interface(buf, domain->interface);
|
||||||
|
tr_debug("MPL transmit %u", mpl_buffer_sequence(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mpl_buffer_inconsistent(const mpl_domain_t *domain, mpl_buffered_message_t *message)
|
static void mpl_buffer_inconsistent(const mpl_domain_t *domain, mpl_buffered_message_t *message)
|
||||||
|
@ -853,6 +854,7 @@ bool mpl_forwarder_process_message(buffer_t *buf, mpl_domain_t *domain, bool see
|
||||||
const uint8_t *seed_id = opt_data + 2;
|
const uint8_t *seed_id = opt_data + 2;
|
||||||
uint8_t seed_id_len = mpl_seed_id_len(seed_id_type);
|
uint8_t seed_id_len = mpl_seed_id_len(seed_id_type);
|
||||||
|
|
||||||
|
tr_debug("MPL %s %"PRIu8, seeding ? "transmit" : "received", sequence);
|
||||||
/* Special handling - just ignore the MPL option if receiving loopback copy.
|
/* Special handling - just ignore the MPL option if receiving loopback copy.
|
||||||
* (MPL gets to process the outgoing message, and with seeding true - when
|
* (MPL gets to process the outgoing message, and with seeding true - when
|
||||||
* looping back, we want to accept it without MPL getting in the way).
|
* looping back, we want to accept it without MPL getting in the way).
|
||||||
|
|
|
@ -238,6 +238,7 @@ typedef struct arm_15_4_mac_parameters_t {
|
||||||
uint16_t pan_id;
|
uint16_t pan_id;
|
||||||
uint16_t mac_short_address;
|
uint16_t mac_short_address;
|
||||||
mac_cordinator_s mac_cordinator_info;
|
mac_cordinator_s mac_cordinator_info;
|
||||||
|
cca_threshold_table_s cca_thr_table;
|
||||||
uint8_t number_of_fhss_channel_retries;
|
uint8_t number_of_fhss_channel_retries;
|
||||||
/* MAC Beacon info */
|
/* MAC Beacon info */
|
||||||
uint8_t *mac_beacon_payload;
|
uint8_t *mac_beacon_payload;
|
||||||
|
|
|
@ -61,17 +61,26 @@ typedef struct {
|
||||||
|
|
||||||
typedef NS_LIST_HEAD(kmp_sec_prot_entry_t, link) kmp_sec_prot_list_t;
|
typedef NS_LIST_HEAD(kmp_sec_prot_entry_t, link) kmp_sec_prot_list_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t instance_id; /**< Message interface instance identifier */
|
||||||
|
uint8_t header_size; /**< Message interface header size */
|
||||||
|
kmp_service_msg_if_send *send; /**< Message interface callback to send KMP frames */
|
||||||
|
ns_list_link_t link; /**< Link */
|
||||||
|
} kmp_msg_if_entry_t;
|
||||||
|
|
||||||
|
typedef NS_LIST_HEAD(kmp_msg_if_entry_t, link) kmp_msg_if_list_t;
|
||||||
|
|
||||||
struct kmp_service_s {
|
struct kmp_service_s {
|
||||||
kmp_sec_prot_list_t sec_prot_list; /**< Security protocols list */
|
kmp_sec_prot_list_t sec_prot_list; /**< Security protocols list */
|
||||||
|
kmp_msg_if_list_t msg_if_list; /**< Message interface list */
|
||||||
kmp_service_incoming_ind *incoming_ind; /**< Callback to application to indicate incoming KMP frame */
|
kmp_service_incoming_ind *incoming_ind; /**< Callback to application to indicate incoming KMP frame */
|
||||||
kmp_service_tx_status_ind *tx_status_ind; /**< Callback to application to indicate TX status */
|
kmp_service_tx_status_ind *tx_status_ind; /**< Callback to application to indicate TX status */
|
||||||
kmp_service_addr_get *addr_get; /**< Callback to get addresses related to KMP */
|
kmp_service_addr_get *addr_get; /**< Callback to get addresses related to KMP */
|
||||||
|
kmp_service_ip_addr_get *ip_addr_get; /**< Callback to get IP addresses related to KMP */
|
||||||
kmp_service_api_get *api_get; /**< Callback to get KMP API from a service */
|
kmp_service_api_get *api_get; /**< Callback to get KMP API from a service */
|
||||||
kmp_service_msg_if_send *send; /**< Callback to send KMP frames */
|
|
||||||
kmp_service_timer_if_start *timer_start; /**< Callback to start timer */
|
kmp_service_timer_if_start *timer_start; /**< Callback to start timer */
|
||||||
kmp_service_timer_if_stop *timer_stop; /**< Callback to stop timer */
|
kmp_service_timer_if_stop *timer_stop; /**< Callback to stop timer */
|
||||||
kmp_service_event_if_event_send *event_send; /**< Callback to send event */
|
kmp_service_event_if_event_send *event_send; /**< Callback to send event */
|
||||||
uint8_t header_size; /**< Header size */
|
|
||||||
ns_list_link_t link; /**< Link */
|
ns_list_link_t link; /**< Link */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,6 +94,7 @@ static NS_LIST_DEFINE(kmp_service_list, kmp_service_t, link);
|
||||||
// KMP instance identifier value
|
// KMP instance identifier value
|
||||||
static uint8_t kmp_instance_identifier = 0;
|
static uint8_t kmp_instance_identifier = 0;
|
||||||
|
|
||||||
|
static kmp_msg_if_entry_t *kmp_api_msg_if_get(kmp_service_t *service, uint8_t msg_if_instance_id);
|
||||||
static void kmp_api_sec_prot_create_confirm(sec_prot_t *prot, sec_prot_result_e result);
|
static void kmp_api_sec_prot_create_confirm(sec_prot_t *prot, sec_prot_result_e result);
|
||||||
static void kmp_api_sec_prot_create_indication(sec_prot_t *prot);
|
static void kmp_api_sec_prot_create_indication(sec_prot_t *prot);
|
||||||
static void kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys);
|
static void kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys);
|
||||||
|
@ -94,12 +104,13 @@ static void kmp_sec_prot_timer_start(sec_prot_t *prot);
|
||||||
static void kmp_sec_prot_timer_stop(sec_prot_t *prot);
|
static void kmp_sec_prot_timer_stop(sec_prot_t *prot);
|
||||||
static void kmp_sec_prot_state_machine_call(sec_prot_t *prot);
|
static void kmp_sec_prot_state_machine_call(sec_prot_t *prot);
|
||||||
static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64);
|
static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64);
|
||||||
|
static void kmp_sec_prot_ip_addr_get(sec_prot_t *prot, uint8_t *address);
|
||||||
static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type);
|
static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type);
|
||||||
static void kmp_sec_prot_receive_disable(sec_prot_t *prot);
|
static void kmp_sec_prot_receive_disable(sec_prot_t *prot);
|
||||||
|
|
||||||
#define kmp_api_get_from_prot(prot) (kmp_api_t *)(((uint8_t *)prot) - offsetof(kmp_api_t, sec_prot));
|
#define kmp_api_get_from_prot(prot) (kmp_api_t *)(((uint8_t *)prot) - offsetof(kmp_api_t, sec_prot));
|
||||||
|
|
||||||
kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_t *prot_cfg, sec_timer_cfg_t *timer_cfg)
|
kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, uint8_t msg_if_instance_id, sec_cfg_t *sec_cfg)
|
||||||
{
|
{
|
||||||
if (!service) {
|
if (!service) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -120,6 +131,11 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_
|
||||||
// Size for security protocol internal data
|
// Size for security protocol internal data
|
||||||
uint16_t sec_size = sec_prot->size();
|
uint16_t sec_size = sec_prot->size();
|
||||||
|
|
||||||
|
kmp_msg_if_entry_t *msg_if_entry = kmp_api_msg_if_get(service, msg_if_instance_id);
|
||||||
|
if (!msg_if_entry) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
kmp_api_t *kmp = ns_dyn_mem_temporary_alloc(sizeof(kmp_api_t) + sec_size);
|
kmp_api_t *kmp = ns_dyn_mem_temporary_alloc(sizeof(kmp_api_t) + sec_size);
|
||||||
if (!kmp) {
|
if (!kmp) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -137,9 +153,10 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_
|
||||||
kmp->timer_start_pending = false;
|
kmp->timer_start_pending = false;
|
||||||
kmp->receive_disable = false;
|
kmp->receive_disable = false;
|
||||||
|
|
||||||
memset(&kmp->sec_prot, 0, sec_size);
|
memset(&kmp->sec_prot, 0, sec_size + offsetof(sec_prot_t, data));
|
||||||
|
|
||||||
kmp->sec_prot.header_size = service->header_size;
|
kmp->sec_prot.header_size = msg_if_entry->header_size;
|
||||||
|
kmp->sec_prot.receive_peer_hdr_size = msg_if_entry->header_size;
|
||||||
kmp->sec_prot.create_conf = kmp_api_sec_prot_create_confirm;
|
kmp->sec_prot.create_conf = kmp_api_sec_prot_create_confirm;
|
||||||
kmp->sec_prot.create_ind = kmp_api_sec_prot_create_indication;
|
kmp->sec_prot.create_ind = kmp_api_sec_prot_create_indication;
|
||||||
kmp->sec_prot.finished_ind = kmp_api_sec_prot_finished_indication;
|
kmp->sec_prot.finished_ind = kmp_api_sec_prot_finished_indication;
|
||||||
|
@ -149,10 +166,11 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_
|
||||||
kmp->sec_prot.timer_stop = kmp_sec_prot_timer_stop;
|
kmp->sec_prot.timer_stop = kmp_sec_prot_timer_stop;
|
||||||
kmp->sec_prot.state_machine_call = kmp_sec_prot_state_machine_call;
|
kmp->sec_prot.state_machine_call = kmp_sec_prot_state_machine_call;
|
||||||
kmp->sec_prot.addr_get = kmp_sec_prot_eui64_addr_get;
|
kmp->sec_prot.addr_get = kmp_sec_prot_eui64_addr_get;
|
||||||
|
kmp->sec_prot.ip_addr_get = kmp_sec_prot_ip_addr_get;
|
||||||
kmp->sec_prot.type_get = kmp_sec_prot_by_type_get;
|
kmp->sec_prot.type_get = kmp_sec_prot_by_type_get;
|
||||||
kmp->sec_prot.receive_disable = kmp_sec_prot_receive_disable;
|
kmp->sec_prot.receive_disable = kmp_sec_prot_receive_disable;
|
||||||
kmp->sec_prot.prot_cfg = prot_cfg;
|
kmp->sec_prot.sec_cfg = sec_cfg;
|
||||||
kmp->sec_prot.timer_cfg = timer_cfg;
|
kmp->sec_prot.msg_if_instance_id = msg_if_instance_id;
|
||||||
|
|
||||||
if (sec_prot->init(&kmp->sec_prot) < 0) {
|
if (sec_prot->init(&kmp->sec_prot) < 0) {
|
||||||
ns_dyn_mem_free(kmp);
|
ns_dyn_mem_free(kmp);
|
||||||
|
@ -162,6 +180,16 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_
|
||||||
return (kmp_api_t *) kmp;
|
return (kmp_api_t *) kmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static kmp_msg_if_entry_t *kmp_api_msg_if_get(kmp_service_t *service, uint8_t msg_if_instance_id)
|
||||||
|
{
|
||||||
|
ns_list_foreach(kmp_msg_if_entry_t, list_entry, &service->msg_if_list) {
|
||||||
|
if (list_entry->instance_id == msg_if_instance_id) {
|
||||||
|
return list_entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int8_t kmp_api_start(kmp_api_t *kmp)
|
int8_t kmp_api_start(kmp_api_t *kmp)
|
||||||
{
|
{
|
||||||
if (kmp->timer_start_pending) {
|
if (kmp->timer_start_pending) {
|
||||||
|
@ -216,12 +244,19 @@ static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size)
|
||||||
kmp_type_e kmp_id = kmp->type;
|
kmp_type_e kmp_id = kmp->type;
|
||||||
if (kmp_id > IEEE_802_1X_INITIAL_KEY) {
|
if (kmp_id > IEEE_802_1X_INITIAL_KEY) {
|
||||||
kmp_id -= IEEE_802_1X_INITIAL_KEY;
|
kmp_id -= IEEE_802_1X_INITIAL_KEY;
|
||||||
|
} else if (kmp_id == RADIUS_IEEE_802_1X_MKA) {
|
||||||
|
kmp_id = IEEE_802_1X_MKA;
|
||||||
|
}
|
||||||
|
|
||||||
|
kmp_msg_if_entry_t *msg_if_entry = kmp_api_msg_if_get(kmp->service, prot->msg_if_instance_id);
|
||||||
|
if (!msg_if_entry) {
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t result = -1;
|
int8_t result = -1;
|
||||||
|
|
||||||
if (kmp->service->send) {
|
if (msg_if_entry->send) {
|
||||||
result = kmp->service->send(kmp->service, kmp_id, kmp->addr, pdu, size, kmp->instance_identifier);
|
result = msg_if_entry->send(kmp->service, prot->msg_if_instance_id, kmp_id, kmp->addr, pdu, size, kmp->instance_identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
@ -267,6 +302,13 @@ static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kmp_sec_prot_ip_addr_get(sec_prot_t *prot, uint8_t *address)
|
||||||
|
{
|
||||||
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
||||||
|
|
||||||
|
kmp->service->ip_addr_get(kmp->service, kmp, address);
|
||||||
|
}
|
||||||
|
|
||||||
static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type)
|
static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type)
|
||||||
{
|
{
|
||||||
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
||||||
|
@ -277,9 +319,15 @@ static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type)
|
||||||
case SEC_PROT_TYPE_EAP_TLS:
|
case SEC_PROT_TYPE_EAP_TLS:
|
||||||
kmp_type = IEEE_802_1X_MKA;
|
kmp_type = IEEE_802_1X_MKA;
|
||||||
break;
|
break;
|
||||||
|
case SEC_PROT_TYPE_RADIUS_EAP_TLS:
|
||||||
|
kmp_type = RADIUS_IEEE_802_1X_MKA;
|
||||||
|
break;
|
||||||
case SEC_PROT_TYPE_TLS:
|
case SEC_PROT_TYPE_TLS:
|
||||||
kmp_type = TLS_PROT;
|
kmp_type = TLS_PROT;
|
||||||
break;
|
break;
|
||||||
|
case SEC_PROT_TYPE_RADIUS_CLIENT:
|
||||||
|
kmp_type = RADIUS_CLIENT_PROT;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -328,6 +376,17 @@ bool kmp_api_receive_disable(kmp_api_t *kmp)
|
||||||
return kmp->receive_disable;
|
return kmp->receive_disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool kmp_api_receive_check(kmp_api_t *kmp, const void *pdu, uint16_t size)
|
||||||
|
{
|
||||||
|
if (kmp->sec_prot.receive_check) {
|
||||||
|
int8_t ret = kmp->sec_prot.receive_check(&kmp->sec_prot, pdu, size);
|
||||||
|
if (ret >= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
kmp_type_e kmp_api_type_from_id_get(uint8_t kmp_id)
|
kmp_type_e kmp_api_type_from_id_get(uint8_t kmp_id)
|
||||||
{
|
{
|
||||||
switch (kmp_id) {
|
switch (kmp_id) {
|
||||||
|
@ -380,12 +439,11 @@ kmp_service_t *kmp_service_create(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
ns_list_init(&service->sec_prot_list);
|
ns_list_init(&service->sec_prot_list);
|
||||||
|
ns_list_init(&service->msg_if_list);
|
||||||
service->incoming_ind = 0;
|
service->incoming_ind = 0;
|
||||||
service->tx_status_ind = 0;
|
service->tx_status_ind = 0;
|
||||||
service->addr_get = 0;
|
service->addr_get = 0;
|
||||||
service->api_get = 0;
|
service->api_get = 0;
|
||||||
service->send = 0;
|
|
||||||
service->header_size = 0;
|
|
||||||
|
|
||||||
ns_list_add_to_start(&kmp_service_list, service);
|
ns_list_add_to_start(&kmp_service_list, service);
|
||||||
|
|
||||||
|
@ -404,7 +462,10 @@ int8_t kmp_service_delete(kmp_service_t *service)
|
||||||
ns_list_remove(&list_entry->sec_prot_list, sec_list_entry);
|
ns_list_remove(&list_entry->sec_prot_list, sec_list_entry);
|
||||||
ns_dyn_mem_free(sec_list_entry);
|
ns_dyn_mem_free(sec_list_entry);
|
||||||
}
|
}
|
||||||
|
ns_list_foreach_safe(kmp_msg_if_entry_t, msg_if_list_entry, &list_entry->msg_if_list) {
|
||||||
|
ns_list_remove(&list_entry->msg_if_list, msg_if_list_entry);
|
||||||
|
ns_dyn_mem_free(msg_if_list_entry);
|
||||||
|
}
|
||||||
ns_list_remove(&kmp_service_list, list_entry);
|
ns_list_remove(&kmp_service_list, list_entry);
|
||||||
ns_dyn_mem_free(list_entry);
|
ns_dyn_mem_free(list_entry);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -420,7 +481,7 @@ static void kmp_sec_prot_state_machine_call(sec_prot_t *prot)
|
||||||
kmp->service->event_send(kmp->service, prot);
|
kmp->service->event_send(kmp->service, prot);
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind *incoming_ind, kmp_service_tx_status_ind *tx_status_ind, kmp_service_addr_get *addr_get, kmp_service_api_get *api_get)
|
int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind *incoming_ind, kmp_service_tx_status_ind *tx_status_ind, kmp_service_addr_get *addr_get, kmp_service_ip_addr_get *ip_addr_get, kmp_service_api_get *api_get)
|
||||||
{
|
{
|
||||||
if (!service) {
|
if (!service) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -429,30 +490,60 @@ int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind
|
||||||
service->incoming_ind = incoming_ind;
|
service->incoming_ind = incoming_ind;
|
||||||
service->tx_status_ind = tx_status_ind;
|
service->tx_status_ind = tx_status_ind;
|
||||||
service->addr_get = addr_get;
|
service->addr_get = addr_get;
|
||||||
|
service->ip_addr_get = ip_addr_get;
|
||||||
service->api_get = api_get;
|
service->api_get = api_get;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t kmp_service_msg_if_register(kmp_service_t *service, kmp_service_msg_if_send *send, uint8_t header_size)
|
int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size)
|
||||||
{
|
{
|
||||||
if (!service) {
|
if (!service) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
service->send = send;
|
kmp_msg_if_entry_t *entry = NULL;
|
||||||
service->header_size = header_size;
|
|
||||||
|
ns_list_foreach(kmp_msg_if_entry_t, list_entry, &service->msg_if_list) {
|
||||||
|
// Message interface already registered
|
||||||
|
if (list_entry->instance_id == instance_id) {
|
||||||
|
entry = list_entry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If removing message interface
|
||||||
|
if (send == NULL) {
|
||||||
|
if (entry != NULL) {
|
||||||
|
ns_list_remove(&service->msg_if_list, entry);
|
||||||
|
ns_dyn_mem_free(entry);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate new entry if does not exists
|
||||||
|
if (entry == NULL) {
|
||||||
|
entry = ns_dyn_mem_temporary_alloc(sizeof(kmp_msg_if_entry_t));
|
||||||
|
if (entry == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ns_list_add_to_start(&service->msg_if_list, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->instance_id = instance_id;
|
||||||
|
entry->send = send;
|
||||||
|
entry->header_size = header_size;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t kmp_service_msg_if_receive(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size)
|
int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size)
|
||||||
{
|
{
|
||||||
if (!service) {
|
if (!service) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
kmp_api_t *kmp = (kmp_api_t *) service->incoming_ind(service, type, addr);
|
kmp_api_t *kmp = (kmp_api_t *) service->incoming_ind(service, instance_id, type, addr, pdu, size);
|
||||||
if (!kmp) {
|
if (!kmp) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,16 +31,19 @@
|
||||||
typedef enum {
|
typedef enum {
|
||||||
KMP_TYPE_NONE = 0,
|
KMP_TYPE_NONE = 0,
|
||||||
|
|
||||||
IEEE_802_1X_MKA = 1,
|
IEEE_802_1X_MKA = 1,
|
||||||
IEEE_802_11_4WH = 6,
|
RADIUS_IEEE_802_1X_MKA = 2,
|
||||||
IEEE_802_11_GKH = 7,
|
IEEE_802_11_4WH = 6,
|
||||||
TLS_PROT = 8,
|
IEEE_802_11_GKH = 7,
|
||||||
|
TLS_PROT = 8,
|
||||||
|
RADIUS_CLIENT_PROT = 9,
|
||||||
|
|
||||||
IEEE_802_1X_INITIAL_KEY = 10,
|
IEEE_802_1X_INITIAL_KEY = 10,
|
||||||
|
|
||||||
IEEE_802_1X_MKA_KEY = 11,
|
IEEE_802_1X_MKA_KEY = 11,
|
||||||
IEEE_802_11_4WH_KEY = 16,
|
RADIUS_IEEE_802_1X_MKA_KEY = 12,
|
||||||
IEEE_802_11_GKH_KEY = 17
|
IEEE_802_11_4WH_KEY = 16,
|
||||||
|
IEEE_802_11_GKH_KEY = 17
|
||||||
} kmp_type_e;
|
} kmp_type_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -125,13 +128,13 @@ typedef void kmp_api_finished(kmp_api_t *kmp);
|
||||||
*
|
*
|
||||||
* \param service KMP service
|
* \param service KMP service
|
||||||
* \param type KMP type
|
* \param type KMP type
|
||||||
* \param prot_cfg protocol configuration
|
* \param msg_if_instance_id message interface instance identifier
|
||||||
* \param timer_cfg timer configuration
|
* \param sec_cfg security configuration
|
||||||
*
|
*
|
||||||
* \return KMP instance or NULL
|
* \return KMP instance or NULL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, sec_prot_cfg_t *prot_cfg, sec_timer_cfg_t *timer_cfg);
|
kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, uint8_t msg_if_instance_id, sec_cfg_t *sec_cfg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmp_api_start start KMP api
|
* kmp_api_start start KMP api
|
||||||
|
@ -172,6 +175,18 @@ kmp_type_e kmp_api_type_get(kmp_api_t *kmp);
|
||||||
*/
|
*/
|
||||||
bool kmp_api_receive_disable(kmp_api_t *kmp);
|
bool kmp_api_receive_disable(kmp_api_t *kmp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kmp_api_receive_check check if received message is for this KMP
|
||||||
|
*
|
||||||
|
* \param kmp instance
|
||||||
|
* \param pdu pdu
|
||||||
|
* \param size pdu size
|
||||||
|
*
|
||||||
|
* \return true/false true if message is for this KMP
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool kmp_api_receive_check(kmp_api_t *kmp, const void *pdu, uint16_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmp_api_type_from_id_get get KMP type from KMP id
|
* kmp_api_type_from_id_get get KMP type from KMP id
|
||||||
*
|
*
|
||||||
|
@ -274,13 +289,14 @@ int8_t kmp_service_delete(kmp_service_t *service);
|
||||||
* kmp_service_incoming_ind Notifies application about incoming KMP frame
|
* kmp_service_incoming_ind Notifies application about incoming KMP frame
|
||||||
*
|
*
|
||||||
* \param service KMP service
|
* \param service KMP service
|
||||||
|
* \param instance_id instance identifier
|
||||||
* \param type protocol type
|
* \param type protocol type
|
||||||
* \param addr address
|
* \param addr address
|
||||||
*
|
*
|
||||||
* \return KMP instance or NULL
|
* \return KMP instance or NULL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef kmp_api_t *kmp_service_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr);
|
typedef kmp_api_t *kmp_service_incoming_ind(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, const void *pdu, uint16_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmp_service_tx_status_ind Notifies application about TX status
|
* kmp_service_tx_status_ind Notifies application about TX status
|
||||||
|
@ -304,6 +320,16 @@ typedef kmp_api_t *kmp_service_tx_status_ind(kmp_service_t *service, uint8_t ins
|
||||||
*/
|
*/
|
||||||
typedef void kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr);
|
typedef void kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kmp_service_ip_addr_get gets IP addressing information related to KMP
|
||||||
|
*
|
||||||
|
* \param service KMP service
|
||||||
|
* \param kmp KMP instance
|
||||||
|
* \param address IP address
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef void kmp_service_ip_addr_get(kmp_service_t *service, kmp_api_t *kmp, uint8_t *address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmp_service_api_get gets KMP API from KMP service
|
* kmp_service_api_get gets KMP API from KMP service
|
||||||
*
|
*
|
||||||
|
@ -323,18 +349,20 @@ typedef kmp_api_t *kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, k
|
||||||
* \param incoming_ind incoming message callback
|
* \param incoming_ind incoming message callback
|
||||||
* \param tx_status tx status callback
|
* \param tx_status tx status callback
|
||||||
* \param addr_get gets addressing information callback
|
* \param addr_get gets addressing information callback
|
||||||
|
* \param ip_addr_get gets IP addressing information callback
|
||||||
* \param api_get gets KMP API from KMP service
|
* \param api_get gets KMP API from KMP service
|
||||||
*
|
*
|
||||||
* \return < 0 failure
|
* \return < 0 failure
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind *incoming_ind, kmp_service_tx_status_ind *tx_status_ind, kmp_service_addr_get *addr_get, kmp_service_api_get *api_get);
|
int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind *incoming_ind, kmp_service_tx_status_ind *tx_status_ind, kmp_service_addr_get *addr_get, kmp_service_ip_addr_get *ip_addr_get, kmp_service_api_get *api_get);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmp_service_msg_if_receive receive a message
|
* kmp_service_msg_if_receive receive a message
|
||||||
*
|
*
|
||||||
* \param service KMP service
|
* \param service KMP service
|
||||||
|
* \param instance_id instance identifier
|
||||||
* \param type protocol type
|
* \param type protocol type
|
||||||
* \param addr address
|
* \param addr address
|
||||||
* \param pdu pdu
|
* \param pdu pdu
|
||||||
|
@ -344,12 +372,13 @@ int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int8_t kmp_service_msg_if_receive(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size);
|
int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmp_service_msg_if_send send a message
|
* kmp_service_msg_if_send send a message
|
||||||
*
|
*
|
||||||
* \param service KMP service
|
* \param service KMP service
|
||||||
|
* \param instance_id instance identifier
|
||||||
* \param type protocol type
|
* \param type protocol type
|
||||||
* \param addr address
|
* \param addr address
|
||||||
* \param pdu pdu
|
* \param pdu pdu
|
||||||
|
@ -360,12 +389,13 @@ int8_t kmp_service_msg_if_receive(kmp_service_t *service, kmp_type_e kmp_id, con
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
|
typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmp_service_msg_if_register registers message interface
|
* kmp_service_msg_if_register registers message interface
|
||||||
*
|
*
|
||||||
* \param service KMP service
|
* \param service KMP service
|
||||||
|
* \param instance_id message interface instance identifier
|
||||||
* \param send KMP PDU send callback
|
* \param send KMP PDU send callback
|
||||||
* \param header_size header size
|
* \param header_size header size
|
||||||
*
|
*
|
||||||
|
@ -373,7 +403,7 @@ typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, kmp_type_e type,
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int8_t kmp_service_msg_if_register(kmp_service_t *service, kmp_service_msg_if_send *send, uint8_t header_size);
|
int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmp_service_tx_status tx status indication
|
* kmp_service_tx_status tx status indication
|
||||||
|
|
|
@ -49,7 +49,7 @@ typedef struct {
|
||||||
|
|
||||||
static NS_LIST_DEFINE(kmp_eapol_pdu_if_list, kmp_eapol_pdu_if_t, link);
|
static NS_LIST_DEFINE(kmp_eapol_pdu_if_list, kmp_eapol_pdu_if_t, link);
|
||||||
|
|
||||||
static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
|
static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
|
||||||
static int8_t kmp_eapol_pdu_if_tx_status(protocol_interface_info_entry_t *interface_ptr, eapol_pdu_tx_status_e tx_status, uint8_t tx_identifier);
|
static int8_t kmp_eapol_pdu_if_tx_status(protocol_interface_info_entry_t *interface_ptr, eapol_pdu_tx_status_e tx_status, uint8_t tx_identifier);
|
||||||
|
|
||||||
int8_t kmp_eapol_pdu_if_register(kmp_service_t *service, protocol_interface_info_entry_t *interface_ptr)
|
int8_t kmp_eapol_pdu_if_register(kmp_service_t *service, protocol_interface_info_entry_t *interface_ptr)
|
||||||
|
@ -72,7 +72,7 @@ int8_t kmp_eapol_pdu_if_register(kmp_service_t *service, protocol_interface_info
|
||||||
eapol_pdu_if->kmp_service = service;
|
eapol_pdu_if->kmp_service = service;
|
||||||
eapol_pdu_if->interface_ptr = interface_ptr;
|
eapol_pdu_if->interface_ptr = interface_ptr;
|
||||||
|
|
||||||
if (kmp_service_msg_if_register(service, kmp_eapol_pdu_if_send, EAPOL_PDU_IF_HEADER_SIZE) < 0) {
|
if (kmp_service_msg_if_register(service, 0, kmp_eapol_pdu_if_send, EAPOL_PDU_IF_HEADER_SIZE) < 0) {
|
||||||
ns_dyn_mem_free(eapol_pdu_if);
|
ns_dyn_mem_free(eapol_pdu_if);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -92,14 +92,16 @@ int8_t kmp_eapol_pdu_if_unregister(kmp_service_t *service)
|
||||||
if (entry->kmp_service == service) {
|
if (entry->kmp_service == service) {
|
||||||
ns_list_remove(&kmp_eapol_pdu_if_list, entry);
|
ns_list_remove(&kmp_eapol_pdu_if_list, entry);
|
||||||
ns_dyn_mem_free(entry);
|
ns_dyn_mem_free(entry);
|
||||||
kmp_service_msg_if_register(service, NULL, 0);
|
kmp_service_msg_if_register(service, 0, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier)
|
static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier)
|
||||||
{
|
{
|
||||||
|
(void) instance_id; // Only one instance of eapol interface possible
|
||||||
|
|
||||||
if (!service || !addr || !pdu) {
|
if (!service || !addr || !pdu) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +159,7 @@ int8_t kmp_eapol_pdu_if_receive(protocol_interface_info_entry_t *interface_ptr,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t ret = kmp_service_msg_if_receive(service, type, &addr, data_pdu, data_pdu_size);
|
int8_t ret = kmp_service_msg_if_receive(service, 0, type, &addr, data_pdu, data_pdu_size);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,52 +43,92 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
kmp_service_t *kmp_service; /**< KMP service */
|
kmp_service_t *kmp_service; /**< KMP service */
|
||||||
|
uint8_t instance_id; /**< Instance identifier */
|
||||||
|
bool relay; /**< Interface is relay interface */
|
||||||
ns_address_t remote_addr; /**< Remote address */
|
ns_address_t remote_addr; /**< Remote address */
|
||||||
int8_t socket_id; /**< Socket ID */
|
int8_t socket_id; /**< Socket ID */
|
||||||
|
bool socket_id_set; /**< Socket ID is set */
|
||||||
ns_list_link_t link; /**< Link */
|
ns_list_link_t link; /**< Link */
|
||||||
} kmp_socket_if_t;
|
} kmp_socket_if_t;
|
||||||
|
|
||||||
static int8_t kmp_socket_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
|
static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier);
|
||||||
static void kmp_socket_if_socket_cb(void *ptr);
|
static void kmp_socket_if_socket_cb(void *ptr);
|
||||||
|
|
||||||
static NS_LIST_DEFINE(kmp_socket_if_list, kmp_socket_if_t, link);
|
static NS_LIST_DEFINE(kmp_socket_if_list, kmp_socket_if_t, link);
|
||||||
|
static uint8_t kmp_socket_if_instance_id = 1;
|
||||||
|
|
||||||
int8_t kmp_socket_if_register(kmp_service_t *service, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port)
|
int8_t kmp_socket_if_register(kmp_service_t *service, uint8_t *instance_id, bool relay, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port)
|
||||||
{
|
{
|
||||||
if (!service || !remote_addr) {
|
if (!service || !remote_addr) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kmp_socket_if_t *socket_if = NULL;
|
||||||
|
bool new_socket_if_allocated = false;
|
||||||
|
|
||||||
ns_list_foreach(kmp_socket_if_t, entry, &kmp_socket_if_list) {
|
ns_list_foreach(kmp_socket_if_t, entry, &kmp_socket_if_list) {
|
||||||
if (entry->kmp_service == service) {
|
if (entry->kmp_service == service && entry->instance_id == *instance_id) {
|
||||||
return -1;
|
socket_if = entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kmp_socket_if_t *socket_if = ns_dyn_mem_alloc(sizeof(kmp_socket_if_t));
|
|
||||||
if (!socket_if) {
|
if (!socket_if) {
|
||||||
return -1;
|
socket_if = ns_dyn_mem_alloc(sizeof(kmp_socket_if_t));
|
||||||
|
if (!socket_if) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(socket_if, 0, sizeof(kmp_socket_if_t));
|
||||||
|
socket_if->socket_id = -1;
|
||||||
|
new_socket_if_allocated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket_if->kmp_service = service;
|
socket_if->kmp_service = service;
|
||||||
|
|
||||||
|
if (*instance_id == 0) {
|
||||||
|
socket_if->instance_id = kmp_socket_if_instance_id++;
|
||||||
|
if (socket_if->instance_id == 0) {
|
||||||
|
socket_if->instance_id++;
|
||||||
|
}
|
||||||
|
*instance_id = socket_if->instance_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_if->relay = relay;
|
||||||
|
|
||||||
socket_if->remote_addr.type = ADDRESS_IPV6;
|
socket_if->remote_addr.type = ADDRESS_IPV6;
|
||||||
|
|
||||||
|
bool address_changed = false;
|
||||||
|
if (memcmp(&socket_if->remote_addr.address, remote_addr, 16) != 0 ||
|
||||||
|
socket_if->remote_addr.identifier != remote_port) {
|
||||||
|
address_changed = true;
|
||||||
|
}
|
||||||
memcpy(&socket_if->remote_addr.address, remote_addr, 16);
|
memcpy(&socket_if->remote_addr.address, remote_addr, 16);
|
||||||
socket_if->remote_addr.identifier = remote_port;
|
socket_if->remote_addr.identifier = remote_port;
|
||||||
|
|
||||||
socket_if->socket_id = socket_open(IPV6_NH_UDP, local_port, &kmp_socket_if_socket_cb);
|
if (socket_if->socket_id < 0 || address_changed) {
|
||||||
if (socket_if->socket_id < 0) {
|
if (socket_if->socket_id >= 0) {
|
||||||
|
socket_close(socket_if->socket_id);
|
||||||
|
}
|
||||||
|
socket_if->socket_id = socket_open(IPV6_NH_UDP, local_port, &kmp_socket_if_socket_cb);
|
||||||
|
if (socket_if->socket_id < 0) {
|
||||||
|
ns_dyn_mem_free(socket_if);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t header_size = 0;
|
||||||
|
if (relay) {
|
||||||
|
header_size = SOCKET_IF_HEADER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kmp_service_msg_if_register(service, *instance_id, kmp_socket_if_send, header_size) < 0) {
|
||||||
ns_dyn_mem_free(socket_if);
|
ns_dyn_mem_free(socket_if);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kmp_service_msg_if_register(service, kmp_socket_if_send, SOCKET_IF_HEADER_SIZE) < 0) {
|
if (new_socket_if_allocated) {
|
||||||
ns_dyn_mem_free(socket_if);
|
ns_list_add_to_end(&kmp_socket_if_list, socket_if);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ns_list_add_to_end(&kmp_socket_if_list, socket_if);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,14 +142,14 @@ int8_t kmp_socket_if_unregister(kmp_service_t *service)
|
||||||
if (entry->kmp_service == service) {
|
if (entry->kmp_service == service) {
|
||||||
ns_list_remove(&kmp_socket_if_list, entry);
|
ns_list_remove(&kmp_socket_if_list, entry);
|
||||||
socket_close(entry->socket_id);
|
socket_close(entry->socket_id);
|
||||||
|
kmp_service_msg_if_register(service, entry->instance_id, NULL, 0);
|
||||||
ns_dyn_mem_free(entry);
|
ns_dyn_mem_free(entry);
|
||||||
kmp_service_msg_if_register(service, NULL, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int8_t kmp_socket_if_send(kmp_service_t *service, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier)
|
static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier)
|
||||||
{
|
{
|
||||||
(void) tx_identifier;
|
(void) tx_identifier;
|
||||||
|
|
||||||
|
@ -120,7 +160,7 @@ static int8_t kmp_socket_if_send(kmp_service_t *service, kmp_type_e kmp_id, cons
|
||||||
kmp_socket_if_t *socket_if = NULL;
|
kmp_socket_if_t *socket_if = NULL;
|
||||||
|
|
||||||
ns_list_foreach(kmp_socket_if_t, entry, &kmp_socket_if_list) {
|
ns_list_foreach(kmp_socket_if_t, entry, &kmp_socket_if_list) {
|
||||||
if (entry->kmp_service == service) {
|
if (entry->kmp_service == service && entry->instance_id == instance_id) {
|
||||||
socket_if = entry;
|
socket_if = entry;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -130,14 +170,16 @@ static int8_t kmp_socket_if_send(kmp_service_t *service, kmp_type_e kmp_id, cons
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Build UPD Relay
|
if (socket_if->relay) {
|
||||||
uint8_t *ptr = pdu;
|
//Build UPD Relay
|
||||||
memcpy(ptr, addr->relay_address, 16);
|
uint8_t *ptr = pdu;
|
||||||
ptr += 16;
|
memcpy(ptr, addr->relay_address, 16);
|
||||||
ptr = common_write_16_bit(addr->port, ptr);
|
ptr += 16;
|
||||||
memcpy(ptr, kmp_address_eui_64_get(addr), 8);
|
ptr = common_write_16_bit(addr->port, ptr);
|
||||||
ptr += 8;
|
memcpy(ptr, kmp_address_eui_64_get(addr), 8);
|
||||||
*ptr = kmp_id;
|
ptr += 8;
|
||||||
|
*ptr = kmp_id;
|
||||||
|
}
|
||||||
|
|
||||||
socket_sendto(socket_if->socket_id, &socket_if->remote_addr, pdu, size);
|
socket_sendto(socket_if->socket_id, &socket_if->remote_addr, pdu, size);
|
||||||
ns_dyn_mem_free(pdu);
|
ns_dyn_mem_free(pdu);
|
||||||
|
@ -172,25 +214,30 @@ static void kmp_socket_if_socket_cb(void *ptr)
|
||||||
ns_dyn_mem_free(pdu);
|
ns_dyn_mem_free(pdu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
kmp_addr_t addr;
|
kmp_addr_t addr;
|
||||||
addr.type = KMP_ADDR_EUI_64_AND_IP;
|
memset(&addr, 0, sizeof(kmp_addr_t));
|
||||||
|
kmp_type_e type = KMP_TYPE_NONE;
|
||||||
uint8_t *data_ptr = pdu;
|
uint8_t *data_ptr = pdu;
|
||||||
memcpy(addr.relay_address, data_ptr, 16);
|
|
||||||
data_ptr += 16;
|
|
||||||
addr.port = common_read_16_bit(data_ptr);
|
|
||||||
data_ptr += 2;
|
|
||||||
memcpy(addr.eui_64, data_ptr, 8);
|
|
||||||
data_ptr += 8;
|
|
||||||
|
|
||||||
kmp_type_e type = kmp_api_type_from_id_get(*data_ptr++);
|
if (socket_if->relay) {
|
||||||
if (type == KMP_TYPE_NONE) {
|
addr.type = KMP_ADDR_EUI_64_AND_IP;
|
||||||
ns_dyn_mem_free(pdu);
|
memcpy(addr.relay_address, data_ptr, 16);
|
||||||
return;
|
data_ptr += 16;
|
||||||
|
addr.port = common_read_16_bit(data_ptr);
|
||||||
|
data_ptr += 2;
|
||||||
|
memcpy(addr.eui_64, data_ptr, 8);
|
||||||
|
data_ptr += 8;
|
||||||
|
|
||||||
|
type = kmp_api_type_from_id_get(*data_ptr++);
|
||||||
|
if (type == KMP_TYPE_NONE) {
|
||||||
|
ns_dyn_mem_free(pdu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cb_data->d_len -= SOCKET_IF_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kmp_service_msg_if_receive(socket_if->kmp_service, socket_if->instance_id, type, &addr, data_ptr, cb_data->d_len);
|
||||||
kmp_service_msg_if_receive(socket_if->kmp_service, type, &addr, data_ptr, cb_data->d_len - 27);
|
|
||||||
|
|
||||||
ns_dyn_mem_free(pdu);
|
ns_dyn_mem_free(pdu);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
* kmp_socket_if_register register socket interface to KMP service
|
* kmp_socket_if_register register socket interface to KMP service
|
||||||
*
|
*
|
||||||
* \param service KMP service to register to
|
* \param service KMP service to register to
|
||||||
|
* \param instance_id instance identifier, for new instance set to zero when called
|
||||||
|
* \param relay interface is relay interface
|
||||||
* \param local_port local port
|
* \param local_port local port
|
||||||
* \param remote_addr remote address
|
* \param remote_addr remote address
|
||||||
* \param remote_port remote port
|
* \param remote_port remote port
|
||||||
|
@ -41,7 +43,7 @@
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int8_t kmp_socket_if_register(kmp_service_t *service, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port);
|
int8_t kmp_socket_if_register(kmp_service_t *service, uint8_t *instance_id, bool relay, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmp_socket_if_unregister unregister socket interface from KMP service
|
* kmp_socket_if_unregister unregister socket interface from KMP service
|
||||||
|
|
|
@ -189,7 +189,7 @@ static int8_t auth_eap_tls_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_
|
||||||
// Call state machine
|
// Call state machine
|
||||||
prot->state_machine(prot);
|
prot->state_machine(prot);
|
||||||
// Resets trickle timer to give time for supplicant to answer
|
// Resets trickle timer to give time for supplicant to answer
|
||||||
sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
|
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||||
data->init_key_cnt++;
|
data->init_key_cnt++;
|
||||||
}
|
}
|
||||||
// Filters repeated initial EAPOL-key messages
|
// Filters repeated initial EAPOL-key messages
|
||||||
|
@ -297,7 +297,7 @@ static void auth_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks
|
||||||
}
|
}
|
||||||
|
|
||||||
sec_prot_timer_timeout_handle(prot, &data->common,
|
sec_prot_timer_timeout_handle(prot, &data->common,
|
||||||
&prot->prot_cfg->sec_prot_trickle_params, ticks);
|
&prot->sec_cfg->prot_cfg.sec_prot_trickle_params, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void auth_eap_tls_sec_prot_tls_create_indication(sec_prot_t *tls_prot)
|
static void auth_eap_tls_sec_prot_tls_create_indication(sec_prot_t *tls_prot)
|
||||||
|
@ -421,7 +421,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE);
|
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE);
|
||||||
|
|
||||||
// Start trickle timer to re-send if no response
|
// Start trickle timer to re-send if no response
|
||||||
sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
|
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||||
|
|
||||||
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_ID);
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_ID);
|
||||||
break;
|
break;
|
||||||
|
@ -445,7 +445,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START);
|
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_START);
|
||||||
|
|
||||||
// Start trickle timer to re-send if no response
|
// Start trickle timer to re-send if no response
|
||||||
sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
|
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||||
|
|
||||||
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_START);
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_START);
|
||||||
break;
|
break;
|
||||||
|
@ -527,7 +527,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING);
|
auth_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING);
|
||||||
|
|
||||||
// Start trickle timer to re-send if no response
|
// Start trickle timer to re-send if no response
|
||||||
sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
|
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||||
} else {
|
} else {
|
||||||
// TLS done, indicate success to peer
|
// TLS done, indicate success to peer
|
||||||
if (data->tls_result == EAP_TLS_RESULT_HANDSHAKE_OVER) {
|
if (data->tls_result == EAP_TLS_RESULT_HANDSHAKE_OVER) {
|
||||||
|
@ -557,7 +557,7 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
|
|
||||||
case EAP_TLS_STATE_FINISHED: {
|
case EAP_TLS_STATE_FINISHED: {
|
||||||
uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot);
|
uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot);
|
||||||
tr_info("EAP-TLS finished, eui-64: %s", remote_eui_64 ? trace_array(sec_prot_remote_eui_64_addr_get(prot), 8) : "not set");
|
tr_info("EAP-TLS finished, eui-64: %s", remote_eui_64 ? trace_array(remote_eui_64, 8) : "not set");
|
||||||
auth_eap_tls_sec_prot_delete_tls(prot);
|
auth_eap_tls_sec_prot_delete_tls(prot);
|
||||||
prot->timer_stop(prot);
|
prot->timer_stop(prot);
|
||||||
prot->finished(prot);
|
prot->finished(prot);
|
||||||
|
|
|
@ -0,0 +1,526 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Arm Limited and affiliates.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nsconfig.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "ns_types.h"
|
||||||
|
#include "ns_list.h"
|
||||||
|
#include "ns_trace.h"
|
||||||
|
#include "common_functions.h"
|
||||||
|
#include "nsdynmemLIB.h"
|
||||||
|
#include "fhss_config.h"
|
||||||
|
#include "NWK_INTERFACE/Include/protocol.h"
|
||||||
|
#include "6LoWPAN/ws/ws_config.h"
|
||||||
|
#include "6LoWPAN/ws/ws_cfg_settings.h"
|
||||||
|
#include "Security/PANA/pana_eap_header.h"
|
||||||
|
#include "Security/protocols/sec_prot_cfg.h"
|
||||||
|
#include "Security/kmp/kmp_addr.h"
|
||||||
|
#include "Security/kmp/kmp_api.h"
|
||||||
|
#include "Security/PANA/pana_eap_header.h"
|
||||||
|
#include "Security/eapol/eapol_helper.h"
|
||||||
|
#include "Security/protocols/sec_prot_certs.h"
|
||||||
|
#include "Security/protocols/sec_prot_keys.h"
|
||||||
|
#include "Security/protocols/sec_prot.h"
|
||||||
|
#include "Security/protocols/sec_prot_lib.h"
|
||||||
|
#include "Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.h"
|
||||||
|
#include "Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_WS
|
||||||
|
|
||||||
|
#define TRACE_GROUP "eapr"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EAP_TLS_STATE_INIT = SEC_STATE_INIT,
|
||||||
|
EAP_TLS_STATE_CREATE_REQ = SEC_STATE_CREATE_REQ,
|
||||||
|
EAP_TLS_STATE_CREATE_RESP = SEC_STATE_CREATE_RESP,
|
||||||
|
EAP_TLS_STATE_CREATE_IND = SEC_STATE_CREATE_IND,
|
||||||
|
|
||||||
|
EAP_TLS_STATE_RESPONSE_ID = SEC_STATE_FIRST,
|
||||||
|
EAP_TLS_STATE_EAP_REQUEST,
|
||||||
|
EAP_TLS_STATE_EAP_RESPONSE,
|
||||||
|
EAP_TLS_STATE_RESPONSE_START,
|
||||||
|
EAP_TLS_STATE_RESPONSE,
|
||||||
|
|
||||||
|
EAP_TLS_STATE_FINISH = SEC_STATE_FINISH,
|
||||||
|
EAP_TLS_STATE_FINISHED = SEC_STATE_FINISHED
|
||||||
|
} eap_tls_sec_prot_state_e;
|
||||||
|
|
||||||
|
// Filters initial EAPOL-key re-transmission bursts
|
||||||
|
#define BURST_FILTER_TIMER_TIMEOUT 5 * 10
|
||||||
|
|
||||||
|
// How many times initial EAPOL-key is accepted on wait for identity response state
|
||||||
|
#define INITIAL_EAPOL_KEY_MAX_COUNT 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sec_prot_common_t common; /**< Common data */
|
||||||
|
sec_prot_t *radius_client_prot; /**< RADIUS client security protocol */
|
||||||
|
sec_prot_receive *radius_client_send; /**< RADIUS client security protocol send (receive from peer) */
|
||||||
|
eapol_pdu_t recv_eapol_pdu; /**< Received EAPOL PDU */
|
||||||
|
tls_data_t tls_send; /**< EAP-TLS send buffer */
|
||||||
|
uint16_t recv_eap_msg_len; /**< Received EAP message length */
|
||||||
|
uint8_t *recv_eap_msg; /**< Received EAP message */
|
||||||
|
uint16_t burst_filt_timer; /**< Burst filter timer */
|
||||||
|
uint8_t eap_id_seq; /**< EAP sequence */
|
||||||
|
uint8_t recv_eap_id_seq; /**< Last received EAP sequence */
|
||||||
|
uint8_t eap_code; /**< Received EAP code */
|
||||||
|
uint8_t eap_type; /**< Received EAP type */
|
||||||
|
uint8_t init_key_cnt; /**< How many time initial EAPOL-key has been received */
|
||||||
|
} radius_eap_tls_sec_prot_int_t;
|
||||||
|
|
||||||
|
static uint16_t radius_eap_tls_sec_prot_size(void);
|
||||||
|
static int8_t radius_eap_tls_sec_prot_init(sec_prot_t *prot);
|
||||||
|
|
||||||
|
static void radius_eap_tls_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_keys);
|
||||||
|
static void radius_eap_tls_sec_prot_delete(sec_prot_t *prot);
|
||||||
|
static int8_t radius_eap_tls_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size);
|
||||||
|
static int8_t radius_eap_tls_sec_prot_radius_client_receive(sec_prot_t *radius_client, void *pdu, uint16_t size);
|
||||||
|
static int8_t radius_eap_tls_sec_prot_radius_eap_message_forward(sec_prot_t *prot, uint8_t *eap_code);
|
||||||
|
|
||||||
|
static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot);
|
||||||
|
|
||||||
|
static int8_t radius_eap_tls_sec_prot_message_handle(sec_prot_t *prot, uint8_t *data_ptr, uint16_t *length);
|
||||||
|
static int8_t radius_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state);
|
||||||
|
|
||||||
|
static void radius_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
|
||||||
|
static int8_t radius_eap_tls_sec_prot_init_radius_client(sec_prot_t *prot);
|
||||||
|
|
||||||
|
static void radius_eap_tls_sec_prot_seq_id_update(sec_prot_t *prot);
|
||||||
|
|
||||||
|
#define eap_tls_sec_prot_get(prot) (radius_eap_tls_sec_prot_int_t *) &prot->data
|
||||||
|
|
||||||
|
int8_t radius_eap_tls_sec_prot_register(kmp_service_t *service)
|
||||||
|
{
|
||||||
|
if (!service) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kmp_service_sec_protocol_register(service, RADIUS_IEEE_802_1X_MKA, radius_eap_tls_sec_prot_size, radius_eap_tls_sec_prot_init) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t radius_eap_tls_sec_prot_size(void)
|
||||||
|
{
|
||||||
|
return sizeof(radius_eap_tls_sec_prot_int_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_eap_tls_sec_prot_init(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
prot->create_req = radius_eap_tls_sec_prot_create_request;
|
||||||
|
prot->create_resp = 0;
|
||||||
|
prot->receive = radius_eap_tls_sec_prot_receive;
|
||||||
|
prot->receive_peer = radius_eap_tls_sec_prot_radius_client_receive;
|
||||||
|
prot->delete = radius_eap_tls_sec_prot_delete;
|
||||||
|
prot->state_machine = radius_eap_tls_sec_prot_state_machine;
|
||||||
|
prot->timer_timeout = radius_eap_tls_sec_prot_timer_timeout;
|
||||||
|
prot->receive_peer_hdr_size += EAPOL_BASE_LENGTH; // 4 bytes of EAPOL data
|
||||||
|
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
|
||||||
|
sec_prot_init(&data->common);
|
||||||
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_INIT);
|
||||||
|
|
||||||
|
data->radius_client_prot = NULL;
|
||||||
|
data->burst_filt_timer = BURST_FILTER_TIMER_TIMEOUT;
|
||||||
|
data->eap_id_seq = 0;
|
||||||
|
data->recv_eap_id_seq = 0;
|
||||||
|
data->eap_code = 0;
|
||||||
|
data->eap_type = 0;
|
||||||
|
eap_tls_sec_prot_lib_message_init(&data->tls_send);
|
||||||
|
data->init_key_cnt = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_eap_tls_sec_prot_delete(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
eap_tls_sec_prot_lib_message_free(&data->tls_send);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_eap_tls_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_keys)
|
||||||
|
{
|
||||||
|
prot->sec_keys = sec_keys;
|
||||||
|
|
||||||
|
// Call state machine
|
||||||
|
prot->state_machine_call(prot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_eap_tls_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size)
|
||||||
|
{
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
int8_t ret_val = -1;
|
||||||
|
|
||||||
|
// Decoding is successful
|
||||||
|
if (eapol_parse_pdu_header(pdu, size, &data->recv_eapol_pdu)) {
|
||||||
|
// Handle EAP messages
|
||||||
|
if (data->recv_eapol_pdu.packet_type == EAPOL_EAP_TYPE) {
|
||||||
|
data->eap_code = data->recv_eapol_pdu.msg.eap.eap_code;
|
||||||
|
data->eap_type = data->recv_eapol_pdu.msg.eap.type;
|
||||||
|
|
||||||
|
// Call state machine
|
||||||
|
prot->state_machine(prot);
|
||||||
|
} else if (data->recv_eapol_pdu.packet_type == EAPOL_KEY_TYPE &&
|
||||||
|
sec_prot_state_get(&data->common) == EAP_TLS_STATE_RESPONSE_ID) {
|
||||||
|
/* If initial EAPOL-key transmission arrives to first EAP-TLS wait state i.e.
|
||||||
|
* when waiting for identity response, triggers re-transmission of identity
|
||||||
|
* request. This allows the supplicant to start EAP-TLS right away, if it has
|
||||||
|
* missed the original identity request.
|
||||||
|
*/
|
||||||
|
if (data->burst_filt_timer == 0 && data->init_key_cnt < INITIAL_EAPOL_KEY_MAX_COUNT) {
|
||||||
|
tr_info("EAP-TLS: initial EAPOL-key recv, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
sec_prot_result_set(&data->common, SEC_RESULT_TIMEOUT);
|
||||||
|
// Call state machine
|
||||||
|
prot->state_machine(prot);
|
||||||
|
// Resets trickle timer to give time for supplicant to answer
|
||||||
|
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||||
|
data->init_key_cnt++;
|
||||||
|
}
|
||||||
|
// Filters repeated initial EAPOL-key messages
|
||||||
|
data->burst_filt_timer = BURST_FILTER_TIMER_TIMEOUT;
|
||||||
|
}
|
||||||
|
ret_val = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&data->recv_eapol_pdu, 0, sizeof(eapol_pdu_t));
|
||||||
|
data->eap_code = 0;
|
||||||
|
data->eap_type = 0;
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_eap_tls_sec_prot_message_handle(sec_prot_t *prot, uint8_t *data_ptr, uint16_t *length)
|
||||||
|
{
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
|
||||||
|
data_ptr = data->recv_eapol_pdu.msg.eap.data_ptr;
|
||||||
|
*length = data->recv_eapol_pdu.msg.eap.length;
|
||||||
|
|
||||||
|
bool old_seq_id = false;
|
||||||
|
|
||||||
|
// Already received sequence ID is received again, ignore
|
||||||
|
if (data->recv_eapol_pdu.msg.eap.id_seq < data->eap_id_seq) {
|
||||||
|
old_seq_id = true;
|
||||||
|
} else if (data->recv_eapol_pdu.msg.eap.id_seq == data->eap_id_seq) {
|
||||||
|
// Confirmation that supplicant has received the message, proceed with protocol
|
||||||
|
data->recv_eap_id_seq = data->recv_eapol_pdu.msg.eap.id_seq;
|
||||||
|
data->eap_id_seq++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_info("EAP-TLS: recv %s type %s id %i flags %x len %i, eui-64 %s", eap_msg_trace[data->eap_code - 1],
|
||||||
|
data->eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", data->recv_eapol_pdu.msg.eap.id_seq,
|
||||||
|
*length >= 6 ? data_ptr[0] : 0, *length, trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
if (old_seq_id) {
|
||||||
|
return EAP_TLS_MSG_DECODE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->eap_type == EAP_IDENTITY) {
|
||||||
|
return EAP_TLS_MSG_IDENTITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data_ptr || *length < 6) {
|
||||||
|
tr_error("EAP-TLS: decode error");
|
||||||
|
return EAP_TLS_MSG_DECODE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EAP_TLS_MSG_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state)
|
||||||
|
{
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
|
||||||
|
uint8_t flags = 0xff;
|
||||||
|
// EAP-TLS flags field is always present during TLS exchange
|
||||||
|
if (tls_state == EAP_TLS_EXCHANGE_ONGOING) {
|
||||||
|
flags = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eap_code == EAP_REQ) {
|
||||||
|
if (eap_type == EAP_TLS && tls_state == EAP_TLS_EXCHANGE_START) {
|
||||||
|
eap_tls_sec_prot_lib_message_allocate(&data->tls_send, TLS_HEAD_LEN, 0);
|
||||||
|
flags = EAP_TLS_START;
|
||||||
|
}
|
||||||
|
} else if (eap_code == EAP_SUCCESS || eap_code == EAP_FAILURE) {
|
||||||
|
// Send Success and Failure with same identifier as received in EAP Response
|
||||||
|
data->eap_id_seq = data->recv_eap_id_seq;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t eapol_pdu_size;
|
||||||
|
uint8_t *eapol_decoded_data = eap_tls_sec_prot_lib_message_build(eap_code, eap_type, &flags, data->eap_id_seq, prot->header_size, &data->tls_send, &eapol_pdu_size);
|
||||||
|
if (!eapol_decoded_data) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_info("EAP-TLS: send %s type %s id %i flags %x len %i, eui-64: %s", eap_msg_trace[eap_code - 1],
|
||||||
|
eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", data->eap_id_seq, flags, eapol_pdu_size,
|
||||||
|
trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
if (prot->send(prot, eapol_decoded_data, eapol_pdu_size + prot->header_size) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_eap_tls_sec_prot_radius_eap_message_forward(sec_prot_t *prot, uint8_t *eap_code)
|
||||||
|
{
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
|
||||||
|
uint16_t eap_pdu_len = data->recv_eap_msg_len - prot->receive_peer_hdr_size;
|
||||||
|
uint8_t *eap_pdu = data->recv_eap_msg + prot->receive_peer_hdr_size;
|
||||||
|
|
||||||
|
if (eap_pdu_len < 4) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*eap_code = *eap_pdu++;
|
||||||
|
uint8_t eap_id_seq = *eap_pdu++;
|
||||||
|
uint16_t eap_len = common_read_16_bit(eap_pdu);
|
||||||
|
eap_pdu += 2;
|
||||||
|
|
||||||
|
if (eap_pdu_len != eap_len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t eap_body_len = eap_len;
|
||||||
|
uint8_t eap_type = 0;
|
||||||
|
uint8_t flags = 0;
|
||||||
|
uint8_t *tls_ptr = NULL;
|
||||||
|
|
||||||
|
if (*eap_code == EAP_REQ || *eap_code == EAP_RESPONSE) {
|
||||||
|
eap_type = *eap_pdu++;
|
||||||
|
eap_body_len--;
|
||||||
|
if (eap_type == EAP_TLS && eap_len >= 5) {
|
||||||
|
tls_ptr = eap_pdu;
|
||||||
|
flags = *tls_ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eapol_pdu_t eapol_pdu;
|
||||||
|
uint16_t eapol_pdu_size = eapol_pdu_eap_frame_init(&eapol_pdu, *eap_code, eap_id_seq, eap_type, eap_body_len, tls_ptr);
|
||||||
|
if (eapol_pdu_size - EAPOL_BASE_LENGTH != eap_len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
eapol_write_pdu_frame(data->recv_eap_msg + prot->header_size, &eapol_pdu);
|
||||||
|
|
||||||
|
tr_info("EAP-TLS: send %s type %s id %i flags %x len %i, eui-64: %s", eap_msg_trace[*eap_code - 1],
|
||||||
|
eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", data->eap_id_seq, flags, eapol_pdu_size,
|
||||||
|
trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
if (prot->send(prot, data->recv_eap_msg, eapol_pdu_size + prot->header_size) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
||||||
|
{
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
|
||||||
|
if (data->burst_filt_timer > ticks) {
|
||||||
|
data->burst_filt_timer -= ticks;
|
||||||
|
} else {
|
||||||
|
data->burst_filt_timer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sec_prot_timer_timeout_handle(prot, &data->common,
|
||||||
|
&prot->sec_cfg->prot_cfg.sec_prot_trickle_params, ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_eap_tls_sec_prot_radius_client_receive(sec_prot_t *radius_client, void *pdu, uint16_t size)
|
||||||
|
{
|
||||||
|
sec_prot_t *prot = radius_client->type_get(radius_client, SEC_PROT_TYPE_RADIUS_EAP_TLS);
|
||||||
|
if (!prot) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
|
||||||
|
data->recv_eap_msg_len = size;
|
||||||
|
data->recv_eap_msg = pdu;
|
||||||
|
|
||||||
|
prot->state_machine_call(prot);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_eap_tls_sec_prot_init_radius_client(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
if (data->radius_client_prot) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->radius_client_prot = prot->type_get(prot, SEC_PROT_TYPE_RADIUS_CLIENT);
|
||||||
|
if (!data->radius_client_prot) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data->radius_client_send = data->radius_client_prot->receive_peer;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
uint8_t *data_ptr = NULL;
|
||||||
|
uint16_t length = 0;
|
||||||
|
|
||||||
|
// EAP-TLS authenticator state machine
|
||||||
|
switch (sec_prot_state_get(&data->common)) {
|
||||||
|
case EAP_TLS_STATE_INIT:
|
||||||
|
tr_info("EAP-TLS init");
|
||||||
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_CREATE_REQ);
|
||||||
|
prot->timer_start(prot);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Wait KMP-CREATE.request
|
||||||
|
case EAP_TLS_STATE_CREATE_REQ:
|
||||||
|
tr_info("EAP-TLS start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
// Set default timeout for the total maximum length of the negotiation
|
||||||
|
sec_prot_default_timeout_set(&data->common);
|
||||||
|
|
||||||
|
// KMP-CREATE.confirm
|
||||||
|
prot->create_conf(prot, SEC_RESULT_OK);
|
||||||
|
|
||||||
|
// Increment sequence ID
|
||||||
|
radius_eap_tls_sec_prot_seq_id_update(prot);
|
||||||
|
|
||||||
|
// Sends EAP request, Identity
|
||||||
|
radius_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE);
|
||||||
|
|
||||||
|
// Start trickle timer to re-send if no response
|
||||||
|
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||||
|
|
||||||
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE_ID);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Wait EAP response, Identity
|
||||||
|
case EAP_TLS_STATE_RESPONSE_ID:
|
||||||
|
|
||||||
|
// On timeout
|
||||||
|
if (sec_prot_result_timeout_check(&data->common)) {
|
||||||
|
// Re-sends EAP request, Identity
|
||||||
|
radius_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle EAP response (expected Identity)
|
||||||
|
if (radius_eap_tls_sec_prot_message_handle(prot, data_ptr, &length) != EAP_TLS_MSG_IDENTITY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_info("EAP-TLS EAP response id, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
if (radius_eap_tls_sec_prot_init_radius_client(prot) < 0) {
|
||||||
|
tr_error("EAP-TLS: radius client init failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send to radius client
|
||||||
|
data->radius_client_send(data->radius_client_prot, (void *) &data->recv_eapol_pdu, length);
|
||||||
|
|
||||||
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_EAP_REQUEST);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Wait EAP request
|
||||||
|
case EAP_TLS_STATE_EAP_REQUEST:
|
||||||
|
|
||||||
|
// On timeout
|
||||||
|
if (sec_prot_result_timeout_check(&data->common)) {
|
||||||
|
// Do nothing for now
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_info("EAP-TLS EAP request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
uint8_t eap_code;
|
||||||
|
if (radius_eap_tls_sec_prot_radius_eap_message_forward(prot, &eap_code) < 0) {
|
||||||
|
tr_error("EAP-TLS: EAP message forward failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eap_code == EAP_SUCCESS) {
|
||||||
|
sec_prot_result_set(&data->common, SEC_RESULT_OK);
|
||||||
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_FINISH);
|
||||||
|
} else if (eap_code == EAP_FAILURE) {
|
||||||
|
sec_prot_result_set(&data->common, SEC_RESULT_ERROR);
|
||||||
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_FINISH);
|
||||||
|
}
|
||||||
|
|
||||||
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_EAP_RESPONSE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Wait EAP response
|
||||||
|
case EAP_TLS_STATE_EAP_RESPONSE:
|
||||||
|
|
||||||
|
// On timeout
|
||||||
|
if (sec_prot_result_timeout_check(&data->common)) {
|
||||||
|
// Do nothing for now
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_info("EAP-TLS EAP response, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
// Handle EAP response
|
||||||
|
if (radius_eap_tls_sec_prot_message_handle(prot, data_ptr, &length) != EAP_TLS_MSG_CONTINUE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send to radius client
|
||||||
|
data->radius_client_send(data->radius_client_prot, (void *) &data->recv_eapol_pdu, length);
|
||||||
|
|
||||||
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_EAP_REQUEST);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EAP_TLS_STATE_FINISH:
|
||||||
|
tr_info("EAP-TLS finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
// KMP-FINISHED.indication,
|
||||||
|
prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys);
|
||||||
|
|
||||||
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_FINISHED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EAP_TLS_STATE_FINISHED: {
|
||||||
|
uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot);
|
||||||
|
tr_info("EAP-TLS finished, eui-64: %s", remote_eui_64 ? trace_array(sec_prot_remote_eui_64_addr_get(prot), 8) : "not set");
|
||||||
|
prot->timer_stop(prot);
|
||||||
|
prot->finished(prot);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_eap_tls_sec_prot_seq_id_update(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
|
||||||
|
data->eap_id_seq++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_WS */
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Arm Limited and affiliates.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RADIUS_EAP_TLS_SEC_PROT_H_
|
||||||
|
#define RADIUS_EAP_TLS_SEC_PROT_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Authenticator RADIUS EAP-TLS security protocol. Specified in RFC 5216.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radius_eap_tls_sec_prot_register register authenticator EAP-TLS protocol to KMP service
|
||||||
|
*
|
||||||
|
* \param service KMP service
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*/
|
||||||
|
int8_t radius_eap_tls_sec_prot_register(kmp_service_t *service);
|
||||||
|
|
||||||
|
#endif /* RADIUS_EAP_TLS_SEC_PROT_H_ */
|
|
@ -404,7 +404,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set retry timeout based on network size
|
// Set retry timeout based on network size
|
||||||
data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
|
data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout;
|
||||||
|
|
||||||
// Store sequence ID
|
// Store sequence ID
|
||||||
supp_eap_tls_sec_prot_seq_id_update(prot);
|
supp_eap_tls_sec_prot_seq_id_update(prot);
|
||||||
|
@ -449,7 +449,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
supp_eap_tls_sec_prot_seq_id_update(prot);
|
supp_eap_tls_sec_prot_seq_id_update(prot);
|
||||||
|
|
||||||
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_REQUEST);
|
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_REQUEST);
|
||||||
data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
|
data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout;
|
||||||
|
|
||||||
// Initialize TLS protocol
|
// Initialize TLS protocol
|
||||||
if (supp_eap_tls_sec_prot_init_tls(prot) < 0) {
|
if (supp_eap_tls_sec_prot_init_tls(prot) < 0) {
|
||||||
|
@ -483,7 +483,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
// Store sequence ID
|
// Store sequence ID
|
||||||
if (supp_eap_tls_sec_prot_seq_id_update(prot)) {
|
if (supp_eap_tls_sec_prot_seq_id_update(prot)) {
|
||||||
// When receiving a new sequence number, adds more time for re-send if no response
|
// When receiving a new sequence number, adds more time for re-send if no response
|
||||||
data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
|
data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All fragments received for a message
|
// All fragments received for a message
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "Security/protocols/sec_prot.h"
|
#include "Security/protocols/sec_prot.h"
|
||||||
#include "Security/protocols/sec_prot_lib.h"
|
#include "Security/protocols/sec_prot_lib.h"
|
||||||
#include "Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.h"
|
#include "Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.h"
|
||||||
#include "Service_Libs/hmac/hmac_sha1.h"
|
#include "Service_Libs/hmac/hmac_md.h"
|
||||||
#include "Service_Libs/nist_aes_kw/nist_aes_kw.h"
|
#include "Service_Libs/nist_aes_kw/nist_aes_kw.h"
|
||||||
|
|
||||||
#ifdef HAVE_WS
|
#ifdef HAVE_WS
|
||||||
|
@ -234,7 +234,7 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case FWH_MESSAGE_1: {
|
case FWH_MESSAGE_1: {
|
||||||
uint8_t pmkid[PMKID_LEN];
|
uint8_t pmkid[PMKID_LEN];
|
||||||
if (sec_prot_lib_pmkid_generate(prot, pmkid, true) < 0) {
|
if (sec_prot_lib_pmkid_generate(prot, pmkid, true, false, NULL) < 0) {
|
||||||
ns_dyn_mem_free(kde_start);
|
ns_dyn_mem_free(kde_start);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -313,7 +313,7 @@ static int8_t auth_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_
|
||||||
static void auth_fwh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
static void auth_fwh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
||||||
{
|
{
|
||||||
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
|
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
|
||||||
sec_prot_timer_timeout_handle(prot, &data->common, &prot->prot_cfg->sec_prot_trickle_params, ticks);
|
sec_prot_timer_timeout_handle(prot, &data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
|
@ -350,7 +350,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_1);
|
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_1);
|
||||||
|
|
||||||
// Start trickle timer to re-send if no response
|
// Start trickle timer to re-send if no response
|
||||||
sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
|
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||||
|
|
||||||
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_2);
|
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_2);
|
||||||
break;
|
break;
|
||||||
|
@ -378,7 +378,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_3);
|
auth_fwh_sec_prot_message_send(prot, FWH_MESSAGE_3);
|
||||||
|
|
||||||
// Start trickle timer to re-send if no response
|
// Start trickle timer to re-send if no response
|
||||||
sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
|
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||||
|
|
||||||
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_4);
|
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_4);
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
// Reset PTK mismatch
|
// Reset PTK mismatch
|
||||||
sec_prot_keys_ptk_mismatch_reset(prot->sec_keys);
|
sec_prot_keys_ptk_mismatch_reset(prot->sec_keys);
|
||||||
// Update PTK
|
// Update PTK
|
||||||
sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk, prot->timer_cfg->ptk_lifetime);
|
sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk, prot->sec_cfg->timer_cfg.ptk_lifetime);
|
||||||
sec_prot_keys_ptk_eui_64_write(prot->sec_keys, data->remote_eui64);
|
sec_prot_keys_ptk_eui_64_write(prot->sec_keys, data->remote_eui64);
|
||||||
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH);
|
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include "Security/protocols/sec_prot.h"
|
#include "Security/protocols/sec_prot.h"
|
||||||
#include "Security/protocols/sec_prot_lib.h"
|
#include "Security/protocols/sec_prot_lib.h"
|
||||||
#include "Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h"
|
#include "Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h"
|
||||||
#include "Service_Libs/hmac/hmac_sha1.h"
|
#include "Service_Libs/hmac/hmac_md.h"
|
||||||
#include "Service_Libs/nist_aes_kw/nist_aes_kw.h"
|
#include "Service_Libs/nist_aes_kw/nist_aes_kw.h"
|
||||||
|
|
||||||
#ifdef HAVE_WS
|
#ifdef HAVE_WS
|
||||||
|
@ -139,7 +139,7 @@ static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot)
|
||||||
sec_prot_init(&data->common);
|
sec_prot_init(&data->common);
|
||||||
sec_prot_state_set(prot, &data->common, FWH_STATE_INIT);
|
sec_prot_state_set(prot, &data->common, FWH_STATE_INIT);
|
||||||
|
|
||||||
data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
|
data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout;
|
||||||
data->msg3_received = false;
|
data->msg3_received = false;
|
||||||
data->msg3_retry_wait = false;
|
data->msg3_retry_wait = false;
|
||||||
data->recv_replay_cnt = 0;
|
data->recv_replay_cnt = 0;
|
||||||
|
@ -337,7 +337,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
if (sec_prot_result_ok_check(&data->common)) {
|
if (sec_prot_result_ok_check(&data->common)) {
|
||||||
// Send 4WH message 2
|
// Send 4WH message 2
|
||||||
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2);
|
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2);
|
||||||
data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
|
data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout;
|
||||||
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3);
|
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3);
|
||||||
} else {
|
} else {
|
||||||
// Ready to be deleted
|
// Ready to be deleted
|
||||||
|
@ -365,7 +365,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
|
|
||||||
// Send 4WH message 2
|
// Send 4WH message 2
|
||||||
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2);
|
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2);
|
||||||
data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
|
data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout;
|
||||||
return;
|
return;
|
||||||
} else if (data->recv_msg != FWH_MESSAGE_3) {
|
} else if (data->recv_msg != FWH_MESSAGE_3) {
|
||||||
return;
|
return;
|
||||||
|
@ -392,7 +392,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
|
|
||||||
// Sends 4WH Message 4
|
// Sends 4WH Message 4
|
||||||
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4);
|
supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4);
|
||||||
data->common.ticks = prot->prot_cfg->sec_prot_retry_timeout;
|
data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout;
|
||||||
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH);
|
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -409,7 +409,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
|
|
||||||
tr_info("4WH: finish, wait Message 3 retry");
|
tr_info("4WH: finish, wait Message 3 retry");
|
||||||
|
|
||||||
sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk, prot->timer_cfg->ptk_lifetime);
|
sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk, prot->sec_cfg->timer_cfg.ptk_lifetime);
|
||||||
sec_prot_keys_ptk_eui_64_write(prot->sec_keys, data->remote_eui64);
|
sec_prot_keys_ptk_eui_64_write(prot->sec_keys, data->remote_eui64);
|
||||||
|
|
||||||
data->common.ticks = 60 * 10; // 60 seconds
|
data->common.ticks = 60 * 10; // 60 seconds
|
||||||
|
@ -473,7 +473,7 @@ static int8_t supp_fwh_sec_prot_ptk_generate(sec_prot_t *prot, sec_prot_keys_t *
|
||||||
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
|
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
|
||||||
|
|
||||||
uint8_t local_eui64[8];
|
uint8_t local_eui64[8];
|
||||||
prot->addr_get(prot, local_eui64, data->remote_eui64);
|
prot->addr_get(prot, local_eui64, NULL);
|
||||||
|
|
||||||
uint8_t *remote_nonce = data->recv_eapol_pdu.msg.key.key_nonce;
|
uint8_t *remote_nonce = data->recv_eapol_pdu.msg.key.key_nonce;
|
||||||
if (!remote_nonce) {
|
if (!remote_nonce) {
|
||||||
|
@ -553,11 +553,24 @@ static int8_t supp_fwh_kde_handle(sec_prot_t *prot)
|
||||||
if (kde_pmkid_read(kde, kde_len, recv_pmkid) < 0) {
|
if (kde_pmkid_read(kde, kde_len, recv_pmkid) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (sec_prot_lib_pmkid_generate(prot, calc_pmkid, false) < 0) {
|
/* Fix the used EUI-64 for the length of the 4WH handshake using the PMKID. Try
|
||||||
|
* first primary BR EUI-64 (e.g. validated by PTK procedure) for PMKID.
|
||||||
|
*/
|
||||||
|
if (sec_prot_lib_pmkid_generate(prot, calc_pmkid, false, false, data->remote_eui64) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
// If PMKID is not valid
|
||||||
if (memcmp(recv_pmkid, calc_pmkid, PMKID_LEN) != 0) {
|
if (memcmp(recv_pmkid, calc_pmkid, PMKID_LEN) != 0) {
|
||||||
goto error;
|
tr_info("PMKID mismatch, 1st EUI-64: %s", tr_array(data->remote_eui64, 8));
|
||||||
|
// Try alternate EUI-64 (e.g. received during security handshake)
|
||||||
|
if (sec_prot_lib_pmkid_generate(prot, calc_pmkid, false, true, data->remote_eui64) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
// If PMKID is not valid, fail
|
||||||
|
if (memcmp(recv_pmkid, calc_pmkid, PMKID_LEN) != 0) {
|
||||||
|
tr_error("PMKID mismatch, 2nd EUI-64: %s", tr_array(data->remote_eui64, 8));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -261,7 +261,7 @@ static int8_t auth_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_
|
||||||
static void auth_gkh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
static void auth_gkh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
||||||
{
|
{
|
||||||
gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot);
|
gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot);
|
||||||
sec_prot_timer_timeout_handle(prot, &data->common, &prot->prot_cfg->sec_prot_trickle_params, ticks);
|
sec_prot_timer_timeout_handle(prot, &data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
|
static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
|
@ -290,7 +290,7 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
auth_gkh_sec_prot_message_send(prot, GKH_MESSAGE_1);
|
auth_gkh_sec_prot_message_send(prot, GKH_MESSAGE_1);
|
||||||
|
|
||||||
// Start trickle timer to re-send if no response
|
// Start trickle timer to re-send if no response
|
||||||
sec_prot_timer_trickle_start(&data->common, &prot->prot_cfg->sec_prot_trickle_params);
|
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||||
|
|
||||||
sec_prot_state_set(prot, &data->common, GKH_STATE_MESSAGE_2);
|
sec_prot_state_set(prot, &data->common, GKH_STATE_MESSAGE_2);
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,7 @@ static int8_t key_sec_prot_initial_key_send(sec_prot_t *prot, sec_prot_keys_t *s
|
||||||
uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys);
|
uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys);
|
||||||
uint8_t pmkid[PMKID_LEN];
|
uint8_t pmkid[PMKID_LEN];
|
||||||
if (pmk) {
|
if (pmk) {
|
||||||
if (sec_prot_lib_pmkid_generate(prot, pmkid, false) >= 0) {
|
if (sec_prot_lib_pmkid_generate(prot, pmkid, false, false, NULL) >= 0) {
|
||||||
kde_len += KDE_PMKID_LEN;
|
kde_len += KDE_PMKID_LEN;
|
||||||
} else {
|
} else {
|
||||||
pmk = NULL;
|
pmk = NULL;
|
||||||
|
@ -270,7 +270,7 @@ static int8_t key_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size)
|
||||||
if (kde_pmkid_read(kde, kde_len, remote_keyid) >= 0) {
|
if (kde_pmkid_read(kde, kde_len, remote_keyid) >= 0) {
|
||||||
tr_debug("recv PMKID: %s", trace_array(remote_keyid, 16));
|
tr_debug("recv PMKID: %s", trace_array(remote_keyid, 16));
|
||||||
uint8_t pmkid[PMKID_LEN];
|
uint8_t pmkid[PMKID_LEN];
|
||||||
if (sec_prot_lib_pmkid_generate(prot, pmkid, true) >= 0) {
|
if (sec_prot_lib_pmkid_generate(prot, pmkid, true, false, NULL) >= 0) {
|
||||||
if (memcmp(remote_keyid, pmkid, PMKID_LEN) == 0) {
|
if (memcmp(remote_keyid, pmkid, PMKID_LEN) == 0) {
|
||||||
prot->sec_keys->pmk_mismatch = false;
|
prot->sec_keys->pmk_mismatch = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,259 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Arm Limited and affiliates.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nsconfig.h"
|
||||||
|
#include "ns_types.h"
|
||||||
|
#include "eventOS_event.h"
|
||||||
|
#include "ns_trace.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "common_functions.h"
|
||||||
|
#include "Security/protocols/radius_sec_prot/avp_helper.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_WS
|
||||||
|
|
||||||
|
#define TRACE_GROUP "avp"
|
||||||
|
|
||||||
|
// RFC 2865
|
||||||
|
|
||||||
|
// 1 User-Name
|
||||||
|
#define AVP_TYPE_USER_NAME 1
|
||||||
|
// 4 for NAS-IP-Address
|
||||||
|
#define AVP_TYPE_NAS_IP_ADDRESS 4
|
||||||
|
// 5 NAS-Port
|
||||||
|
#define AVP_TYPE_NAS_PORT 5
|
||||||
|
// 12 Framed-MTU
|
||||||
|
#define AVP_TYPE_FRAMED_MTU 12
|
||||||
|
// 24 State
|
||||||
|
#define AVP_TYPE_STATE 24
|
||||||
|
// 26 Vendor-Specific
|
||||||
|
#define AVP_TYPE_VENDOR_SPECIFIC 26
|
||||||
|
// 30 Called-Station-Id
|
||||||
|
#define AVP_TYPE_CALLED_STATION_ID 30
|
||||||
|
// 31 Calling-Station-Id
|
||||||
|
#define AVP_TYPE_CALLING_STATION_ID 31
|
||||||
|
// 32 NAS-Identifier
|
||||||
|
#define AVP_TYPE_NAS_IDENTIFIER 32
|
||||||
|
// 61 NAS-Port-Type
|
||||||
|
#define AVP_TYPE_NAS_PORT_TYPE 61
|
||||||
|
|
||||||
|
// RFC 3579
|
||||||
|
|
||||||
|
// 79 EAP-Message
|
||||||
|
#define AVP_TYPE_EAP_MESSAGE 79
|
||||||
|
// 80 Message-Authenticator
|
||||||
|
#define AVP_TYPE_MESSAGE_AUTHENTICATOR 80
|
||||||
|
|
||||||
|
// RFC 3162
|
||||||
|
|
||||||
|
// 95 NAS-IPv6-Address
|
||||||
|
#define AVP_TYPE_NAS_IPV6_ADDRESS 95
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t *avp_header_write(uint8_t *ptr, const uint8_t type, const uint8_t data_length)
|
||||||
|
{
|
||||||
|
*ptr++ = type;
|
||||||
|
*ptr++ = data_length + AVP_FIXED_LEN;
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t *avp_search(uint8_t *ptr, uint16_t len, const uint8_t type, uint8_t *avp_len)
|
||||||
|
{
|
||||||
|
while (len >= AVP_FIXED_LEN) {
|
||||||
|
*avp_len = ptr[1];
|
||||||
|
|
||||||
|
// Validates length field
|
||||||
|
if (*avp_len > len) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr[0] == type) {
|
||||||
|
return ptr + AVP_FIXED_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > *avp_len) {
|
||||||
|
len -= *avp_len;
|
||||||
|
ptr += *avp_len;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t *avp_vpa_search(uint8_t *ptr, uint16_t len, const uint32_t vendor_id, const uint8_t vendor_type, uint8_t *vendor_len)
|
||||||
|
{
|
||||||
|
uint8_t avp_len = 0;
|
||||||
|
|
||||||
|
while (len >= AVP_FIXED_LEN) {
|
||||||
|
avp_len = ptr[1];
|
||||||
|
|
||||||
|
// Validates length field
|
||||||
|
if (avp_len > len) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr[0] == AVP_TYPE_VENDOR_SPECIFIC && avp_len >= 9) {
|
||||||
|
ptr[2] = 0;
|
||||||
|
uint32_t avp_vendor_id = common_read_32_bit(&ptr[2]);
|
||||||
|
*vendor_len = ptr[7];
|
||||||
|
if (avp_vendor_id == vendor_id && ptr[6] == vendor_type) {
|
||||||
|
return &ptr[8];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > avp_len) {
|
||||||
|
len -= avp_len;
|
||||||
|
ptr += avp_len;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_user_name_write(uint8_t *ptr, const uint8_t name_len, const uint8_t *name)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_USER_NAME, name_len);
|
||||||
|
memcpy(ptr, name, name_len);
|
||||||
|
return ptr + name_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_nas_ip_address_write(uint8_t *ptr, uint32_t addr)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_NAS_IP_ADDRESS, 4);
|
||||||
|
memcpy(ptr, &addr, 4);
|
||||||
|
return ptr + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_nas_port_write(uint8_t *ptr, const uint32_t port)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_NAS_PORT, 4);
|
||||||
|
ptr = common_write_32_bit(port, ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_framed_mtu_write(uint8_t *ptr, const uint32_t mtu)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_FRAMED_MTU, 4);
|
||||||
|
ptr = common_write_32_bit(mtu, ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_state_write(uint8_t *ptr, const uint8_t state_len, const uint8_t *state)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_STATE, state_len);
|
||||||
|
memcpy(ptr, state, state_len);
|
||||||
|
return ptr + state_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_called_station_id_write(uint8_t *ptr, const uint8_t id_len, const uint8_t *id)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_CALLED_STATION_ID, id_len);
|
||||||
|
memcpy(ptr, id, id_len);
|
||||||
|
return ptr + id_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_calling_station_id_write(uint8_t *ptr, const uint8_t id_len, const uint8_t *id)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_CALLING_STATION_ID, id_len);
|
||||||
|
memcpy(ptr, id, id_len);
|
||||||
|
return ptr + id_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_nas_identifier_write(uint8_t *ptr, const uint8_t id_len, const uint8_t *id)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_NAS_IDENTIFIER, id_len);
|
||||||
|
memcpy(ptr, id, id_len);
|
||||||
|
return ptr + id_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_nas_port_type_write(uint8_t *ptr, const uint32_t port_type)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_NAS_PORT_TYPE, 4);
|
||||||
|
ptr = common_write_32_bit(port_type, ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_eap_message_write(uint8_t *ptr, const uint8_t eap_len, const uint8_t *eap)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_EAP_MESSAGE, eap_len);
|
||||||
|
memcpy(ptr, eap, eap_len);
|
||||||
|
return ptr + eap_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_message_authenticator_write(uint8_t *ptr, const uint8_t *auth)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_MESSAGE_AUTHENTICATOR, 16);
|
||||||
|
memcpy(ptr, auth, 16);
|
||||||
|
return ptr + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_nas_ipv6_address_write(uint8_t *ptr, const uint8_t *address)
|
||||||
|
{
|
||||||
|
ptr = avp_header_write(ptr, AVP_TYPE_NAS_IPV6_ADDRESS, 16);
|
||||||
|
memcpy(ptr, address, 16);
|
||||||
|
return ptr + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_eap_message_read(uint8_t *ptr, uint16_t len, uint8_t *eap_len)
|
||||||
|
{
|
||||||
|
ptr = avp_search(ptr, len, AVP_TYPE_EAP_MESSAGE, eap_len);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_message_authenticator_read(uint8_t *ptr, uint16_t len)
|
||||||
|
{
|
||||||
|
uint8_t auth_len = 0;
|
||||||
|
ptr = avp_search(ptr, len, AVP_TYPE_MESSAGE_AUTHENTICATOR, &auth_len);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (auth_len < 18) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_state_read(uint8_t *ptr, uint16_t len, uint8_t *state_len)
|
||||||
|
{
|
||||||
|
ptr = avp_search(ptr, len, AVP_TYPE_STATE, state_len);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *avp_vsa_ms_mppe_recv_key_read(uint8_t *ptr, uint16_t len, uint8_t *recv_key_len)
|
||||||
|
{
|
||||||
|
const uint32_t vendor_id = 311;
|
||||||
|
const uint8_t vendor_type = 17;
|
||||||
|
|
||||||
|
ptr = avp_vpa_search(ptr, len, vendor_id, vendor_type, recv_key_len);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,239 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Arm Limited and affiliates.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVP_HELPER_H_
|
||||||
|
#define AVP_HELPER_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RADIUS AVP helper functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AVP_FIXED_LEN 2 // type, length
|
||||||
|
#define AVP_VALUE_MAX_LEN 253 // 255 - type field - length field
|
||||||
|
|
||||||
|
#define AVP_TYPE_USER_NAME_LEN(len) (AVP_FIXED_LEN + len)
|
||||||
|
#define AVP_TYPE_NAS_IP_ADDRESS_LEN (AVP_FIXED_LEN + 4)
|
||||||
|
#define AVP_TYPE_NAS_PORT_LEN (AVP_FIXED_LEN + 4)
|
||||||
|
#define AVP_TYPE_FRAMED_MTU_LEN (AVP_FIXED_LEN + 4)
|
||||||
|
#define AVP_TYPE_STATE_LEN (AVP_FIXED_LEN + 8)
|
||||||
|
//#define AVP_TYPE_VENDOR_SPECIFIC 26
|
||||||
|
#define AVP_TYPE_CALLED_STATION_ID_LEN(len) (AVP_FIXED_LEN + len)
|
||||||
|
#define AVP_TYPE_CALLING_STATION_ID_LEN(len) (AVP_FIXED_LEN + len)
|
||||||
|
#define AVP_TYPE_NAS_IDENTIFIER_LEN(len) (AVP_FIXED_LEN + len)
|
||||||
|
#define AVP_TYPE_NAS_PORT_TYPE_LEN (AVP_FIXED_LEN + 4)
|
||||||
|
#define AVP_TYPE_EAP_MESSAGE_LEN(len) (AVP_FIXED_LEN + len)
|
||||||
|
#define AVP_TYPE_MESSAGE_AUTHENTICATOR_LEN (AVP_FIXED_LEN + 16)
|
||||||
|
#define AVP_TYPE_NAS_IPV6_ADDRESS_LEN (AVP_FIXED_LEN + 16)
|
||||||
|
|
||||||
|
// Wireless - IEEE 802.11
|
||||||
|
#define NAS_PORT_TYPE_WIRELESS_IEEE802_11 19
|
||||||
|
|
||||||
|
// EUI-64 in ascii string: 00-11-..-77
|
||||||
|
#define STATION_ID_LEN 16 + 7
|
||||||
|
|
||||||
|
// MTU value TBD
|
||||||
|
#define FRAMED_MTU 1400
|
||||||
|
|
||||||
|
#define NAS_PORT 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_user_name_write write use name
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param name_len name length
|
||||||
|
* \param name name
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_user_name_write(uint8_t *ptr, const uint8_t name_len, const uint8_t *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_nas_ip_address_write nas ip address
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param addr address
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_nas_ip_address_write(uint8_t *ptr, uint32_t addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_nas_port_write write nas port
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param port nas port
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_nas_port_write(uint8_t *ptr, const uint32_t port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_framed_mtu_write write frame mtu
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param mtu frame mtu
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_framed_mtu_write(uint8_t *ptr, const uint32_t mtu);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_state_write write write state
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param state_len state length
|
||||||
|
* \param state state
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_state_write(uint8_t *ptr, const uint8_t state_len, const uint8_t *state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_called_station_id_write write called station id
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param id_len identifier length
|
||||||
|
* \param id identifier
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_called_station_id_write(uint8_t *ptr, const uint8_t id_len, const uint8_t *id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_calling_station_id_write write calling station id
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param id_len identifier length
|
||||||
|
* \param id identifier
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_calling_station_id_write(uint8_t *ptr, const uint8_t id_len, const uint8_t *id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_nas_identifier_write write nas identifier
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param id_len nas identifier length
|
||||||
|
* \param id nas identifier
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_nas_identifier_write(uint8_t *ptr, const uint8_t id_len, const uint8_t *id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_nas_port_type_write write nas port type
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param port_type port type
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_nas_port_type_write(uint8_t *ptr, const uint32_t port_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_nas_message_write write eap message
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param eap_len eap length
|
||||||
|
* \param eap eap frame
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_eap_message_write(uint8_t *ptr, const uint8_t eap_len, const uint8_t *eap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_message_authenticator_write write message authenticator
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param auth authenticator
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_message_authenticator_write(uint8_t *ptr, const uint8_t *auth);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_nas_ipv6_address_write write ipv6 address
|
||||||
|
*
|
||||||
|
* \param ptr pointer where to write
|
||||||
|
* \param address ipv6 address
|
||||||
|
*
|
||||||
|
* return incremented write pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_nas_ipv6_address_write(uint8_t *ptr, const uint8_t *address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_eap_message_read read eap message
|
||||||
|
*
|
||||||
|
* \param ptr pointer to received message
|
||||||
|
* \param len received message length
|
||||||
|
* \param eap_len length of the eap frame
|
||||||
|
*
|
||||||
|
* return pointer to eap message or null
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_eap_message_read(uint8_t *ptr, uint16_t len, uint8_t *eap_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_message_authenticator_read read message authenticator
|
||||||
|
*
|
||||||
|
* \param ptr pointer to received message
|
||||||
|
* \param len received message length
|
||||||
|
*
|
||||||
|
* return pointer to message authenticator or null
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_message_authenticator_read(uint8_t *ptr, uint16_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_state_read read state
|
||||||
|
*
|
||||||
|
* \param ptr pointer to received message
|
||||||
|
* \param len received message length
|
||||||
|
* \param state_len length of the state
|
||||||
|
*
|
||||||
|
* return pointer to state or null
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_state_read(uint8_t *ptr, uint16_t len, uint8_t *state_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avp_vsa_ms_mppe_recv_key_read read vendor specific MS-MPPE-Recv-Key
|
||||||
|
*
|
||||||
|
* \param ptr pointer to received message
|
||||||
|
* \param len received message length
|
||||||
|
* \param recv_key_len length of the state
|
||||||
|
*
|
||||||
|
* return pointer to MS-MPPE-Recv-Key or null
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t *avp_vsa_ms_mppe_recv_key_read(uint8_t *ptr, uint16_t len, uint8_t *recv_key_len);
|
||||||
|
|
||||||
|
#endif /* AVP_HELPER_H_ */
|
|
@ -0,0 +1,995 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Arm Limited and affiliates.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nsconfig.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "ns_types.h"
|
||||||
|
#include "ns_list.h"
|
||||||
|
#include "ns_trace.h"
|
||||||
|
#include "common_functions.h"
|
||||||
|
#include "nsdynmemLIB.h"
|
||||||
|
#include "randLIB.h"
|
||||||
|
#include "mbedtls/sha256.h"
|
||||||
|
#include "mbedtls/md5.h"
|
||||||
|
#include "fhss_config.h"
|
||||||
|
#include "Service_Libs/Trickle/trickle.h"
|
||||||
|
#include "NWK_INTERFACE/Include/protocol.h"
|
||||||
|
#include "6LoWPAN/ws/ws_config.h"
|
||||||
|
#include "Security/protocols/sec_prot_cfg.h"
|
||||||
|
#include "Security/kmp/kmp_addr.h"
|
||||||
|
#include "Security/kmp/kmp_api.h"
|
||||||
|
#include "Security/PANA/pana_eap_header.h"
|
||||||
|
#include "Security/eapol/eapol_helper.h"
|
||||||
|
#include "Security/protocols/sec_prot_certs.h"
|
||||||
|
#include "Security/protocols/sec_prot_keys.h"
|
||||||
|
#include "Security/protocols/sec_prot.h"
|
||||||
|
#include "Security/protocols/sec_prot_lib.h"
|
||||||
|
#include "Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.h"
|
||||||
|
#include "Security/protocols/radius_sec_prot/radius_client_sec_prot.h"
|
||||||
|
#include "Security/protocols/radius_sec_prot/avp_helper.h"
|
||||||
|
#include "Security/protocols/tls_sec_prot/tls_sec_prot_lib.h"
|
||||||
|
#include "Service_Libs/hmac/hmac_md.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_WS
|
||||||
|
|
||||||
|
#define TRACE_GROUP "radp"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RADIUS_STATE_INIT = SEC_STATE_INIT,
|
||||||
|
RADIUS_STATE_CREATE_REQ = SEC_STATE_CREATE_REQ,
|
||||||
|
RADIUS_STATE_CREATE_RESP = SEC_STATE_CREATE_RESP,
|
||||||
|
RADIUS_STATE_CREATE_IND = SEC_STATE_CREATE_IND,
|
||||||
|
|
||||||
|
RADIUS_STATE_STATE_RESPONSE_ID = SEC_STATE_FIRST,
|
||||||
|
RADIUS_STATE_SEND_INITIAL_ACCESS_REQUEST,
|
||||||
|
RADIUS_STATE_SEND_ACCESS_REQUEST,
|
||||||
|
RADIUS_STATE_ACCESS_ACCEPT_REJECT_CHALLENGE,
|
||||||
|
RADIUS_STATE_ACCESS_REQUEST,
|
||||||
|
RADIUS_STATE_CONFIGURE,
|
||||||
|
RADIUS_STATE_PROCESS,
|
||||||
|
|
||||||
|
RADIUS_STATE_FINISH = SEC_STATE_FINISH,
|
||||||
|
RADIUS_STATE_FINISHED = SEC_STATE_FINISHED
|
||||||
|
} radius_client_sec_prot_state_e;
|
||||||
|
|
||||||
|
#define RADIUS_MSG_FIXED_LENGTH 20
|
||||||
|
#define RADIUS_ACCESS_REQUEST 1
|
||||||
|
#define RADIUS_ACCESS_ACCEPT 2
|
||||||
|
#define RADIUS_ACCESS_REJECT 3
|
||||||
|
#define RADIUS_ACCESS_CHALLENGE 11
|
||||||
|
|
||||||
|
#define MS_MPPE_RECV_KEY_SALT_LEN 2
|
||||||
|
#define MS_MPPE_RECV_KEY_BLOCK_LEN 16
|
||||||
|
|
||||||
|
typedef struct radius_client_sec_prot_lib_int_s radius_client_sec_prot_lib_int_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sec_prot_common_t common; /**< Common data */
|
||||||
|
sec_prot_t *radius_eap_tls_prot; /**< Radius EAP-TLS security protocol */
|
||||||
|
sec_prot_receive *radius_eap_tls_send; /**< Radius EAP-TLS security protocol send (receive from peer) */
|
||||||
|
uint8_t radius_eap_tls_header_size; /**< Radius EAP-TLS header size */
|
||||||
|
uint8_t new_pmk[PMK_LEN]; /**< New Pair Wise Master Key */
|
||||||
|
uint16_t recv_eap_msg_len; /**< Received EAP message length */
|
||||||
|
uint8_t *recv_eap_msg; /**< Received EAP message */
|
||||||
|
uint16_t send_radius_msg_len; /**< Send radius message length */
|
||||||
|
uint8_t *send_radius_msg; /**< Send radius message */
|
||||||
|
uint8_t identity_len; /**< Supplicant EAP identity length */
|
||||||
|
uint8_t *identity; /**< Supplicant EAP identity */
|
||||||
|
uint8_t radius_code; /**< Radius code that was received */
|
||||||
|
uint8_t radius_identifier; /**< Radius identifier that was last sent */
|
||||||
|
uint8_t request_authenticator[16]; /**< Radius request authenticator that was last sent */
|
||||||
|
uint8_t state_len; /**< Radius state length that was last received */
|
||||||
|
uint8_t *state; /**< Radius state that was last received */
|
||||||
|
uint8_t remote_eui_64_hash[8]; /**< Remote EUI-64 hash used for calling station id */
|
||||||
|
bool remote_eui_64_hash_set : 1; /**< Remote EUI-64 hash used for calling station id set */
|
||||||
|
bool new_pmk_set : 1; /**< New Pair Wise Master Key set */
|
||||||
|
} radius_client_sec_prot_int_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t radius_client_identifier; /**< Radius client identifier */
|
||||||
|
uint8_t local_eui64_hash[8]; /**< Local EUI-64 hash used for called stations id */
|
||||||
|
uint8_t hash_random[16]; /**< Random used to generate local and remote EUI-64 hashes */
|
||||||
|
bool local_eui64_hash_set : 1; /**< Local EUI-64 hash used for called stations id set */
|
||||||
|
bool hash_random_set : 1; /**< Random used to generate local and remote EUI-64 hashes set */
|
||||||
|
} radius_client_sec_prot_shared_t;
|
||||||
|
|
||||||
|
static uint16_t radius_client_sec_prot_size(void);
|
||||||
|
static int8_t radius_client_sec_prot_init(sec_prot_t *prot);
|
||||||
|
static void radius_client_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result);
|
||||||
|
static void radius_client_sec_prot_delete(sec_prot_t *prot);
|
||||||
|
static int8_t radius_client_sec_prot_receive_check(sec_prot_t *prot, const void *pdu, uint16_t size);
|
||||||
|
static int8_t radius_client_sec_prot_init_radius_eap_tls(sec_prot_t *prot);
|
||||||
|
static uint16_t radius_client_sec_prot_eap_avps_handle(uint16_t avp_length, uint8_t *avp_ptr, uint8_t *copy_to_ptr);
|
||||||
|
static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size);
|
||||||
|
static int8_t radius_client_sec_prot_radius_eap_receive(sec_prot_t *prot, void *pdu, uint16_t size);
|
||||||
|
static void radius_client_sec_prot_allocate_and_create_radius_message(sec_prot_t *prot);
|
||||||
|
static int8_t radius_client_sec_prot_radius_msg_send(sec_prot_t *prot);
|
||||||
|
static uint8_t radius_client_sec_prot_identifier_allocate(void);
|
||||||
|
static uint8_t radius_client_sec_prot_hex_to_ascii(uint8_t value);
|
||||||
|
static int8_t radius_client_sec_prot_eui_64_hash_generate(uint8_t *eui_64, uint8_t *hashed_eui_64);
|
||||||
|
static void radius_client_sec_prot_station_id_generate(uint8_t *eui_64, uint8_t *station_id_ptr);
|
||||||
|
static int8_t radius_client_sec_prot_message_authenticator_calc(sec_prot_t *prot, uint16_t msg_len, uint8_t *msg_ptr, uint8_t *auth_ptr);
|
||||||
|
static int8_t radius_client_sec_prot_response_authenticator_calc(sec_prot_t *prot, uint16_t msg_len, uint8_t *msg_ptr, uint8_t *auth_ptr);
|
||||||
|
static int8_t radius_client_sec_prot_ms_mppe_recv_key_pmk_decrypt(sec_prot_t *prot, uint8_t *recv_key, uint8_t recv_key_len, uint8_t *request_authenticator, uint8_t *pmk_ptr);
|
||||||
|
static void radius_client_sec_prot_finished_send(sec_prot_t *prot);
|
||||||
|
static void radius_client_sec_prot_state_machine(sec_prot_t *prot);
|
||||||
|
static void radius_client_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
|
||||||
|
|
||||||
|
#define radius_client_sec_prot_get(prot) (radius_client_sec_prot_int_t *) &prot->data
|
||||||
|
|
||||||
|
// Data shared between radius client instances
|
||||||
|
static radius_client_sec_prot_shared_t *shared_data = NULL;
|
||||||
|
|
||||||
|
int8_t radius_client_sec_prot_register(kmp_service_t *service)
|
||||||
|
{
|
||||||
|
if (!service) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kmp_service_sec_protocol_register(service, RADIUS_CLIENT_PROT, radius_client_sec_prot_size, radius_client_sec_prot_init) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t radius_client_sec_prot_size(void)
|
||||||
|
{
|
||||||
|
return sizeof(radius_client_sec_prot_int_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_client_sec_prot_init(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
prot->create_req = NULL;
|
||||||
|
prot->create_resp = radius_client_sec_prot_create_response;
|
||||||
|
prot->receive = radius_client_sec_prot_receive;
|
||||||
|
prot->receive_peer = radius_client_sec_prot_radius_eap_receive;
|
||||||
|
prot->delete = radius_client_sec_prot_delete;
|
||||||
|
prot->state_machine = radius_client_sec_prot_state_machine;
|
||||||
|
prot->timer_timeout = radius_client_sec_prot_timer_timeout;
|
||||||
|
prot->finished_send = radius_client_sec_prot_finished_send;
|
||||||
|
prot->receive_check = radius_client_sec_prot_receive_check;
|
||||||
|
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
|
||||||
|
sec_prot_init(&data->common);
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_INIT);
|
||||||
|
data->radius_eap_tls_prot = NULL;
|
||||||
|
data->radius_eap_tls_send = NULL;
|
||||||
|
data->radius_eap_tls_header_size = 0;
|
||||||
|
memset(data->new_pmk, 0, PMK_LEN);
|
||||||
|
data->recv_eap_msg_len = 0;
|
||||||
|
data->recv_eap_msg = NULL;
|
||||||
|
data->send_radius_msg_len = 0;
|
||||||
|
data->send_radius_msg = NULL;
|
||||||
|
data->identity_len = 0;
|
||||||
|
data->identity = NULL;
|
||||||
|
data->radius_code = 0;
|
||||||
|
data->radius_identifier = 0;
|
||||||
|
memset(data->request_authenticator, 0, 16);
|
||||||
|
data->state_len = 0;
|
||||||
|
data->state = NULL;
|
||||||
|
memset(data->remote_eui_64_hash, 0, 8);
|
||||||
|
data->remote_eui_64_hash_set = false;
|
||||||
|
data->new_pmk_set = false;
|
||||||
|
|
||||||
|
if (!shared_data) {
|
||||||
|
shared_data = ns_dyn_mem_alloc(sizeof(radius_client_sec_prot_shared_t));
|
||||||
|
if (!shared_data) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
shared_data->radius_client_identifier = 0;
|
||||||
|
memset(shared_data->local_eui64_hash, 0, 8);
|
||||||
|
memset(shared_data->hash_random, 0, 16);
|
||||||
|
shared_data->local_eui64_hash_set = false;
|
||||||
|
shared_data->hash_random_set = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_client_sec_prot_delete(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
|
||||||
|
if (data->recv_eap_msg != NULL) {
|
||||||
|
ns_dyn_mem_free(data->recv_eap_msg);
|
||||||
|
}
|
||||||
|
if (data->send_radius_msg != NULL) {
|
||||||
|
ns_dyn_mem_free(data->send_radius_msg);
|
||||||
|
}
|
||||||
|
if (data->identity != NULL) {
|
||||||
|
ns_dyn_mem_free(data->identity);
|
||||||
|
}
|
||||||
|
if (data->state != NULL) {
|
||||||
|
ns_dyn_mem_free(data->state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_client_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
|
||||||
|
// Call state machine
|
||||||
|
sec_prot_result_set(&data->common, result);
|
||||||
|
prot->state_machine_call(prot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_client_sec_prot_receive_check(sec_prot_t *prot, const void *pdu, uint16_t size)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
|
||||||
|
if (size >= 2) {
|
||||||
|
const uint8_t *radius_msg = pdu;
|
||||||
|
if (radius_msg[1] == data->radius_identifier) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_client_sec_prot_init_radius_eap_tls(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
if (data->radius_eap_tls_prot) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->radius_eap_tls_prot = prot->type_get(prot, SEC_PROT_TYPE_RADIUS_EAP_TLS);
|
||||||
|
if (!data->radius_eap_tls_prot) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data->radius_eap_tls_header_size = data->radius_eap_tls_prot->receive_peer_hdr_size;
|
||||||
|
data->radius_eap_tls_send = data->radius_eap_tls_prot->receive_peer;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t radius_client_sec_prot_eap_avps_handle(uint16_t avp_length, uint8_t *avp_ptr, uint8_t *copy_to_ptr)
|
||||||
|
{
|
||||||
|
// Calculate EAP AVPs length and copy EAP AVPs to continuous buffer if buffer is give
|
||||||
|
uint16_t eap_len = 0;
|
||||||
|
while (true) {
|
||||||
|
uint8_t avp_eap_len;
|
||||||
|
uint8_t *eap_message = avp_eap_message_read(avp_ptr, avp_length, &avp_eap_len);
|
||||||
|
if (eap_message) {
|
||||||
|
avp_eap_len -= AVP_FIXED_LEN;
|
||||||
|
|
||||||
|
// Calculate EAP AVPs length
|
||||||
|
eap_len += avp_eap_len;
|
||||||
|
|
||||||
|
// Copy EAP AVPs to continuous buffer
|
||||||
|
if (copy_to_ptr) {
|
||||||
|
memcpy(copy_to_ptr, eap_message, avp_eap_len);
|
||||||
|
copy_to_ptr += avp_eap_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t offset = eap_message - avp_ptr;
|
||||||
|
avp_length = avp_length - (offset + avp_eap_len);
|
||||||
|
avp_ptr = eap_message + avp_eap_len;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eap_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
|
||||||
|
if (size < RADIUS_MSG_FIXED_LENGTH) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *radius_msg_ptr = pdu;
|
||||||
|
|
||||||
|
uint8_t code = *radius_msg_ptr++;
|
||||||
|
uint8_t identifier = *radius_msg_ptr++;
|
||||||
|
/* If identifier does not match to sent identifier, silently ignore message,
|
||||||
|
already checked on socket if before routing the request to receive, so
|
||||||
|
this is double check to ensure correct routing */
|
||||||
|
if (identifier != data->radius_identifier) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t length = common_read_16_bit(radius_msg_ptr);
|
||||||
|
radius_msg_ptr += 2;
|
||||||
|
|
||||||
|
// Store response authenticator
|
||||||
|
uint8_t recv_response_authenticator[16];
|
||||||
|
memcpy(recv_response_authenticator, radius_msg_ptr, 16);
|
||||||
|
|
||||||
|
// Replace response authenticator with request authenticator
|
||||||
|
memcpy(radius_msg_ptr, data->request_authenticator, 16);
|
||||||
|
radius_msg_ptr += 16;
|
||||||
|
|
||||||
|
// Calculate expected response authenticator
|
||||||
|
uint8_t calc_response_authenticator[16];
|
||||||
|
if (radius_client_sec_prot_response_authenticator_calc(prot, length, pdu, calc_response_authenticator) < 0) {
|
||||||
|
tr_error("Could not calculate response authenticator MD5 hash");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that received and calculated response authenticator matches
|
||||||
|
if (memcmp(recv_response_authenticator, calc_response_authenticator, 16) != 0) {
|
||||||
|
tr_error("Invalid response authenticator recv: %s, calc: %s", tr_array(recv_response_authenticator, 16), tr_array(calc_response_authenticator, 16));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t avp_length = length - RADIUS_MSG_FIXED_LENGTH;
|
||||||
|
|
||||||
|
uint8_t *message_authenticator = avp_message_authenticator_read(radius_msg_ptr, avp_length);
|
||||||
|
if (message_authenticator == NULL) {
|
||||||
|
tr_error("No message authenticator");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store message authenticator
|
||||||
|
uint8_t recv_message_authenticator[16];
|
||||||
|
memcpy(recv_message_authenticator, message_authenticator, 16);
|
||||||
|
|
||||||
|
// Replace message authenticator with zero
|
||||||
|
memset(message_authenticator, 0, 16);
|
||||||
|
|
||||||
|
// Calculate expected message authenticator
|
||||||
|
uint8_t calc_message_authenticator[16];
|
||||||
|
if (radius_client_sec_prot_message_authenticator_calc(prot, length, pdu, calc_message_authenticator) < 0) {
|
||||||
|
tr_error("Could not calculate message authenticator HMAC-MD5 hash");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that received and calculated message authenticator matches
|
||||||
|
if (memcmp(recv_message_authenticator, calc_message_authenticator, 16) != 0) {
|
||||||
|
tr_error("Invalid message authenticator recv: %s, calc: %s", tr_array(recv_message_authenticator, 16), tr_array(calc_message_authenticator, 16));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate EAP AVPs length
|
||||||
|
data->recv_eap_msg_len = radius_client_sec_prot_eap_avps_handle(avp_length, radius_msg_ptr, NULL);
|
||||||
|
if (data->recv_eap_msg_len == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory for continuous EAP buffer
|
||||||
|
data->recv_eap_msg = ns_dyn_mem_temporary_alloc(data->recv_eap_msg_len + data->radius_eap_tls_header_size);
|
||||||
|
if (data->recv_eap_msg == NULL) {
|
||||||
|
tr_error("Cannot allocate eap msg");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy EAP AVPs to continuous buffer
|
||||||
|
uint16_t copy_eap_len = radius_client_sec_prot_eap_avps_handle(avp_length, radius_msg_ptr, data->recv_eap_msg + data->radius_eap_tls_header_size);
|
||||||
|
if (copy_eap_len != data->recv_eap_msg_len) {
|
||||||
|
ns_dyn_mem_free(data->recv_eap_msg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store state
|
||||||
|
uint8_t state_len;
|
||||||
|
uint8_t *state = avp_state_read(radius_msg_ptr, avp_length, &state_len);
|
||||||
|
if (state) {
|
||||||
|
state_len -= AVP_FIXED_LEN;
|
||||||
|
if (data->state && data->state_len != state_len) {
|
||||||
|
ns_dyn_mem_free(data->state);
|
||||||
|
data->state = NULL;
|
||||||
|
}
|
||||||
|
if (!data->state) {
|
||||||
|
data->state = ns_dyn_mem_temporary_alloc(state_len);
|
||||||
|
}
|
||||||
|
if (!data->state) {
|
||||||
|
tr_error("Cannot allocate state");
|
||||||
|
ns_dyn_mem_free(data->recv_eap_msg);
|
||||||
|
data->recv_eap_msg = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(data->state, state, state_len);
|
||||||
|
data->state_len = state_len;
|
||||||
|
} else {
|
||||||
|
if (data->state) {
|
||||||
|
ns_dyn_mem_free(data->state);
|
||||||
|
data->state = NULL;
|
||||||
|
data->state_len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code == RADIUS_ACCESS_ACCEPT) {
|
||||||
|
uint8_t recv_key_len;
|
||||||
|
uint8_t *recv_key = avp_vsa_ms_mppe_recv_key_read(radius_msg_ptr, avp_length, &recv_key_len);
|
||||||
|
if (recv_key && recv_key_len > AVP_FIXED_LEN) {
|
||||||
|
if (radius_client_sec_prot_ms_mppe_recv_key_pmk_decrypt(prot, recv_key,
|
||||||
|
recv_key_len - AVP_FIXED_LEN, data->request_authenticator, data->new_pmk) >= 0) {
|
||||||
|
data->new_pmk_set = true;
|
||||||
|
tr_info("RADIUS PMK: %s %s", tr_array(data->new_pmk, 16), tr_array(data->new_pmk + 16, 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data->radius_code = code;
|
||||||
|
data->recv_eap_msg_len += data->radius_eap_tls_header_size;
|
||||||
|
prot->state_machine(prot);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_client_sec_prot_radius_eap_receive(sec_prot_t *prot, void *pdu, uint16_t size)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
|
||||||
|
data->recv_eap_msg_len = size;
|
||||||
|
data->recv_eap_msg = pdu;
|
||||||
|
|
||||||
|
prot->state_machine(prot);
|
||||||
|
|
||||||
|
data->recv_eap_msg_len = 0;
|
||||||
|
data->recv_eap_msg = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t radius_client_sec_prot_identifier_allocate(void)
|
||||||
|
{
|
||||||
|
return shared_data->radius_client_identifier++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t radius_client_sec_prot_eui_64_hash_get(sec_prot_t *prot, uint8_t *local_eui_64_hash, uint8_t *remote_eui_64_hash, bool remote_eui_64_hash_set)
|
||||||
|
{
|
||||||
|
if (!shared_data->local_eui64_hash_set || !remote_eui_64_hash_set) {
|
||||||
|
uint8_t local_eui64[8];
|
||||||
|
uint8_t remote_eui64[8];
|
||||||
|
prot->addr_get(prot, local_eui64, remote_eui64);
|
||||||
|
if (!shared_data->local_eui64_hash_set) {
|
||||||
|
radius_client_sec_prot_eui_64_hash_generate(local_eui64, shared_data->local_eui64_hash);
|
||||||
|
shared_data->local_eui64_hash_set = true;
|
||||||
|
}
|
||||||
|
if (!remote_eui_64_hash_set) {
|
||||||
|
radius_client_sec_prot_eui_64_hash_generate(remote_eui64, remote_eui_64_hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(local_eui_64_hash, shared_data->local_eui64_hash, 8);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_client_sec_prot_allocate_and_create_radius_message(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
|
||||||
|
// code(1), packet-identifier(1), length(2), authenticator(16)
|
||||||
|
uint16_t radius_msg_length = RADIUS_MSG_FIXED_LENGTH;
|
||||||
|
|
||||||
|
eapol_pdu_t *eap_hdr = (eapol_pdu_t *) data->recv_eap_msg;
|
||||||
|
|
||||||
|
if (eap_hdr->msg.eap.type == EAP_IDENTITY) {
|
||||||
|
uint16_t id_len = eap_hdr->msg.eap.length;
|
||||||
|
// Calculate identity length
|
||||||
|
if (id_len > 5) {
|
||||||
|
id_len -= 5;
|
||||||
|
}
|
||||||
|
// Maximum length is 253 bytes
|
||||||
|
if (id_len > AVP_VALUE_MAX_LEN) {
|
||||||
|
id_len = AVP_VALUE_MAX_LEN;
|
||||||
|
}
|
||||||
|
data->identity = ns_dyn_mem_temporary_alloc(id_len);
|
||||||
|
if (!data->identity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data->identity_len = id_len;
|
||||||
|
memcpy(data->identity, eap_hdr->msg.eap.data_ptr, id_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate eap fragments
|
||||||
|
uint16_t eap_len = eap_hdr->msg.eap.length;
|
||||||
|
while (true) {
|
||||||
|
if (eap_len > AVP_VALUE_MAX_LEN) {
|
||||||
|
eap_len -= AVP_VALUE_MAX_LEN;
|
||||||
|
radius_msg_length += AVP_TYPE_EAP_MESSAGE_LEN(AVP_VALUE_MAX_LEN);
|
||||||
|
} else {
|
||||||
|
radius_msg_length += AVP_TYPE_EAP_MESSAGE_LEN(eap_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
radius_msg_length += AVP_TYPE_USER_NAME_LEN(data->identity_len);
|
||||||
|
radius_msg_length += AVP_TYPE_NAS_PORT_LEN;
|
||||||
|
radius_msg_length += AVP_TYPE_FRAMED_MTU_LEN;
|
||||||
|
|
||||||
|
if (data->state) {
|
||||||
|
radius_msg_length += AVP_FIXED_LEN + data->state_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
radius_msg_length += AVP_TYPE_CALLED_STATION_ID_LEN(STATION_ID_LEN);
|
||||||
|
radius_msg_length += AVP_TYPE_CALLING_STATION_ID_LEN(STATION_ID_LEN);
|
||||||
|
radius_msg_length += AVP_TYPE_NAS_IDENTIFIER_LEN(STATION_ID_LEN);
|
||||||
|
radius_msg_length += AVP_TYPE_NAS_PORT_TYPE_LEN;
|
||||||
|
radius_msg_length += AVP_TYPE_MESSAGE_AUTHENTICATOR_LEN;
|
||||||
|
radius_msg_length += AVP_TYPE_NAS_IPV6_ADDRESS_LEN;
|
||||||
|
|
||||||
|
uint8_t *radius_msg_ptr = ns_dyn_mem_temporary_alloc(radius_msg_length);
|
||||||
|
uint8_t *radius_msg_start_ptr = radius_msg_ptr;
|
||||||
|
|
||||||
|
*radius_msg_ptr++ = RADIUS_ACCESS_REQUEST; // code
|
||||||
|
data->radius_identifier = radius_client_sec_prot_identifier_allocate();
|
||||||
|
*radius_msg_ptr++ = data->radius_identifier; // identifier
|
||||||
|
radius_msg_ptr = common_write_16_bit(radius_msg_length, radius_msg_ptr); // length
|
||||||
|
|
||||||
|
randLIB_get_n_bytes_random(data->request_authenticator, 16);
|
||||||
|
memcpy(radius_msg_ptr, data->request_authenticator, 16); // request authenticator
|
||||||
|
radius_msg_ptr += 16;
|
||||||
|
|
||||||
|
radius_msg_ptr = avp_user_name_write(radius_msg_ptr, data->identity_len, data->identity);
|
||||||
|
|
||||||
|
uint8_t local_eui_64_hash[8];
|
||||||
|
radius_client_sec_prot_eui_64_hash_get(prot, local_eui_64_hash, data->remote_eui_64_hash, data->remote_eui_64_hash_set);
|
||||||
|
data->remote_eui_64_hash_set = true;
|
||||||
|
|
||||||
|
uint8_t station_id[STATION_ID_LEN];
|
||||||
|
|
||||||
|
radius_client_sec_prot_station_id_generate(data->remote_eui_64_hash, station_id);
|
||||||
|
radius_msg_ptr = avp_calling_station_id_write(radius_msg_ptr, STATION_ID_LEN, station_id);
|
||||||
|
|
||||||
|
radius_client_sec_prot_station_id_generate(local_eui_64_hash, station_id);
|
||||||
|
radius_msg_ptr = avp_called_station_id_write(radius_msg_ptr, STATION_ID_LEN, station_id);
|
||||||
|
|
||||||
|
radius_msg_ptr = avp_nas_identifier_write(radius_msg_ptr, STATION_ID_LEN, station_id);
|
||||||
|
|
||||||
|
radius_msg_ptr = avp_nas_port_write(radius_msg_ptr, NAS_PORT);
|
||||||
|
|
||||||
|
radius_msg_ptr = avp_framed_mtu_write(radius_msg_ptr, FRAMED_MTU);
|
||||||
|
|
||||||
|
if (data->state) {
|
||||||
|
radius_msg_ptr = avp_state_write(radius_msg_ptr, data->state_len, data->state);
|
||||||
|
}
|
||||||
|
|
||||||
|
radius_msg_ptr = avp_nas_port_type_write(radius_msg_ptr, NAS_PORT_TYPE_WIRELESS_IEEE802_11);
|
||||||
|
|
||||||
|
uint8_t address[16];
|
||||||
|
prot->ip_addr_get(prot, address);
|
||||||
|
radius_msg_ptr = avp_nas_ipv6_address_write(radius_msg_ptr, address);
|
||||||
|
|
||||||
|
// Write eap fragments
|
||||||
|
eap_len = eap_hdr->msg.eap.length;
|
||||||
|
uint8_t *eap_ptr = eap_hdr->packet_body;
|
||||||
|
while (true) {
|
||||||
|
if (eap_len > AVP_VALUE_MAX_LEN) {
|
||||||
|
eap_len -= AVP_VALUE_MAX_LEN;
|
||||||
|
radius_msg_ptr = avp_eap_message_write(radius_msg_ptr, AVP_VALUE_MAX_LEN, eap_ptr);
|
||||||
|
eap_ptr += AVP_VALUE_MAX_LEN;
|
||||||
|
} else {
|
||||||
|
radius_msg_ptr = avp_eap_message_write(radius_msg_ptr, eap_len, eap_ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *message_auth_ptr = radius_msg_ptr;
|
||||||
|
uint8_t message_auth[16];
|
||||||
|
memset(message_auth, 0, 16); // zero for value calculation
|
||||||
|
radius_msg_ptr = avp_message_authenticator_write(radius_msg_ptr, message_auth);
|
||||||
|
// Calculate message authenticator
|
||||||
|
if (radius_client_sec_prot_message_authenticator_calc(prot, radius_msg_length, radius_msg_start_ptr, message_auth) < 0) {
|
||||||
|
ns_dyn_mem_free(radius_msg_start_ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Write message authenticator
|
||||||
|
radius_msg_ptr = avp_message_authenticator_write(message_auth_ptr, message_auth);
|
||||||
|
|
||||||
|
// Store message for sending
|
||||||
|
if (data->send_radius_msg != NULL) {
|
||||||
|
ns_dyn_mem_free(data->send_radius_msg);
|
||||||
|
}
|
||||||
|
data->send_radius_msg = radius_msg_start_ptr;
|
||||||
|
data->send_radius_msg_len = radius_msg_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_client_sec_prot_radius_msg_send(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
|
||||||
|
if (!data->send_radius_msg || data->send_radius_msg_len == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prot->send(prot, data->send_radius_msg, data->send_radius_msg_len) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data->send_radius_msg = NULL;
|
||||||
|
data->send_radius_msg_len = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_client_sec_prot_eui_64_hash_generate(uint8_t *eui_64, uint8_t *hashed_eui_64)
|
||||||
|
{
|
||||||
|
int8_t ret_val = 0;
|
||||||
|
|
||||||
|
if (!shared_data->hash_random_set) {
|
||||||
|
randLIB_get_n_bytes_random(shared_data->hash_random, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t hashed_string[24];
|
||||||
|
memcpy(&hashed_string[0], eui_64, 8);
|
||||||
|
memcpy(&hashed_string[8], shared_data->hash_random, 16);
|
||||||
|
|
||||||
|
mbedtls_sha256_context ctx;
|
||||||
|
|
||||||
|
mbedtls_sha256_init(&ctx);
|
||||||
|
|
||||||
|
if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
|
||||||
|
ret_val = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mbedtls_sha256_update_ret(&ctx, hashed_string, 24) != 0) {
|
||||||
|
ret_val = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t output[32];
|
||||||
|
|
||||||
|
if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
|
||||||
|
ret_val = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(hashed_eui_64, output, 8);
|
||||||
|
|
||||||
|
error:
|
||||||
|
mbedtls_sha256_free(&ctx);
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t radius_client_sec_prot_hex_to_ascii(uint8_t value)
|
||||||
|
{
|
||||||
|
char character = '0';
|
||||||
|
if (value <= 9) {
|
||||||
|
character = '0' + value;
|
||||||
|
} else if (value >= 0x0A && value <= 0x0F) {
|
||||||
|
character = 'A' + value - 0x0A;
|
||||||
|
}
|
||||||
|
return character;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_client_sec_prot_station_id_generate(uint8_t *eui_64, uint8_t *station_id_ptr)
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
|
*station_id_ptr++ = radius_client_sec_prot_hex_to_ascii(eui_64[i] / 16);
|
||||||
|
*station_id_ptr++ = radius_client_sec_prot_hex_to_ascii(eui_64[i] % 16);
|
||||||
|
if (i != 7) {
|
||||||
|
*station_id_ptr++ = '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_client_sec_prot_message_authenticator_calc(sec_prot_t *prot, uint16_t msg_len, uint8_t *msg_ptr, uint8_t *auth_ptr)
|
||||||
|
{
|
||||||
|
const uint8_t *key = prot->sec_cfg->radius_cfg.radius_shared_secret;
|
||||||
|
uint16_t key_len = prot->sec_cfg->radius_cfg.radius_shared_secret_len;
|
||||||
|
if (prot->sec_cfg->radius_cfg.radius_shared_secret_len == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef MBEDTLS_MD5_C
|
||||||
|
tr_error("FATAL: MD5 MBEDTLS_MD5_C not enabled");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (hmac_md_calc(ALG_HMAC_MD5, key, key_len, msg_ptr, msg_len, auth_ptr, 16) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_client_sec_prot_response_authenticator_calc(sec_prot_t *prot, uint16_t msg_len, uint8_t *msg_ptr, uint8_t *auth_ptr)
|
||||||
|
{
|
||||||
|
#ifdef MBEDTLS_MD5_C
|
||||||
|
const uint8_t *key = prot->sec_cfg->radius_cfg.radius_shared_secret;
|
||||||
|
uint16_t key_len = prot->sec_cfg->radius_cfg.radius_shared_secret_len;
|
||||||
|
if (prot->sec_cfg->radius_cfg.radius_shared_secret_len == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t ret_value = -1;
|
||||||
|
|
||||||
|
mbedtls_md5_context ctx;
|
||||||
|
|
||||||
|
mbedtls_md5_init(&ctx);
|
||||||
|
|
||||||
|
if (mbedtls_md5_starts_ret(&ctx) != 0) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mbedtls_md5_update_ret(&ctx, msg_ptr, msg_len) != 0) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mbedtls_md5_update_ret(&ctx, key, key_len) != 0) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mbedtls_md5_finish_ret(&ctx, auth_ptr) != 0) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret_value = 0;
|
||||||
|
|
||||||
|
end:
|
||||||
|
mbedtls_md5_free(&ctx);
|
||||||
|
|
||||||
|
return ret_value;
|
||||||
|
#else
|
||||||
|
(void) prot;
|
||||||
|
(void) msg_len;
|
||||||
|
(void) msg_ptr;
|
||||||
|
(void) auth_ptr;
|
||||||
|
|
||||||
|
tr_error("FATAL: MD5 MBEDTLS_MD5_C not enabled");
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t radius_client_sec_prot_ms_mppe_recv_key_pmk_decrypt(sec_prot_t *prot, uint8_t *recv_key, uint8_t recv_key_len, uint8_t *request_authenticator, uint8_t *pmk_ptr)
|
||||||
|
{
|
||||||
|
#ifdef MBEDTLS_MD5_C
|
||||||
|
const uint8_t *key = prot->sec_cfg->radius_cfg.radius_shared_secret;
|
||||||
|
uint16_t key_len = prot->sec_cfg->radius_cfg.radius_shared_secret_len;
|
||||||
|
if (prot->sec_cfg->radius_cfg.radius_shared_secret_len == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recv_key_len < MS_MPPE_RECV_KEY_SALT_LEN + MS_MPPE_RECV_KEY_BLOCK_LEN) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *salt_ptr = recv_key;
|
||||||
|
uint8_t *cipher_text_ptr = recv_key + MS_MPPE_RECV_KEY_SALT_LEN;
|
||||||
|
int16_t cipher_text_len = recv_key_len - MS_MPPE_RECV_KEY_SALT_LEN;
|
||||||
|
|
||||||
|
uint8_t plain_text[cipher_text_len];
|
||||||
|
uint8_t *plain_text_ptr = plain_text;
|
||||||
|
|
||||||
|
bool first_interm_b_value = true;
|
||||||
|
uint8_t interm_b_val[MS_MPPE_RECV_KEY_BLOCK_LEN];
|
||||||
|
|
||||||
|
bool md5_failed = false;
|
||||||
|
|
||||||
|
mbedtls_md5_context ctx;
|
||||||
|
|
||||||
|
while (cipher_text_len >= MS_MPPE_RECV_KEY_BLOCK_LEN) {
|
||||||
|
mbedtls_md5_init(&ctx);
|
||||||
|
|
||||||
|
if (mbedtls_md5_starts_ret(&ctx) != 0) {
|
||||||
|
md5_failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mbedtls_md5_update_ret(&ctx, key, key_len) != 0) {
|
||||||
|
md5_failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first_interm_b_value) {
|
||||||
|
// b(1) = MD5(secret + request-authenticator + salt)
|
||||||
|
if (mbedtls_md5_update_ret(&ctx, request_authenticator, MS_MPPE_RECV_KEY_BLOCK_LEN) != 0) {
|
||||||
|
md5_failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mbedtls_md5_update_ret(&ctx, salt_ptr, MS_MPPE_RECV_KEY_SALT_LEN) != 0) {
|
||||||
|
md5_failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// b(i) = MD5(secret + cipher_text(i - 1))
|
||||||
|
if (mbedtls_md5_update_ret(&ctx, cipher_text_ptr - MS_MPPE_RECV_KEY_BLOCK_LEN, MS_MPPE_RECV_KEY_BLOCK_LEN) != 0) {
|
||||||
|
md5_failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mbedtls_md5_finish_ret(&ctx, interm_b_val) != 0) {
|
||||||
|
md5_failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mbedtls_md5_free(&ctx);
|
||||||
|
|
||||||
|
first_interm_b_value = false;
|
||||||
|
|
||||||
|
for (uint8_t index = 0; index < MS_MPPE_RECV_KEY_BLOCK_LEN; index++) {
|
||||||
|
*plain_text_ptr++ = *cipher_text_ptr++ ^ interm_b_val[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
cipher_text_len -= MS_MPPE_RECV_KEY_BLOCK_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (md5_failed) {
|
||||||
|
mbedtls_md5_free(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (md5_failed || cipher_text_len != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pmk_ptr, plain_text + 1, PMK_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
(void) prot;
|
||||||
|
(void) recv_key;
|
||||||
|
(void) recv_key_len;
|
||||||
|
(void) request_authenticator;
|
||||||
|
(void) pmk_ptr;
|
||||||
|
|
||||||
|
tr_error("FATAL: MD5 MBEDTLS_MD5_C not enabled");
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_client_sec_prot_finished_send(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
prot->timer_start(prot);
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_FINISHED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_client_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
|
||||||
|
sec_prot_timer_timeout_handle(prot, &data->common,
|
||||||
|
&prot->sec_cfg->prot_cfg.sec_prot_trickle_params, ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_client_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
|
{
|
||||||
|
radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot);
|
||||||
|
|
||||||
|
switch (sec_prot_state_get(&data->common)) {
|
||||||
|
case RADIUS_STATE_INIT:
|
||||||
|
tr_debug("Radius: init");
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_STATE_RESPONSE_ID);
|
||||||
|
prot->timer_start(prot);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Wait EAP response, Identity (starts RADIUS Client protocol)
|
||||||
|
case RADIUS_STATE_STATE_RESPONSE_ID:
|
||||||
|
tr_debug("Radius: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
// Set default timeout for the total maximum length of the negotiation
|
||||||
|
sec_prot_default_timeout_set(&data->common);
|
||||||
|
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_CREATE_RESP);
|
||||||
|
|
||||||
|
if (radius_client_sec_prot_init_radius_eap_tls(prot) < 0) {
|
||||||
|
tr_error("Radius: EAP-TLS init failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
radius_client_sec_prot_allocate_and_create_radius_message(prot);
|
||||||
|
|
||||||
|
// Send KMP-CREATE.indication
|
||||||
|
prot->create_ind(prot);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Wait KMP-CREATE.response
|
||||||
|
case RADIUS_STATE_CREATE_RESP:
|
||||||
|
if (sec_prot_result_ok_check(&data->common)) {
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_SEND_INITIAL_ACCESS_REQUEST);
|
||||||
|
prot->state_machine_call(prot);
|
||||||
|
} else {
|
||||||
|
// Ready to be deleted
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_FINISHED);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RADIUS_STATE_SEND_INITIAL_ACCESS_REQUEST:
|
||||||
|
tr_debug("Radius: send initial access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
if (radius_client_sec_prot_radius_msg_send(prot) < 0) {
|
||||||
|
tr_error("Radius: msg send error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start trickle timer to re-send if no response
|
||||||
|
sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params);
|
||||||
|
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_ACCESS_ACCEPT_REJECT_CHALLENGE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RADIUS_STATE_ACCESS_ACCEPT_REJECT_CHALLENGE:
|
||||||
|
|
||||||
|
// On timeout
|
||||||
|
if (sec_prot_result_timeout_check(&data->common)) {
|
||||||
|
// Do nothing for now
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_debug("Radius: received access accept/reject/challenge, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
// Send to radius EAP-TLS
|
||||||
|
data->radius_eap_tls_send(data->radius_eap_tls_prot, (void *) data->recv_eap_msg, data->recv_eap_msg_len);
|
||||||
|
data->recv_eap_msg = NULL;
|
||||||
|
data->recv_eap_msg_len = 0;
|
||||||
|
|
||||||
|
if (data->radius_code == RADIUS_ACCESS_REJECT) {
|
||||||
|
sec_prot_result_set(&data->common, SEC_RESULT_ERROR);
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_FINISH);
|
||||||
|
} else if (data->radius_code == RADIUS_ACCESS_ACCEPT) {
|
||||||
|
if (data->new_pmk_set) {
|
||||||
|
sec_prot_result_set(&data->common, SEC_RESULT_OK);
|
||||||
|
} else {
|
||||||
|
sec_prot_result_set(&data->common, SEC_RESULT_ERROR);
|
||||||
|
}
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_FINISH);
|
||||||
|
} else if (data->radius_code == RADIUS_ACCESS_CHALLENGE) {
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_SEND_ACCESS_REQUEST);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RADIUS_STATE_SEND_ACCESS_REQUEST:
|
||||||
|
|
||||||
|
// On timeout
|
||||||
|
if (sec_prot_result_timeout_check(&data->common)) {
|
||||||
|
// Do nothing for now
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_debug("Radius: send access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
radius_client_sec_prot_allocate_and_create_radius_message(prot);
|
||||||
|
|
||||||
|
if (radius_client_sec_prot_radius_msg_send(prot) < 0) {
|
||||||
|
tr_error("Radius: msg send error");
|
||||||
|
}
|
||||||
|
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_ACCESS_ACCEPT_REJECT_CHALLENGE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RADIUS_STATE_FINISH:
|
||||||
|
tr_debug("Radius: finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
|
||||||
|
|
||||||
|
if (sec_prot_result_ok_check(&data->common)) {
|
||||||
|
sec_prot_keys_pmk_write(prot->sec_keys, data->new_pmk, prot->sec_cfg->timer_cfg.pmk_lifetime);
|
||||||
|
// Supplicant PMK is now valid
|
||||||
|
sec_prot_keys_pmk_mismatch_reset(prot->sec_keys);
|
||||||
|
/* Calls KMP-FINISHED.indication with ignore results because next
|
||||||
|
protocol is triggered from radius EAP-TLS */
|
||||||
|
sec_prot_result_set(&data->common, SEC_RESULT_IGNORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// KMP-FINISHED.indication
|
||||||
|
prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys);
|
||||||
|
sec_prot_state_set(prot, &data->common, RADIUS_STATE_FINISHED);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RADIUS_STATE_FINISHED: {
|
||||||
|
uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot);
|
||||||
|
tr_debug("Radius: finished, eui-64: %s", remote_eui_64 ? trace_array(remote_eui_64, 8) : "not set");
|
||||||
|
|
||||||
|
prot->timer_stop(prot);
|
||||||
|
prot->finished(prot);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_WS */
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Arm Limited and affiliates.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RADIUS_CLIENT_SEC_PROT_H_
|
||||||
|
#define RADIUS_CLIENT_SEC_PROT_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RADIUS client security protocol
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* radius_client_sec_prot_register register RADIUS client protocol to KMP service
|
||||||
|
*
|
||||||
|
* \param service KMP service
|
||||||
|
*
|
||||||
|
* \return < 0 failure
|
||||||
|
* \return >= 0 success
|
||||||
|
*/
|
||||||
|
int8_t radius_client_sec_prot_register(kmp_service_t *service);
|
||||||
|
|
||||||
|
#endif /* RADIUS_CLIENT_SEC_PROT_H_ */
|
|
@ -34,7 +34,8 @@ typedef enum {
|
||||||
SEC_RESULT_ERR_UNSPEC = -3,
|
SEC_RESULT_ERR_UNSPEC = -3,
|
||||||
SEC_RESULT_TIMEOUT = -4,
|
SEC_RESULT_TIMEOUT = -4,
|
||||||
SEC_RESULT_ERROR = -5,
|
SEC_RESULT_ERROR = -5,
|
||||||
SEC_RESULT_CONF_ERROR = -6
|
SEC_RESULT_CONF_ERROR = -6,
|
||||||
|
SEC_RESULT_IGNORE
|
||||||
} sec_prot_result_e;
|
} sec_prot_result_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -49,7 +50,9 @@ typedef enum {
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SEC_PROT_TYPE_EAP_TLS = 0,
|
SEC_PROT_TYPE_EAP_TLS = 0,
|
||||||
SEC_PROT_TYPE_TLS
|
SEC_PROT_TYPE_RADIUS_EAP_TLS,
|
||||||
|
SEC_PROT_TYPE_TLS,
|
||||||
|
SEC_PROT_TYPE_RADIUS_CLIENT
|
||||||
} sec_prot_type_e;
|
} sec_prot_type_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -216,6 +219,15 @@ typedef void sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
|
||||||
*/
|
*/
|
||||||
typedef void sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64);
|
typedef void sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sec_prot_ip_addr_get gets IP address for security protocol
|
||||||
|
*
|
||||||
|
* \param prot protocol
|
||||||
|
* \param address IP address
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef void sec_prot_ip_addr_get(sec_prot_t *prot, uint8_t *address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sec_prot_by_type_get gets security protocol
|
* sec_prot_by_type_get gets security protocol
|
||||||
*
|
*
|
||||||
|
@ -237,6 +249,19 @@ typedef sec_prot_t *sec_prot_by_type_get(sec_prot_t *prot, uint8_t type);
|
||||||
*/
|
*/
|
||||||
typedef void sec_prot_receive_disable(sec_prot_t *prot);
|
typedef void sec_prot_receive_disable(sec_prot_t *prot);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sec_prot_receive_check check if received message is for this protocol
|
||||||
|
*
|
||||||
|
* \param prot protocol
|
||||||
|
* \param pdu pdu
|
||||||
|
* \param size pdu size
|
||||||
|
*
|
||||||
|
* \return < 0 message is not for this protocol
|
||||||
|
* \return >= 0 message is for this protocol
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef int8_t sec_prot_receive_check(sec_prot_t *prot, const void *pdu, uint16_t size);
|
||||||
|
|
||||||
typedef struct sec_prot_int_data_s sec_prot_int_data_t;
|
typedef struct sec_prot_int_data_s sec_prot_int_data_t;
|
||||||
|
|
||||||
// Security protocol data
|
// Security protocol data
|
||||||
|
@ -252,6 +277,8 @@ struct sec_prot_s {
|
||||||
|
|
||||||
sec_prot_send *send; /**< Protocol send */
|
sec_prot_send *send; /**< Protocol send */
|
||||||
sec_prot_receive *receive; /**< Protocol receive */
|
sec_prot_receive *receive; /**< Protocol receive */
|
||||||
|
sec_prot_receive *receive_peer; /**< Protocol receive from peer (used by peer protocol for send) */
|
||||||
|
|
||||||
sec_prot_tx_status_ind *tx_status_ind; /**< TX status indication */
|
sec_prot_tx_status_ind *tx_status_ind; /**< TX status indication */
|
||||||
|
|
||||||
sec_prot_delete *delete; /**< Protocol delete */
|
sec_prot_delete *delete; /**< Protocol delete */
|
||||||
|
@ -264,13 +291,16 @@ struct sec_prot_s {
|
||||||
sec_prot_timer_timeout *timer_timeout; /**< Timer timeout */
|
sec_prot_timer_timeout *timer_timeout; /**< Timer timeout */
|
||||||
|
|
||||||
sec_prot_eui64_addr_get *addr_get; /**< Gets EUI-64 addresses */
|
sec_prot_eui64_addr_get *addr_get; /**< Gets EUI-64 addresses */
|
||||||
|
sec_prot_ip_addr_get *ip_addr_get; /**< Gets IP address */
|
||||||
sec_prot_by_type_get *type_get; /**< Gets security protocol by type */
|
sec_prot_by_type_get *type_get; /**< Gets security protocol by type */
|
||||||
sec_prot_receive_disable *receive_disable; /**< Disable receiving of messages */
|
sec_prot_receive_disable *receive_disable; /**< Disable receiving of messages */
|
||||||
|
sec_prot_receive_check *receive_check; /**< Check if messages is for this protocol */
|
||||||
|
|
||||||
sec_prot_keys_t *sec_keys; /**< Security keys storage pointer */
|
sec_prot_keys_t *sec_keys; /**< Security keys storage pointer */
|
||||||
sec_prot_cfg_t *prot_cfg; /**< Security protocol configuration pointer */
|
sec_cfg_t *sec_cfg; /**< Security configuration configuration pointer */
|
||||||
sec_timer_cfg_t *timer_cfg; /**< Security timer configuration pointer */
|
|
||||||
uint8_t header_size; /**< Header size */
|
uint8_t header_size; /**< Header size */
|
||||||
|
uint8_t receive_peer_hdr_size; /**< Receive from peer header size */
|
||||||
|
uint8_t msg_if_instance_id; /**< Message interface instance identifier */
|
||||||
sec_prot_int_data_t *data; /**< Protocol internal data */
|
sec_prot_int_data_t *data; /**< Protocol internal data */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -43,4 +43,19 @@ typedef struct sec_timer_cfg_s {
|
||||||
uint8_t gtk_new_install_req; /* GTK_NEW_INSTALL_REQUIRED (percent of GTK lifetime) */
|
uint8_t gtk_new_install_req; /* GTK_NEW_INSTALL_REQUIRED (percent of GTK lifetime) */
|
||||||
} sec_timer_cfg_t;
|
} sec_timer_cfg_t;
|
||||||
|
|
||||||
|
/* Security radius configuration settings */
|
||||||
|
|
||||||
|
typedef struct sec_radius_cfg_s {
|
||||||
|
uint8_t radius_addr[16]; /**< Radius server IPv6 address */
|
||||||
|
uint8_t *radius_shared_secret; /**< Radius shared secret */
|
||||||
|
uint16_t radius_shared_secret_len; /**< Radius shared secret length */
|
||||||
|
bool radius_addr_set : 1; /**< Radius server address is set */
|
||||||
|
} sec_radius_cfg_t;
|
||||||
|
|
||||||
|
typedef struct sec_cfg_s {
|
||||||
|
sec_prot_cfg_t prot_cfg;
|
||||||
|
sec_timer_cfg_t timer_cfg;
|
||||||
|
sec_radius_cfg_t radius_cfg;
|
||||||
|
} sec_cfg_t;
|
||||||
|
|
||||||
#endif /* SEC_PROT_CONF_H_ */
|
#endif /* SEC_PROT_CONF_H_ */
|
||||||
|
|
|
@ -142,6 +142,7 @@ typedef struct {
|
||||||
sec_prot_gtk_keys_t *gtks; /**< Link to GTKs */
|
sec_prot_gtk_keys_t *gtks; /**< Link to GTKs */
|
||||||
uint16_t new_pan_id; /**< new PAN ID indicated by bootstrap */
|
uint16_t new_pan_id; /**< new PAN ID indicated by bootstrap */
|
||||||
uint16_t key_pan_id; /**< PAN ID for keys */
|
uint16_t key_pan_id; /**< PAN ID for keys */
|
||||||
|
uint16_t pan_version; /**< PAN version for keys */
|
||||||
bool updated : 1; /**< Network info has been updated */
|
bool updated : 1; /**< Network info has been updated */
|
||||||
} sec_prot_keys_nw_info_t;
|
} sec_prot_keys_nw_info_t;
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
#include "Security/protocols/sec_prot_keys.h"
|
#include "Security/protocols/sec_prot_keys.h"
|
||||||
#include "Security/protocols/sec_prot.h"
|
#include "Security/protocols/sec_prot.h"
|
||||||
#include "Security/protocols/sec_prot_lib.h"
|
#include "Security/protocols/sec_prot_lib.h"
|
||||||
|
#include "Service_Libs/hmac/hmac_md.h"
|
||||||
#include "Service_Libs/ieee_802_11/ieee_802_11.h"
|
#include "Service_Libs/ieee_802_11/ieee_802_11.h"
|
||||||
#include "Service_Libs/hmac/hmac_sha1.h"
|
|
||||||
#include "Service_Libs/nist_aes_kw/nist_aes_kw.h"
|
#include "Service_Libs/nist_aes_kw/nist_aes_kw.h"
|
||||||
#include "mbedtls/sha256.h"
|
#include "mbedtls/sha256.h"
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ int8_t sec_prot_lib_pmkid_calc(const uint8_t *pmk, const uint8_t *auth_eui64, co
|
||||||
ptr += EUI64_LEN;
|
ptr += EUI64_LEN;
|
||||||
memcpy(ptr, supp_eui64, EUI64_LEN);
|
memcpy(ptr, supp_eui64, EUI64_LEN);
|
||||||
|
|
||||||
if (hmac_sha1_calc(pmk, PMK_LEN, data, data_len, pmkid, PMKID_LEN) < 0) {
|
if (hmac_md_calc(ALG_HMAC_SHA1_160, pmk, PMK_LEN, data, data_len, pmkid, PMKID_LEN) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ int8_t sec_prot_lib_ptkid_calc(const uint8_t *ptk, const uint8_t *auth_eui64, co
|
||||||
ptr += EUI64_LEN;
|
ptr += EUI64_LEN;
|
||||||
memcpy(ptr, supp_eui64, EUI64_LEN);
|
memcpy(ptr, supp_eui64, EUI64_LEN);
|
||||||
|
|
||||||
if (hmac_sha1_calc(ptk, PTK_LEN, data, data_len, ptkid, PTKID_LEN) < 0) {
|
if (hmac_md_calc(ALG_HMAC_SHA1_160, ptk, PTK_LEN, data, data_len, ptkid, PTKID_LEN) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +351,7 @@ uint8_t *sec_prot_lib_message_build(uint8_t *ptk, uint8_t *kde, uint16_t kde_len
|
||||||
|
|
||||||
if (eapol_pdu->msg.key.key_information.key_mic) {
|
if (eapol_pdu->msg.key.key_information.key_mic) {
|
||||||
uint8_t mic[EAPOL_KEY_MIC_LEN];
|
uint8_t mic[EAPOL_KEY_MIC_LEN];
|
||||||
if (hmac_sha1_calc(ptk, KCK_LEN, eapol_pdu_frame + header_size, eapol_pdu_size, mic, EAPOL_KEY_MIC_LEN) < 0) {
|
if (hmac_md_calc(ALG_HMAC_SHA1_160, ptk, KCK_LEN, eapol_pdu_frame + header_size, eapol_pdu_size, mic, EAPOL_KEY_MIC_LEN) < 0) {
|
||||||
ns_dyn_mem_free(eapol_pdu_frame);
|
ns_dyn_mem_free(eapol_pdu_frame);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ int8_t sec_prot_lib_mic_validate(uint8_t *ptk, uint8_t *mic, uint8_t *pdu, uint8
|
||||||
eapol_write_key_packet_mic(pdu, 0);
|
eapol_write_key_packet_mic(pdu, 0);
|
||||||
|
|
||||||
uint8_t calc_mic[EAPOL_KEY_MIC_LEN];
|
uint8_t calc_mic[EAPOL_KEY_MIC_LEN];
|
||||||
if (hmac_sha1_calc(ptk, EAPOL_KEY_MIC_LEN, pdu, pdu_size, calc_mic, EAPOL_KEY_MIC_LEN) < 0) {
|
if (hmac_md_calc(ALG_HMAC_SHA1_160, ptk, EAPOL_KEY_MIC_LEN, pdu, pdu_size, calc_mic, EAPOL_KEY_MIC_LEN) < 0) {
|
||||||
tr_error("MIC invalid");
|
tr_error("MIC invalid");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -445,7 +445,7 @@ int8_t sec_prot_lib_mic_validate(uint8_t *ptk, uint8_t *mic, uint8_t *pdu, uint8
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t sec_prot_lib_pmkid_generate(sec_prot_t *prot, uint8_t *pmkid, bool is_auth)
|
int8_t sec_prot_lib_pmkid_generate(sec_prot_t *prot, uint8_t *pmkid, bool is_auth, bool alt_remote_eui64_use, uint8_t *used_remote_eui64)
|
||||||
{
|
{
|
||||||
uint8_t *pmk = sec_prot_keys_pmk_get(prot->sec_keys);
|
uint8_t *pmk = sec_prot_keys_pmk_get(prot->sec_keys);
|
||||||
if (!pmk) {
|
if (!pmk) {
|
||||||
|
@ -456,14 +456,22 @@ int8_t sec_prot_lib_pmkid_generate(sec_prot_t *prot, uint8_t *pmkid, bool is_aut
|
||||||
uint8_t remote_eui64[8];
|
uint8_t remote_eui64[8];
|
||||||
// Tries to get the EUI-64 that is validated by PTK procedure or bound to supplicant entry
|
// Tries to get the EUI-64 that is validated by PTK procedure or bound to supplicant entry
|
||||||
uint8_t *remote_eui64_ptr = sec_prot_keys_ptk_eui_64_get(prot->sec_keys);
|
uint8_t *remote_eui64_ptr = sec_prot_keys_ptk_eui_64_get(prot->sec_keys);
|
||||||
if (remote_eui64_ptr) {
|
if (remote_eui64_ptr && !alt_remote_eui64_use) {
|
||||||
memcpy(remote_eui64, remote_eui64_ptr, 8);
|
memcpy(remote_eui64, remote_eui64_ptr, 8);
|
||||||
prot->addr_get(prot, local_eui64, NULL);
|
prot->addr_get(prot, local_eui64, NULL);
|
||||||
} else {
|
} else {
|
||||||
|
// If request is for alternative EUI-64, but PTK EUI-64 is not present, returns failure
|
||||||
|
if (alt_remote_eui64_use && !remote_eui64_ptr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
// If validated EUI-64 is not present, use the remote EUI-64
|
// If validated EUI-64 is not present, use the remote EUI-64
|
||||||
prot->addr_get(prot, local_eui64, remote_eui64);
|
prot->addr_get(prot, local_eui64, remote_eui64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (used_remote_eui64 != NULL) {
|
||||||
|
memcpy(used_remote_eui64, remote_eui64, 8);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_auth) {
|
if (is_auth) {
|
||||||
return sec_prot_lib_pmkid_calc(pmk, local_eui64, remote_eui64, pmkid);
|
return sec_prot_lib_pmkid_calc(pmk, local_eui64, remote_eui64, pmkid);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -162,11 +162,13 @@ int8_t sec_prot_lib_mic_validate(uint8_t *ptk, uint8_t *mic, uint8_t *pdu, uint8
|
||||||
* \param prot security protocol
|
* \param prot security protocol
|
||||||
* \param pmkid PMK ID
|
* \param pmkid PMK ID
|
||||||
* \param is_auth set for authenticator
|
* \param is_auth set for authenticator
|
||||||
|
* \param alt_remote_eui64_use use alternative remote EUI-64 if available
|
||||||
|
* \param used_remote_eui64 remote EUI-64 used on PMKID generation
|
||||||
*
|
*
|
||||||
* \return < 0 failure
|
* \return < 0 failure
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*/
|
*/
|
||||||
int8_t sec_prot_lib_pmkid_generate(sec_prot_t *prot, uint8_t *pmkid, bool is_auth);
|
int8_t sec_prot_lib_pmkid_generate(sec_prot_t *prot, uint8_t *pmkid, bool is_auth, bool alt_remote_eui64_use, uint8_t *used_remote_eui64);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sec_prot_lib_ptkid_generate generate PTK ID from PTK
|
* sec_prot_lib_ptkid_generate generate PTK ID from PTK
|
||||||
|
|
|
@ -375,7 +375,7 @@ static void client_tls_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
data->calculating = false;
|
data->calculating = false;
|
||||||
|
|
||||||
if (sec_prot_result_ok_check(&data->common)) {
|
if (sec_prot_result_ok_check(&data->common)) {
|
||||||
sec_prot_keys_pmk_write(prot->sec_keys, data->new_pmk, prot->timer_cfg->pmk_lifetime);
|
sec_prot_keys_pmk_write(prot->sec_keys, data->new_pmk, prot->sec_cfg->timer_cfg.pmk_lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMP-FINISHED.indication,
|
// KMP-FINISHED.indication,
|
||||||
|
@ -494,7 +494,7 @@ static void server_tls_sec_prot_state_machine(sec_prot_t *prot)
|
||||||
data->calculating = false;
|
data->calculating = false;
|
||||||
|
|
||||||
if (sec_prot_result_ok_check(&data->common)) {
|
if (sec_prot_result_ok_check(&data->common)) {
|
||||||
sec_prot_keys_pmk_write(prot->sec_keys, data->new_pmk, prot->timer_cfg->pmk_lifetime);
|
sec_prot_keys_pmk_write(prot->sec_keys, data->new_pmk, prot->sec_cfg->timer_cfg.pmk_lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMP-FINISHED.indication,
|
// KMP-FINISHED.indication,
|
||||||
|
|
|
@ -83,6 +83,7 @@ static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots);
|
||||||
static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure);
|
static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure);
|
||||||
static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay);
|
static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay);
|
||||||
static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure);
|
static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure);
|
||||||
|
static int32_t fhss_channel_index_from_mask(const uint32_t *channel_mask, int32_t channel_index, uint16_t number_of_channels);
|
||||||
|
|
||||||
// This function supports rounding up
|
// This function supports rounding up
|
||||||
static int64_t divide_integer(int64_t dividend, int32_t divisor)
|
static int64_t divide_integer(int64_t dividend, int32_t divisor)
|
||||||
|
@ -235,12 +236,14 @@ static int32_t fhss_ws_calc_bc_channel(fhss_structure_t *fhss_structure)
|
||||||
|
|
||||||
if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_TR51CF) {
|
if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_TR51CF) {
|
||||||
next_channel = tr51_get_bc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels, NULL);
|
next_channel = tr51_get_bc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels, NULL);
|
||||||
|
next_channel = fhss_channel_index_from_mask(fhss_structure->ws->fhss_configuration.channel_mask, next_channel, fhss_structure->number_of_channels);
|
||||||
if (++fhss_structure->ws->bc_slot == fhss_structure->number_of_channels) {
|
if (++fhss_structure->ws->bc_slot == fhss_structure->number_of_channels) {
|
||||||
fhss_structure->ws->bc_slot = 0;
|
fhss_structure->ws->bc_slot = 0;
|
||||||
}
|
}
|
||||||
} else if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_DH1CF) {
|
} else if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_DH1CF) {
|
||||||
fhss_structure->ws->bc_slot++;
|
fhss_structure->ws->bc_slot++;
|
||||||
next_channel = dh1cf_get_bc_channel_index(fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels);
|
next_channel = dh1cf_get_bc_channel_index(fhss_structure->ws->bc_slot, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels);
|
||||||
|
next_channel = fhss_channel_index_from_mask(fhss_structure->ws->fhss_configuration.channel_mask, next_channel, fhss_structure->number_of_channels);
|
||||||
} else if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_VENDOR_DEF_CF) {
|
} else if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_VENDOR_DEF_CF) {
|
||||||
if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) {
|
if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) {
|
||||||
next_channel = fhss_structure->ws->fhss_configuration.vendor_defined_cf(fhss_structure->fhss_api, fhss_structure->ws->bc_slot, NULL, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels);
|
next_channel = fhss_structure->ws->fhss_configuration.vendor_defined_cf(fhss_structure->fhss_api, fhss_structure->ws->bc_slot, NULL, fhss_structure->ws->fhss_configuration.bsi, fhss_structure->number_of_channels);
|
||||||
|
@ -264,6 +267,22 @@ static uint8_t calc_own_tx_trig_slot(uint8_t own_hop)
|
||||||
return (own_hop & 1);
|
return (own_hop & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t fhss_channel_index_from_mask(const uint32_t *channel_mask, int32_t channel_index, uint16_t number_of_channels)
|
||||||
|
{
|
||||||
|
//Function will return real active channel index at list
|
||||||
|
int32_t active_channels = 0;
|
||||||
|
// Set channel maks outside excluded channels
|
||||||
|
for (int32_t i = 0; i < number_of_channels; i++) {
|
||||||
|
if (channel_mask[0 + (i / 32)] & (1 << (i % 32))) {
|
||||||
|
if (channel_index == active_channels) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
active_channels++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
||||||
{
|
{
|
||||||
int32_t next_channel;
|
int32_t next_channel;
|
||||||
|
@ -276,6 +295,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
||||||
// stop broadcast schedule
|
// stop broadcast schedule
|
||||||
fhss_structure->ws->is_on_bc_channel = false;
|
fhss_structure->ws->is_on_bc_channel = false;
|
||||||
fhss_structure->ws->synchronization_time = 0;
|
fhss_structure->ws->synchronization_time = 0;
|
||||||
|
fhss_structure->ws->broadcast_timer_running = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (fhss_structure->ws->is_on_bc_channel == false) {
|
if (fhss_structure->ws->is_on_bc_channel == false) {
|
||||||
|
@ -324,6 +344,9 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
||||||
#ifdef FHSS_CHANNEL_DEBUG
|
#ifdef FHSS_CHANNEL_DEBUG
|
||||||
tr_info("%"PRIu32" UC %u", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api), fhss_structure->rx_channel);
|
tr_info("%"PRIu32" UC %u", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api), fhss_structure->rx_channel);
|
||||||
#endif /*FHSS_CHANNEL_DEBUG*/
|
#endif /*FHSS_CHANNEL_DEBUG*/
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
tr_info("%u UC_change %u", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api), next_channel);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
fhss_structure->callbacks.change_channel(fhss_structure->fhss_api, next_channel);
|
fhss_structure->callbacks.change_channel(fhss_structure->fhss_api, next_channel);
|
||||||
#ifdef FHSS_CHANNEL_DEBUG_CBS
|
#ifdef FHSS_CHANNEL_DEBUG_CBS
|
||||||
|
@ -331,6 +354,13 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
|
||||||
fhss_bc_switch();
|
fhss_bc_switch();
|
||||||
}
|
}
|
||||||
#endif /*FHSS_CHANNEL_DEBUG_CBS*/
|
#endif /*FHSS_CHANNEL_DEBUG_CBS*/
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
if (fhss_structure->ws->is_on_bc_channel == true) {
|
||||||
|
tr_info("%u BC_start %u", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api), next_channel);
|
||||||
|
} else {
|
||||||
|
tr_info("%u BC_done", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int own_floor(float value)
|
static int own_floor(float value)
|
||||||
|
@ -373,6 +403,9 @@ static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots)
|
||||||
}
|
}
|
||||||
if (queue_size) {
|
if (queue_size) {
|
||||||
fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api);
|
fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api);
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
tr_info("%u TX_poll", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +417,10 @@ static uint32_t fhss_ws_calculate_ufsi(fhss_structure_t *fhss_structure, uint32_
|
||||||
cur_slot = fhss_structure->number_of_uc_channels;
|
cur_slot = fhss_structure->number_of_uc_channels;
|
||||||
}
|
}
|
||||||
cur_slot--;
|
cur_slot--;
|
||||||
uint32_t remaining_time_ms = US_TO_MS(get_remaining_slots_us(fhss_structure, fhss_unicast_handler, MS_TO_US(fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval)));
|
uint32_t remaining_time_ms = 0;
|
||||||
|
if (fhss_structure->ws->unicast_timer_running == true) {
|
||||||
|
remaining_time_ms = US_TO_MS(get_remaining_slots_us(fhss_structure, fhss_unicast_handler, MS_TO_US(dwell_time) - NS_TO_US(dwell_time * fhss_structure->ws->drift_per_millisecond_ns)));
|
||||||
|
}
|
||||||
uint32_t time_to_tx = 0;
|
uint32_t time_to_tx = 0;
|
||||||
uint32_t cur_time = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api);
|
uint32_t cur_time = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api);
|
||||||
if (cur_time < tx_time) {
|
if (cur_time < tx_time) {
|
||||||
|
@ -447,6 +483,7 @@ static int16_t fhss_ws_synch_state_set_callback(const fhss_api_t *api, fhss_stat
|
||||||
// Start broadcast schedule when BC intervals are known
|
// Start broadcast schedule when BC intervals are known
|
||||||
if (fhss_broadcast_interval && fhss_bc_dwell_interval) {
|
if (fhss_broadcast_interval && fhss_bc_dwell_interval) {
|
||||||
fhss_broadcast_handler(fhss_structure->fhss_api, 0);
|
fhss_broadcast_handler(fhss_structure->fhss_api, 0);
|
||||||
|
fhss_structure->ws->broadcast_timer_running = true;
|
||||||
}
|
}
|
||||||
// Start unicast schedule
|
// Start unicast schedule
|
||||||
if ((fhss_structure->ws->fhss_configuration.ws_uc_channel_function != WS_FIXED_CHANNEL)) {
|
if ((fhss_structure->ws->fhss_configuration.ws_uc_channel_function != WS_FIXED_CHANNEL)) {
|
||||||
|
@ -459,6 +496,7 @@ static int16_t fhss_ws_synch_state_set_callback(const fhss_api_t *api, fhss_stat
|
||||||
eventOS_callback_timer_stop(fhss_structure->fhss_event_timer);
|
eventOS_callback_timer_stop(fhss_structure->fhss_event_timer);
|
||||||
fhss_stop_timer(fhss_structure, fhss_unicast_handler);
|
fhss_stop_timer(fhss_structure, fhss_unicast_handler);
|
||||||
fhss_stop_timer(fhss_structure, fhss_broadcast_handler);
|
fhss_stop_timer(fhss_structure, fhss_broadcast_handler);
|
||||||
|
fhss_structure->ws->broadcast_timer_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fhss_structure->fhss_state = fhss_state;
|
fhss_structure->fhss_state = fhss_state;
|
||||||
|
@ -477,12 +515,14 @@ static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure)
|
||||||
if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_FIXED_CHANNEL) {
|
if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_FIXED_CHANNEL) {
|
||||||
return;
|
return;
|
||||||
} else if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_TR51CF) {
|
} else if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_TR51CF) {
|
||||||
next_channel = fhss_structure->rx_channel = tr51_get_uc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, fhss_structure->ws->uc_slot, mac_address, fhss_structure->number_of_uc_channels, NULL);
|
next_channel = tr51_get_uc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, fhss_structure->ws->uc_slot, mac_address, fhss_structure->number_of_uc_channels, NULL);
|
||||||
|
next_channel = fhss_structure->rx_channel = fhss_channel_index_from_mask(fhss_structure->ws->fhss_configuration.unicast_channel_mask, next_channel, fhss_structure->number_of_channels);
|
||||||
if (++fhss_structure->ws->uc_slot == fhss_structure->number_of_uc_channels) {
|
if (++fhss_structure->ws->uc_slot == fhss_structure->number_of_uc_channels) {
|
||||||
fhss_structure->ws->uc_slot = 0;
|
fhss_structure->ws->uc_slot = 0;
|
||||||
}
|
}
|
||||||
} else if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_DH1CF) {
|
} else if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_DH1CF) {
|
||||||
next_channel = fhss_structure->rx_channel = dh1cf_get_uc_channel_index(fhss_structure->ws->uc_slot, mac_address, fhss_structure->number_of_uc_channels);
|
next_channel = dh1cf_get_uc_channel_index(fhss_structure->ws->uc_slot, mac_address, fhss_structure->number_of_uc_channels);
|
||||||
|
next_channel = fhss_structure->rx_channel = fhss_channel_index_from_mask(fhss_structure->ws->fhss_configuration.unicast_channel_mask, next_channel, fhss_structure->number_of_channels);
|
||||||
fhss_structure->ws->uc_slot++;
|
fhss_structure->ws->uc_slot++;
|
||||||
} else if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_VENDOR_DEF_CF) {
|
} else if (fhss_structure->ws->fhss_configuration.ws_uc_channel_function == WS_VENDOR_DEF_CF) {
|
||||||
if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) {
|
if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) {
|
||||||
|
@ -496,6 +536,9 @@ static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure)
|
||||||
#ifdef FHSS_CHANNEL_DEBUG
|
#ifdef FHSS_CHANNEL_DEBUG
|
||||||
tr_info("%"PRIu32" UC %u %u", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api), next_channel, fhss_structure->ws->uc_slot);
|
tr_info("%"PRIu32" UC %u %u", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api), next_channel, fhss_structure->ws->uc_slot);
|
||||||
#endif /*FHSS_CHANNEL_DEBUG*/
|
#endif /*FHSS_CHANNEL_DEBUG*/
|
||||||
|
#ifdef TIMING_TOOL_TRACES
|
||||||
|
tr_info("%u UC_change %u", fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api), next_channel);
|
||||||
|
#endif
|
||||||
fhss_structure->callbacks.change_channel(fhss_structure->fhss_api, next_channel);
|
fhss_structure->callbacks.change_channel(fhss_structure->fhss_api, next_channel);
|
||||||
#ifdef FHSS_CHANNEL_DEBUG_CBS
|
#ifdef FHSS_CHANNEL_DEBUG_CBS
|
||||||
if (fhss_uc_switch) {
|
if (fhss_uc_switch) {
|
||||||
|
@ -540,8 +583,10 @@ static int fhss_ws_tx_handle_callback(const fhss_api_t *api, bool is_broadcast_a
|
||||||
int32_t tx_channel = neighbor_timing_info->uc_timing_info.fixed_channel;
|
int32_t tx_channel = neighbor_timing_info->uc_timing_info.fixed_channel;
|
||||||
if (neighbor_timing_info->uc_timing_info.unicast_channel_function == WS_TR51CF) {
|
if (neighbor_timing_info->uc_timing_info.unicast_channel_function == WS_TR51CF) {
|
||||||
tx_channel = tr51_get_uc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, destination_slot, destination_address, neighbor_timing_info->uc_timing_info.unicast_number_of_channels, NULL);
|
tx_channel = tr51_get_uc_channel_index(fhss_structure->ws->tr51_channel_table, fhss_structure->ws->tr51_output_table, destination_slot, destination_address, neighbor_timing_info->uc_timing_info.unicast_number_of_channels, NULL);
|
||||||
|
tx_channel = fhss_channel_index_from_mask(neighbor_timing_info->uc_channel_list.channel_mask, tx_channel, fhss_structure->number_of_channels);
|
||||||
} else if (neighbor_timing_info->uc_timing_info.unicast_channel_function == WS_DH1CF) {
|
} else if (neighbor_timing_info->uc_timing_info.unicast_channel_function == WS_DH1CF) {
|
||||||
tx_channel = dh1cf_get_uc_channel_index(destination_slot, destination_address, neighbor_timing_info->uc_channel_list.channel_count);
|
tx_channel = dh1cf_get_uc_channel_index(destination_slot, destination_address, neighbor_timing_info->uc_channel_list.channel_count);
|
||||||
|
tx_channel = fhss_channel_index_from_mask(neighbor_timing_info->uc_channel_list.channel_mask, tx_channel, fhss_structure->number_of_channels);
|
||||||
} else if (neighbor_timing_info->uc_timing_info.unicast_channel_function == WS_VENDOR_DEF_CF) {
|
} else if (neighbor_timing_info->uc_timing_info.unicast_channel_function == WS_VENDOR_DEF_CF) {
|
||||||
if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) {
|
if (fhss_structure->ws->fhss_configuration.vendor_defined_cf) {
|
||||||
tx_channel = fhss_structure->ws->fhss_configuration.vendor_defined_cf(fhss_structure->fhss_api, fhss_structure->ws->bc_slot, destination_address, fhss_structure->ws->fhss_configuration.bsi, neighbor_timing_info->uc_timing_info.unicast_number_of_channels);
|
tx_channel = fhss_structure->ws->fhss_configuration.vendor_defined_cf(fhss_structure->fhss_api, fhss_structure->ws->bc_slot, destination_address, fhss_structure->ws->fhss_configuration.bsi, neighbor_timing_info->uc_timing_info.unicast_number_of_channels);
|
||||||
|
@ -814,8 +859,13 @@ static uint32_t fhss_ws_get_retry_period_callback(const fhss_api_t *api, uint8_t
|
||||||
if (!fhss_structure) {
|
if (!fhss_structure) {
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
// We don't know the broadcast schedule, use large backoff with MAC retries
|
||||||
|
if (fhss_structure->ws->broadcast_timer_running == false) {
|
||||||
|
return 100000;
|
||||||
|
}
|
||||||
|
// We don't know the TX/RX slots, use randomised large backoff with MAC retries
|
||||||
if (fhss_structure->own_hop == 0xff) {
|
if (fhss_structure->own_hop == 0xff) {
|
||||||
return return_value;
|
return ((uint32_t) randLIB_get_random_in_range(50, 150) * 1000);
|
||||||
}
|
}
|
||||||
if (fhss_structure->ws->is_on_bc_channel == true) {
|
if (fhss_structure->ws->is_on_bc_channel == true) {
|
||||||
return return_value;
|
return return_value;
|
||||||
|
@ -916,6 +966,7 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
|
||||||
timeout -= MS_TO_US(bc_timing_info->broadcast_interval - bc_timing_info->broadcast_dwell_interval);
|
timeout -= MS_TO_US(bc_timing_info->broadcast_interval - bc_timing_info->broadcast_dwell_interval);
|
||||||
}
|
}
|
||||||
fhss_ws_start_timer(fhss_structure, timeout, fhss_broadcast_handler);
|
fhss_ws_start_timer(fhss_structure, timeout, fhss_broadcast_handler);
|
||||||
|
fhss_structure->ws->broadcast_timer_running = true;
|
||||||
uint16_t slots_since_reception = (bc_timing_info->broadcast_interval_offset + time_from_reception_ms) / bc_timing_info->broadcast_interval;
|
uint16_t slots_since_reception = (bc_timing_info->broadcast_interval_offset + time_from_reception_ms) / bc_timing_info->broadcast_interval;
|
||||||
// TODO: Calculate drift error
|
// TODO: Calculate drift error
|
||||||
fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval = bc_timing_info->broadcast_dwell_interval;
|
fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval = bc_timing_info->broadcast_dwell_interval;
|
||||||
|
|
|
@ -41,6 +41,7 @@ struct fhss_ws {
|
||||||
int16_t *tr51_channel_table;
|
int16_t *tr51_channel_table;
|
||||||
uint8_t *tr51_output_table;
|
uint8_t *tr51_output_table;
|
||||||
bool unicast_timer_running;
|
bool unicast_timer_running;
|
||||||
|
bool broadcast_timer_running;
|
||||||
bool is_on_bc_channel;
|
bool is_on_bc_channel;
|
||||||
struct fhss_ws_configuration fhss_configuration;
|
struct fhss_ws_configuration fhss_configuration;
|
||||||
const struct broadcast_timing_info *parent_bc_info;
|
const struct broadcast_timing_info *parent_bc_info;
|
||||||
|
|
|
@ -21,20 +21,20 @@
|
||||||
#include "ns_list.h"
|
#include "ns_list.h"
|
||||||
#include "ns_trace.h"
|
#include "ns_trace.h"
|
||||||
#include "mbedtls/md.h"
|
#include "mbedtls/md.h"
|
||||||
#include "Service_Libs/hmac/hmac_sha1.h"
|
#include "hmac_md.h"
|
||||||
|
|
||||||
#define TRACE_GROUP "hmac"
|
#define TRACE_GROUP "hmac"
|
||||||
|
|
||||||
int8_t hmac_sha1_calc(const uint8_t *key, uint16_t key_len, const uint8_t *data, uint16_t data_len, uint8_t *result, uint8_t result_len)
|
int8_t hmac_md_calc(const alg_hmac_md_e md, const uint8_t *key, uint16_t key_len, const uint8_t *data, uint16_t data_len, uint8_t *result, uint8_t result_len)
|
||||||
{
|
{
|
||||||
#ifdef EXTRA_DEBUG_INFO
|
#ifdef EXTRA_DEBUG_INFO
|
||||||
// Extensive debug for now, to be disabled later
|
// Extensive debug for now, to be disabled later
|
||||||
tr_debug("hmac_sha_1 key %s\n", trace_array(key, key_len));
|
tr_debug("hmac_md key %s\n", trace_array(key, key_len));
|
||||||
|
|
||||||
const uint8_t *print_data = data;
|
const uint8_t *print_data = data;
|
||||||
uint16_t print_data_len = data_len;
|
uint16_t print_data_len = data_len;
|
||||||
while (true) {
|
while (true) {
|
||||||
tr_debug("hmac_sha_1 data %s\n", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
|
tr_debug("hmac_md data %s\n", trace_array(print_data, print_data_len > 32 ? 32 : print_data_len));
|
||||||
if (print_data_len > 32) {
|
if (print_data_len > 32) {
|
||||||
print_data_len -= 32;
|
print_data_len -= 32;
|
||||||
print_data += 32;
|
print_data += 32;
|
||||||
|
@ -44,7 +44,12 @@ int8_t hmac_sha1_calc(const uint8_t *key, uint16_t key_len, const uint8_t *data,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
|
mbedtls_md_type_t md_type;
|
||||||
|
if (md == ALG_HMAC_MD5) {
|
||||||
|
md_type = MBEDTLS_MD_MD5;
|
||||||
|
} else {
|
||||||
|
md_type = MBEDTLS_MD_SHA1;
|
||||||
|
}
|
||||||
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
|
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
|
||||||
if (md_info == NULL) {
|
if (md_info == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -76,7 +81,7 @@ int8_t hmac_sha1_calc(const uint8_t *key, uint16_t key_len, const uint8_t *data,
|
||||||
memcpy(result, result_value, result_len);
|
memcpy(result, result_value, result_len);
|
||||||
|
|
||||||
#ifdef EXTRA_DEBUG_INFO
|
#ifdef EXTRA_DEBUG_INFO
|
||||||
tr_debug("hmac_sha_1 result %s\n", trace_array(result_value, 20));
|
tr_debug("hmac_md result %s\n", trace_array(result_value, 20));
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -18,11 +18,17 @@
|
||||||
#ifndef HMAC_SHA1_
|
#ifndef HMAC_SHA1_
|
||||||
#define HMAC_SHA1_
|
#define HMAC_SHA1_
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ALG_HMAC_MD5,
|
||||||
|
ALG_HMAC_SHA1_160
|
||||||
|
} alg_hmac_md_e;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Calculate HMAC-SHA1-160
|
* \brief Calculate HMAC-SHA1-160 or HMAC-MD5
|
||||||
*
|
*
|
||||||
* Calculate HMAC-SHA1-160
|
* Calculate HMAC-SHA1-160 or HMAC-MD5
|
||||||
*
|
*
|
||||||
|
* \param md message digest algorithm
|
||||||
* \param key pointer to key
|
* \param key pointer to key
|
||||||
* \param key_len key length
|
* \param key_len key length
|
||||||
* \param data pointer to data
|
* \param data pointer to data
|
||||||
|
@ -34,6 +40,6 @@
|
||||||
* \return >= 0 success
|
* \return >= 0 success
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int8_t hmac_sha1_calc(const uint8_t *key, uint16_t key_len, const uint8_t *data, uint16_t data_len, uint8_t *result, uint8_t result_len);
|
int8_t hmac_md_calc(const alg_hmac_md_e md, const uint8_t *key, uint16_t key_len, const uint8_t *data, uint16_t data_len, uint8_t *result, uint8_t result_len);
|
||||||
|
|
||||||
#endif /* HMAC_SHA1_ */
|
#endif /* HMAC_SHA1_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue