Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 58 additions & 2 deletions features/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class WisunBorderRouter {
/** Create WisunBorderRouter
*
* */
WisunBorderRouter() { }
WisunBorderRouter();

/**
* \brief Start Wi-SUN Border Router
Expand Down Expand Up @@ -209,9 +209,65 @@ class WisunBorderRouter {
* */
int routing_table_get(ws_br_route_info_t *table_ptr, uint16_t table_len);

/**
* \brief Set Wi-SUN 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 address set to NULL. The RADIUS shared secret must be set before address
* is set using set_radius_shared_secret() call.
*
* \param address Pointer to IPv6 address string or NULL to disable RADIUS. Address string format is e.g. 2001:1234::1 and it is NUL terminated.
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_UNKNOWN in case of failure.
* */
mesh_error_t set_radius_server_ipv6_address(const char *address);

/**
* \brief Get Wi-SUN RADIUS server IPv6 address.
*
* Function gets external RADIUS server IPv6 address from Border Router.
*
* \param address Pointer to buffer where to write IPv6 address string. Must have space at least for 39 characters and NUL terminator.
* \return MESH_ERROR_NONE on success.
* \return error value in case of failure, e.g. if address has not been set to Border Router.
* */
mesh_error_t get_radius_server_ipv6_address(char *address);

/**
* \brief Set Wi-SUN 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 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 MESH_ERROR_NONE on success.
* \return error value in case of failure.
* */
mesh_error_t set_radius_shared_secret(uint16_t shared_secret_len, const uint8_t *shared_secret);

/**
* \brief Get Wi-SUN RADIUS shared secret.
*
* Function gets RADIUS shared secret from Border Router.
*
* \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 MESH_ERROR_NONE on success.
* \return error value in case of failure.
* */
mesh_error_t get_radius_shared_secret(uint16_t *shared_secret_len, uint8_t *shared_secret);

private:
mesh_error_t configure();
mesh_error_t apply_configuration(int8_t mesh_if_id);
mesh_error_t set_bbr_radius_address(void);
char _radius_ipv6_addr[40];
int8_t _mesh_if_id = -1;

bool _radius_ipv6_addr_set = false;
bool _configured = false;
};

