mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-18 05:42:49 +00:00
mesh: support advertising with node identity on all subnets
This commit is contained in:
parent
89b2d435cd
commit
047f254657
@ -173,9 +173,13 @@ typedef struct {
|
|||||||
// advertisement using node id active
|
// advertisement using node id active
|
||||||
uint8_t node_id_advertisement_running;
|
uint8_t node_id_advertisement_running;
|
||||||
|
|
||||||
|
|
||||||
// advertisement using network id (used by proxy)
|
// advertisement using network id (used by proxy)
|
||||||
adv_bearer_connectable_advertisement_data_item_t advertisement_with_network_id;
|
adv_bearer_connectable_advertisement_data_item_t advertisement_with_network_id;
|
||||||
|
|
||||||
|
// advertising using node id (used by proxy)
|
||||||
|
adv_bearer_connectable_advertisement_data_item_t advertisement_with_node_id;
|
||||||
|
|
||||||
// secure network beacons
|
// secure network beacons
|
||||||
mesh_secure_network_beacon_state_t beacon_state;
|
mesh_secure_network_beacon_state_t beacon_state;
|
||||||
uint32_t beacon_interval_ms;
|
uint32_t beacon_interval_ms;
|
||||||
|
@ -60,6 +60,9 @@
|
|||||||
#include "mesh/mesh_network.h"
|
#include "mesh/mesh_network.h"
|
||||||
#include "mesh/mesh_node.h"
|
#include "mesh/mesh_node.h"
|
||||||
|
|
||||||
|
static void mesh_proxy_start_advertising_with_node_id_next_subnet(void);
|
||||||
|
static void mesh_proxy_start_advertising_with_node_id_for_subnet(mesh_subnet_t * mesh_subnet);
|
||||||
|
|
||||||
#ifdef ENABLE_MESH_PROXY_SERVER
|
#ifdef ENABLE_MESH_PROXY_SERVER
|
||||||
|
|
||||||
// we only support a single active node id advertisement. when new one is started, an active one is stopped
|
// we only support a single active node id advertisement. when new one is started, an active one is stopped
|
||||||
@ -72,13 +75,14 @@ static btstack_crypto_aes128_t mesh_proxy_node_id_crypt
|
|||||||
static uint8_t mesh_proxy_node_id_plaintext[16];
|
static uint8_t mesh_proxy_node_id_plaintext[16];
|
||||||
static uint8_t mesh_proxy_node_id_hash[16];
|
static uint8_t mesh_proxy_node_id_hash[16];
|
||||||
static uint8_t mesh_proxy_node_id_random_value[8];
|
static uint8_t mesh_proxy_node_id_random_value[8];
|
||||||
|
static uint8_t mesh_proxy_node_id_all_subnets;
|
||||||
|
|
||||||
static uint16_t primary_element_address;
|
static uint16_t primary_element_address;
|
||||||
|
|
||||||
// Mesh Proxy, advertise with node id
|
// Mesh Proxy, advertise unprovisioned device
|
||||||
static adv_bearer_connectable_advertisement_data_item_t connectable_advertisement;
|
static adv_bearer_connectable_advertisement_data_item_t connectable_advertisement_unprovisioned_device;
|
||||||
|
|
||||||
static const uint8_t adv_data_with_node_identity_template[] = {
|
static const uint8_t adv_data_with_node_id_template[] = {
|
||||||
// Flags general discoverable, BR/EDR not supported
|
// Flags general discoverable, BR/EDR not supported
|
||||||
0x02, BLUETOOTH_DATA_TYPE_FLAGS, 0x06,
|
0x02, BLUETOOTH_DATA_TYPE_FLAGS, 0x06,
|
||||||
// 16-bit Service UUIDs
|
// 16-bit Service UUIDs
|
||||||
@ -129,9 +133,9 @@ static void mesh_proxy_setup_advertising_unprovisioned(adv_bearer_connectable_ad
|
|||||||
|
|
||||||
void mesh_proxy_start_advertising_unprovisioned_device(void){
|
void mesh_proxy_start_advertising_unprovisioned_device(void){
|
||||||
const uint8_t * device_uuid = mesh_node_get_device_uuid();
|
const uint8_t * device_uuid = mesh_node_get_device_uuid();
|
||||||
mesh_proxy_setup_advertising_unprovisioned(&connectable_advertisement, device_uuid);
|
mesh_proxy_setup_advertising_unprovisioned(&connectable_advertisement_unprovisioned_device, device_uuid);
|
||||||
// setup advertisements
|
// setup advertisements
|
||||||
adv_bearer_advertisements_add_item(&connectable_advertisement);
|
adv_bearer_advertisements_add_item(&connectable_advertisement_unprovisioned_device);
|
||||||
adv_bearer_advertisements_enable(1);
|
adv_bearer_advertisements_enable(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +144,7 @@ void mesh_proxy_start_advertising_unprovisioned_device(void){
|
|||||||
* @param device_uuid
|
* @param device_uuid
|
||||||
*/
|
*/
|
||||||
void mesh_proxy_stop_advertising_unprovisioned_device(void){
|
void mesh_proxy_stop_advertising_unprovisioned_device(void){
|
||||||
adv_bearer_advertisements_remove_item(&connectable_advertisement);
|
adv_bearer_advertisements_remove_item(&connectable_advertisement_unprovisioned_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -151,17 +155,22 @@ static uint8_t mesh_proxy_setup_advertising_with_network_id(uint8_t * buffer, ui
|
|||||||
return 20;
|
return 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mesh_proxy_stop_advertising_with_node_id_for_subnet(mesh_subnet_t * mesh_subnet){
|
||||||
|
if (mesh_subnet->node_id_advertisement_running != 0){
|
||||||
|
adv_bearer_advertisements_remove_item(&mesh_subnet->advertisement_with_node_id);
|
||||||
|
mesh_subnet->node_id_advertisement_running = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void mesh_proxy_stop_all_advertising_with_node_id(void){
|
static void mesh_proxy_stop_all_advertising_with_node_id(void){
|
||||||
adv_bearer_advertisements_remove_item(&connectable_advertisement);
|
|
||||||
mesh_subnet_iterator_t it;
|
mesh_subnet_iterator_t it;
|
||||||
mesh_subnet_iterator_init(&it);
|
mesh_subnet_iterator_init(&it);
|
||||||
while (mesh_subnet_iterator_has_more(&it)){
|
while (mesh_subnet_iterator_has_more(&it)){
|
||||||
mesh_subnet_t * network_key = mesh_subnet_iterator_get_next(&it);
|
mesh_subnet_t * mesh_subnet = mesh_subnet_iterator_get_next(&it);
|
||||||
if (network_key->node_id_advertisement_running != 0){
|
mesh_proxy_stop_advertising_with_node_id_for_subnet(mesh_subnet);
|
||||||
|
}
|
||||||
btstack_run_loop_remove_timer(&mesh_proxy_node_id_timer);
|
btstack_run_loop_remove_timer(&mesh_proxy_node_id_timer);
|
||||||
network_key->node_id_advertisement_running = 0;
|
mesh_proxy_node_id_all_subnets = 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mesh_proxy_node_id_timeout_handler(btstack_timer_source_t * ts){
|
static void mesh_proxy_node_id_timeout_handler(btstack_timer_source_t * ts){
|
||||||
@ -170,15 +179,15 @@ static void mesh_proxy_node_id_timeout_handler(btstack_timer_source_t * ts){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void mesh_proxy_node_id_handle_get_aes128(void * arg){
|
static void mesh_proxy_node_id_handle_get_aes128(void * arg){
|
||||||
mesh_subnet_t * network_key = (mesh_subnet_t *) arg;
|
mesh_subnet_t * mesh_subnet = (mesh_subnet_t *) arg;
|
||||||
|
|
||||||
memcpy(connectable_advertisement.adv_data, adv_data_with_node_identity_template, 12);
|
memcpy(mesh_subnet->advertisement_with_node_id.adv_data, adv_data_with_node_id_template, 12);
|
||||||
memcpy(&connectable_advertisement.adv_data[12], &mesh_proxy_node_id_hash[8], 8);
|
memcpy(&mesh_subnet->advertisement_with_node_id.adv_data[12], &mesh_proxy_node_id_hash[8], 8);
|
||||||
memcpy(&connectable_advertisement.adv_data[20], mesh_proxy_node_id_random_value, 8);
|
memcpy(&mesh_subnet->advertisement_with_node_id.adv_data[20], mesh_proxy_node_id_random_value, 8);
|
||||||
connectable_advertisement.adv_length = 28;
|
mesh_subnet->advertisement_with_node_id.adv_length = 28;
|
||||||
|
|
||||||
// setup advertisements
|
// setup advertisements
|
||||||
adv_bearer_advertisements_add_item(&connectable_advertisement);
|
adv_bearer_advertisements_add_item(&mesh_subnet->advertisement_with_node_id);
|
||||||
adv_bearer_advertisements_enable(1);
|
adv_bearer_advertisements_enable(1);
|
||||||
|
|
||||||
// set timer
|
// set timer
|
||||||
@ -187,34 +196,29 @@ static void mesh_proxy_node_id_handle_get_aes128(void * arg){
|
|||||||
btstack_run_loop_add_timer(&mesh_proxy_node_id_timer);
|
btstack_run_loop_add_timer(&mesh_proxy_node_id_timer);
|
||||||
|
|
||||||
// mark as active
|
// mark as active
|
||||||
network_key->node_id_advertisement_running = 1;
|
mesh_subnet->node_id_advertisement_running = 1;
|
||||||
|
|
||||||
|
// next one
|
||||||
|
if (mesh_proxy_node_id_all_subnets == 0) return;
|
||||||
|
mesh_proxy_start_advertising_with_node_id_next_subnet();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mesh_proxy_node_id_handle_random(void * arg){
|
static void mesh_proxy_node_id_handle_random(void * arg){
|
||||||
mesh_subnet_t * network_key = (mesh_subnet_t *) arg;
|
mesh_subnet_t * mesh_subnet = (mesh_subnet_t *) arg;
|
||||||
|
|
||||||
// Hash = e(IdentityKey, Padding | Random | Address) mod 2^64
|
// Hash = e(IdentityKey, Padding | Random | Address) mod 2^64
|
||||||
memset(mesh_proxy_node_id_plaintext, 0, sizeof(mesh_proxy_node_id_plaintext));
|
memset(mesh_proxy_node_id_plaintext, 0, sizeof(mesh_proxy_node_id_plaintext));
|
||||||
memcpy(&mesh_proxy_node_id_plaintext[6] , mesh_proxy_node_id_random_value, 8);
|
memcpy(&mesh_proxy_node_id_plaintext[6] , mesh_proxy_node_id_random_value, 8);
|
||||||
big_endian_store_16(mesh_proxy_node_id_plaintext, 14, primary_element_address);
|
big_endian_store_16(mesh_proxy_node_id_plaintext, 14, primary_element_address);
|
||||||
// TODO: old vs. new key
|
// TODO: old vs. new key
|
||||||
btstack_crypto_aes128_encrypt(&mesh_proxy_node_id_crypto_request_aes128, network_key->old_key->identity_key, mesh_proxy_node_id_plaintext, mesh_proxy_node_id_hash, mesh_proxy_node_id_handle_get_aes128, network_key);
|
btstack_crypto_aes128_encrypt(&mesh_proxy_node_id_crypto_request_aes128, mesh_subnet->old_key->identity_key, mesh_proxy_node_id_plaintext, mesh_proxy_node_id_hash, mesh_proxy_node_id_handle_get_aes128, mesh_subnet);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mesh_proxy_start_advertising_with_node_id(uint16_t netkey_index){
|
static void mesh_proxy_start_advertising_with_node_id_for_subnet(mesh_subnet_t * mesh_subnet){
|
||||||
mesh_proxy_stop_all_advertising_with_node_id();
|
if (mesh_subnet->node_id_advertisement_running) return;
|
||||||
// get network key
|
log_info("Proxy start advertising with node id, netkey index %04x", mesh_subnet->netkey_index);
|
||||||
mesh_subnet_t * network_key = mesh_subnet_get_by_netkey_index(netkey_index);
|
|
||||||
if (network_key == NULL) return;
|
|
||||||
log_info("Proxy start advertising with node id, netkey index %04x", netkey_index);
|
|
||||||
// setup node id
|
// setup node id
|
||||||
btstack_crypto_random_generate(&mesh_proxy_node_id_crypto_request_random, mesh_proxy_node_id_random_value, sizeof(mesh_proxy_node_id_random_value), mesh_proxy_node_id_handle_random, network_key);
|
btstack_crypto_random_generate(&mesh_proxy_node_id_crypto_request_random, mesh_proxy_node_id_random_value, sizeof(mesh_proxy_node_id_random_value), mesh_proxy_node_id_handle_random, mesh_subnet);
|
||||||
}
|
|
||||||
|
|
||||||
static void mesh_proxy_stop_advertising_with_node_id(uint16_t netkey_index){
|
|
||||||
UNUSED(netkey_index);
|
|
||||||
log_info("Proxy stop advertising with node id, netkey index %04x", netkey_index);
|
|
||||||
mesh_proxy_stop_all_advertising_with_node_id();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public API
|
// Public API
|
||||||
@ -240,18 +244,18 @@ uint8_t mesh_proxy_get_advertising_with_node_id_status(uint16_t netkey_index, me
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t mesh_proxy_set_advertising_with_node_id(uint16_t netkey_index, mesh_node_identity_state_t state){
|
uint8_t mesh_proxy_set_advertising_with_node_id(uint16_t netkey_index, mesh_node_identity_state_t state){
|
||||||
mesh_subnet_t * network_key = mesh_subnet_get_by_netkey_index(netkey_index);
|
mesh_subnet_t * mesh_subnet = mesh_subnet_get_by_netkey_index(netkey_index);
|
||||||
if (network_key == NULL){
|
if (mesh_subnet == NULL){
|
||||||
return MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX;
|
return MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_MESH_PROXY_SERVER
|
#ifdef ENABLE_MESH_PROXY_SERVER
|
||||||
switch (state){
|
switch (state){
|
||||||
case MESH_NODE_IDENTITY_STATE_ADVERTISING_STOPPED:
|
case MESH_NODE_IDENTITY_STATE_ADVERTISING_STOPPED:
|
||||||
mesh_proxy_stop_advertising_with_node_id(netkey_index);
|
mesh_proxy_stop_advertising_with_node_id_for_subnet(mesh_subnet);
|
||||||
return MESH_FOUNDATION_STATUS_SUCCESS;
|
return MESH_FOUNDATION_STATUS_SUCCESS;
|
||||||
case MESH_NODE_IDENTITY_STATE_ADVERTISING_RUNNING:
|
case MESH_NODE_IDENTITY_STATE_ADVERTISING_RUNNING:
|
||||||
mesh_proxy_start_advertising_with_node_id(netkey_index);
|
mesh_proxy_start_advertising_with_node_id_for_subnet(mesh_subnet);
|
||||||
return MESH_FOUNDATION_STATUS_SUCCESS;
|
return MESH_FOUNDATION_STATUS_SUCCESS;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -261,6 +265,29 @@ uint8_t mesh_proxy_set_advertising_with_node_id(uint16_t netkey_index, mesh_node
|
|||||||
return MESH_FOUNDATION_STATUS_FEATURE_NOT_SUPPORTED;
|
return MESH_FOUNDATION_STATUS_FEATURE_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mesh_proxy_start_advertising_with_node_id_next_subnet(void){
|
||||||
|
mesh_subnet_iterator_t it;
|
||||||
|
mesh_subnet_iterator_init(&it);
|
||||||
|
while (mesh_subnet_iterator_has_more(&it)){
|
||||||
|
mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it);
|
||||||
|
if (subnet->node_id_advertisement_running != 0) continue;
|
||||||
|
|
||||||
|
mesh_proxy_start_advertising_with_node_id_for_subnet(subnet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mesh_proxy_start_advertising_with_node_id(void){
|
||||||
|
mesh_proxy_node_id_all_subnets = 1;
|
||||||
|
adv_bearer_advertisements_enable(1);
|
||||||
|
|
||||||
|
// start advertising on first subnet that is not already advertising with node id
|
||||||
|
mesh_proxy_start_advertising_with_node_id_next_subnet();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mesh_proxy_stop_advertising_with_node_id(void){
|
||||||
|
mesh_proxy_stop_all_advertising_with_node_id();
|
||||||
|
}
|
||||||
|
|
||||||
void mesh_proxy_start_advertising_with_network_id(void){
|
void mesh_proxy_start_advertising_with_network_id(void){
|
||||||
mesh_subnet_iterator_t it;
|
mesh_subnet_iterator_t it;
|
||||||
|
@ -86,6 +86,16 @@ uint8_t mesh_proxy_set_advertising_with_node_id(uint16_t netkey_index, mesh_node
|
|||||||
*/
|
*/
|
||||||
uint8_t mesh_proxy_get_advertising_with_node_id_status(uint16_t netkey_index, mesh_node_identity_state_t * out_state );
|
uint8_t mesh_proxy_get_advertising_with_node_id_status(uint16_t netkey_index, mesh_node_identity_state_t * out_state );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start Advertising with Node Identity (on all subnets)
|
||||||
|
*/
|
||||||
|
void mesh_proxy_start_advertising_with_node_id(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop Advertising with Node Identity (on all subnets)
|
||||||
|
*/
|
||||||
|
void mesh_proxy_stop_advertising_with_node_id(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start Advertising with Network ID (on all subnets)
|
* @brief Start Advertising with Network ID (on all subnets)
|
||||||
*/
|
*/
|
||||||
|
@ -466,6 +466,8 @@ static void show_usage(void){
|
|||||||
printf("i - Input Output OOB \n");
|
printf("i - Input Output OOB \n");
|
||||||
printf("s - Static Output OOB \n");
|
printf("s - Static Output OOB \n");
|
||||||
printf("b - Set Secure Network Beacon %s\n", mesh_foundation_beacon_get() ? "Off" : "On");
|
printf("b - Set Secure Network Beacon %s\n", mesh_foundation_beacon_get() ? "Off" : "On");
|
||||||
|
printf("n - Start Advertising with Node Identity\n");
|
||||||
|
printf("N - Stop Advertising with Node Identity\n");
|
||||||
printf("g - Generic ON/OFF Server Toggle Value\n");
|
printf("g - Generic ON/OFF Server Toggle Value\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@ -544,6 +546,14 @@ static void stdin_process(char cmd){
|
|||||||
mesh_foundation_beacon_set(1 - mesh_foundation_beacon_get());
|
mesh_foundation_beacon_set(1 - mesh_foundation_beacon_get());
|
||||||
mesh_foundation_state_store();
|
mesh_foundation_state_store();
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
printf("Start Advertising with Node ID\n");
|
||||||
|
mesh_proxy_start_advertising_with_node_id();
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
printf("Stop Advertising with Node ID\n");
|
||||||
|
mesh_proxy_start_advertising_with_node_id();
|
||||||
|
break;
|
||||||
case ' ':
|
case ' ':
|
||||||
show_usage();
|
show_usage();
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user