#endif
12 changes: 12 additions & 0 deletions features/nanostack/mbed-mesh-api/mbed_lib.json
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,18 @@
"own-certificate-key-len": {
"help": "Own certificate's key length; optional for PEM format, must be defined for DER format",
"value": null
},
"radius-server-ipv6-address": {
"help": "RADIUS Server IPv6 address in string format (e.g. \"2001:1234::1\")",
"value": null
},
"radius-shared-secret": {
"help": "RADIUS shared secret; ASCII string (e.g. \"radiuspassword\") or sequence of bytes (e.g. 0x01, 0x02, 0x03, 0x04, 0x05)",
"value": null
},
"radius-shared-secret-len": {
"help": "RADIUS shared secret length; If length is not defined, strlen() is used to determine RADIUS shared secret length",
"value": null
}
},
"target_overrides": {
Expand Down
136 changes: 136 additions & 0 deletions features/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,21 @@
#include "WisunBorderRouter.h"
#include "MeshInterfaceNanostack.h"
#include "net_interface.h"
#include "ip6string.h"

extern "C" {
#include "ws_bbr_api.h"
}

#define TRACE_GROUP "WSBR"


WisunBorderRouter::WisunBorderRouter()
{
// Apply mbed configuration to Wi-SUN BBR
configure();
}

mesh_error_t WisunBorderRouter::start(NetworkInterface *mesh_if, NetworkInterface *backbone_if)
{
if (mesh_if == NULL || backbone_if == NULL) {
Expand Down Expand Up @@ -53,6 +61,8 @@ mesh_error_t WisunBorderRouter::start(NetworkInterface *mesh_if, NetworkInterfac
return MESH_ERROR_UNKNOWN;
}

apply_configuration(mesh_if_id);

int ret = ws_bbr_start(mesh_if_id, backbone_if_id);
if (ret < 0) {
return MESH_ERROR_UNKNOWN;
Expand All @@ -76,6 +86,8 @@ mesh_error_t WisunBorderRouter::start(NetworkInterface *mesh_if, OnboardNetworkS
return MESH_ERROR_UNKNOWN;
}

apply_configuration(mesh_if_id);

int ret = ws_bbr_start(mesh_if_id, backbone_if_id);
if (ret < 0) {
return MESH_ERROR_UNKNOWN;
Expand All @@ -95,6 +107,55 @@ void WisunBorderRouter::stop()
_mesh_if_id = -1;
}

mesh_error_t WisunBorderRouter::configure()
{
#if defined(MBED_CONF_MBED_MESH_API_RADIUS_SHARED_SECRET) || defined(MBED_CONF_MBED_MESH_API_RADIUS_SERVER_IPV6_ADDRESS)
mesh_error_t status;
#endif

if (_configured) {
// Already configured
return MESH_ERROR_NONE;
}

_configured = true;

#ifdef MBED_CONF_MBED_MESH_API_RADIUS_SHARED_SECRET
const char radius_shared_secret[] = {MBED_CONF_MBED_MESH_API_RADIUS_SHARED_SECRET};
#ifdef MBED_CONF_MBED_MESH_API_RADIUS_SHARED_SECRET_LEN
const uint16_t radius_shared_secret_len = MBED_CONF_MBED_MESH_API_RADIUS_SHARED_SECRET_LEN;
#else
uint16_t radius_shared_secret_len = strlen(radius_shared_secret);
#endif
status = set_radius_shared_secret(radius_shared_secret_len, (uint8_t *) radius_shared_secret);
if (status != MESH_ERROR_NONE) {
tr_error("Failed to set RADIUS shared secret!");
return status;
}
#endif

#ifdef MBED_CONF_MBED_MESH_API_RADIUS_SERVER_IPV6_ADDRESS
const char radius_server_ipv6_addr[] = {MBED_CONF_MBED_MESH_API_RADIUS_SERVER_IPV6_ADDRESS};
status = set_radius_server_ipv6_address(radius_server_ipv6_addr);
if (status != MESH_ERROR_NONE) {
tr_error("Failed to set RADIUS server IPv6 address!");
return status;
}
#endif

return MESH_ERROR_NONE;
}

mesh_error_t WisunBorderRouter::apply_configuration(int8_t mesh_if_id)
{
mesh_error_t status = set_bbr_radius_address();
if (status != MESH_ERROR_NONE) {
tr_error("Failed to apply RADIUS server IPv6 address!");
return MESH_ERROR_PARAM;
}
return MESH_ERROR_NONE;
}

mesh_error_t WisunBorderRouter::set_rpl_parameters(uint8_t dio_interval_min, uint8_t dio_interval_doublings, uint8_t dio_redundancy_constant)
{
int status = ws_bbr_rpl_parameters_set(_mesh_if_id, dio_interval_min, dio_interval_doublings, dio_redundancy_constant);
Expand Down Expand Up @@ -188,3 +249,78 @@ int WisunBorderRouter::routing_table_get(ws_br_route_info_t *table_ptr, uint16_t

return ws_bbr_routing_table_get(_mesh_if_id, (bbr_route_info_t *)table_ptr, table_len);
}

mesh_error_t WisunBorderRouter::set_radius_server_ipv6_address(const char *address)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the GET interfaces for these

Could this be combined in the higher level api to have radius_configure(address,password)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I can add the get interface. There are no defaults for these, so the application must always program these first, but it might be easier for application, if the values could also be read from Nanostack.

I would prefer having the two functions for this since either one can be changed individually.

Copy link
Author

@mikaleppanen mikaleppanen Aug 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added get interfaces. Added storing of IP address and shared secret to border router class. Changed configuration to two phases, on class init the .json configuration is applied (if set) and then on BBR start the BBR is configured with the address and shared secret using the then defined (mesh) interface id.

{
if (address) {
uint8_t ipv6_addr[16];
if (!stoip6(address, strlen(address), ipv6_addr)) {
return MESH_ERROR_PARAM;
}
// Stored address (returned by get) is in the format given by user of the interface
strcpy(_radius_ipv6_addr, address);
_radius_ipv6_addr_set = true;
} else {
_radius_ipv6_addr_set = false;
}

return set_bbr_radius_address();
}

mesh_error_t WisunBorderRouter::get_radius_server_ipv6_address(char *address)
{
if (!_radius_ipv6_addr_set) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You would not need these booleans if you would always read these variables from the Mbed json in the begining?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RADIUS configuration could be unspecified in the .json (use internal TLS) and then later enabled by configuration function calls.

return MESH_ERROR_UNKNOWN;
}
strcpy(address, _radius_ipv6_addr);

return MESH_ERROR_NONE;
}

mesh_error_t WisunBorderRouter::set_bbr_radius_address(void)
{
int status;

if (_radius_ipv6_addr_set) {
uint8_t ipv6_addr[16];
if (!stoip6(_radius_ipv6_addr, strlen(_radius_ipv6_addr), ipv6_addr)) {
return MESH_ERROR_PARAM;
}
status = ws_bbr_radius_address_set(_mesh_if_id, ipv6_addr);
} else {
status = ws_bbr_radius_address_set(_mesh_if_id, NULL);
}
if (status != 0) {
return MESH_ERROR_UNKNOWN;
}

return MESH_ERROR_NONE;
}

mesh_error_t WisunBorderRouter::set_radius_shared_secret(uint16_t shared_secret_len, const uint8_t *shared_secret)
{
if (shared_secret_len == 0 || !shared_secret) {
return MESH_ERROR_PARAM;
}

int status = ws_bbr_radius_shared_secret_set(_mesh_if_id, shared_secret_len, shared_secret);
if (status != 0) {
return MESH_ERROR_UNKNOWN;
}

return MESH_ERROR_NONE;
}

mesh_error_t WisunBorderRouter::get_radius_shared_secret(uint16_t *shared_secret_len, uint8_t *shared_secret)
{
if (shared_secret_len == NULL) {
return MESH_ERROR_PARAM;
}

int status = ws_bbr_radius_shared_secret_get(_mesh_if_id, shared_secret_len, shared_secret);
if (status != 0) {
return MESH_ERROR_UNKNOWN;
}

return MESH_ERROR_NONE;
}
12 changes: 6 additions & 6 deletions features/nanostack/mbed-mesh-api/source/WisunInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ nsapi_error_t WisunInterface::do_initialize()

nsapi_error_t WisunInterface::configure()
{
int status;
mesh_error_t status;

if (_configured) {
// Already configured
Expand All @@ -82,7 +82,7 @@ nsapi_error_t WisunInterface::configure()
#ifdef MBED_CONF_MBED_MESH_API_WISUN_NETWORK_NAME
char network_name[] = {MBED_CONF_MBED_MESH_API_WISUN_NETWORK_NAME};
status = set_network_name((char *) &network_name);
if (status < 0) {
if (status != MESH_ERROR_NONE) {
tr_error("Failed to set network name!");
return NSAPI_ERROR_PARAMETER;
}
Expand All @@ -92,7 +92,7 @@ nsapi_error_t WisunInterface::configure()
status = set_network_regulatory_domain(MBED_CONF_MBED_MESH_API_WISUN_REGULATORY_DOMAIN,
MBED_CONF_MBED_MESH_API_WISUN_OPERATING_CLASS,
MBED_CONF_MBED_MESH_API_WISUN_OPERATING_MODE);
if (status < 0) {
if (status != MESH_ERROR_NONE) {
tr_error("Failed to set regulatory domain!");
return NSAPI_ERROR_PARAMETER;
}
Expand All @@ -102,7 +102,7 @@ nsapi_error_t WisunInterface::configure()
status = set_unicast_channel_function(static_cast<mesh_channel_function_t>(MBED_CONF_MBED_MESH_API_WISUN_UC_CHANNEL_FUNCTION),
MBED_CONF_MBED_MESH_API_WISUN_UC_FIXED_CHANNEL,
MBED_CONF_MBED_MESH_API_WISUN_UC_DWELL_INTERVAL);
if (status < 0) {
if (status != MESH_ERROR_NONE) {
tr_error("Failed to set unicast channel function configuration");
return NSAPI_ERROR_PARAMETER;
}
Expand All @@ -113,15 +113,15 @@ nsapi_error_t WisunInterface::configure()
MBED_CONF_MBED_MESH_API_WISUN_BC_FIXED_CHANNEL,
MBED_CONF_MBED_MESH_API_WISUN_BC_DWELL_INTERVAL,
MBED_CONF_MBED_MESH_API_WISUN_BC_INTERVAL);
if (status < 0) {
if (status != MESH_ERROR_NONE) {
tr_error("Failed to set broadcast channel function configuration");
return NSAPI_ERROR_PARAMETER;
}
#endif

#ifdef MBED_CONF_MBED_MESH_API_WISUN_NETWORK_SIZE
status = set_network_size(MBED_CONF_MBED_MESH_API_WISUN_NETWORK_SIZE);
if (status < 0) {
if (status != MESH_ERROR_NONE) {
tr_error("Failed to set network size");
return NSAPI_ERROR_PARAMETER;
}
Expand Down