1 /* 2 * Copyright (C) 2019 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define __BTSTACK_FILE__ "mesh_configuration_server.c" 39 40 #include <string.h> 41 #include <stdio.h> 42 43 #include "mesh/mesh_configuration_server.h" 44 45 #include "bluetooth_company_id.h" 46 #include "btstack_debug.h" 47 #include "btstack_memory.h" 48 #include "btstack_tlv.h" 49 #include "btstack_util.h" 50 51 #include "mesh/beacon.h" 52 #include "mesh/gatt_bearer.h" 53 #include "mesh/mesh.h" 54 #include "mesh/mesh_access.h" 55 #include "mesh/mesh_crypto.h" 56 #include "mesh/mesh_foundation.h" 57 #include "mesh/mesh_iv_index_seq_number.h" 58 #include "mesh/mesh_keys.h" 59 #include "mesh/mesh_network.h" 60 #include "mesh/mesh_node.h" 61 #include "mesh/mesh_proxy.h" 62 #include "mesh/mesh_upper_transport.h" 63 #include "mesh/mesh_virtual_addresses.h" 64 65 #define MESH_HEARTBEAT_FEATURES_SUPPORTED_MASK 0x000f 66 67 typedef struct { 68 uint16_t hash; 69 uint8_t label_uuid[16]; 70 } mesh_persistent_virtual_address_t; 71 72 73 // current access pdu 74 static mesh_pdu_t * access_pdu_in_process; 75 76 // data from current pdu 77 static uint16_t configuration_server_element_address; 78 static uint32_t configuration_server_model_identifier; 79 static mesh_model_t * configuration_server_target_model; 80 static mesh_publication_model_t configuration_server_publication_model; 81 82 // cmac for virtual address hash and netkey derive 83 static btstack_crypto_aes128_cmac_t configuration_server_cmac_request; 84 85 // used to setup virtual addresses 86 static uint8_t configuration_server_label_uuid[16]; 87 static uint16_t configuration_server_hash; 88 89 // heartbeat publication and subscription state for all Configuration Server models - there is only one 90 // static mesh_heartbeat_subscription_t mesh_heartbeat_subscription; 91 92 // for PTS testing 93 static int config_netkey_list_max = 0; 94 95 96 // Heartbeat (helper) 97 static uint16_t heartbeat_pwr2(uint8_t value){ 98 if (!value) return 0x0000; 99 if (value == 0xff || value == 0x11) return 0xffff; 100 return 1 << (value-1); 101 } 102 103 static uint8_t heartbeat_count_log(uint16_t value){ 104 if (!value) return 0x00; 105 if (value == 0x01) return 0x01; 106 if (value == 0xffff) return 0xff; 107 // count leading zeros, supported by clang and gcc 108 return 32 - __builtin_clz(value - 1) + 1; 109 } 110 111 // TLV 112 113 static const btstack_tlv_t * btstack_tlv_singleton_impl; 114 static void * btstack_tlv_singleton_context; 115 116 static uint32_t mesh_virtual_address_tag_for_pseudo_dst(uint16_t pseudo_dst){ 117 return ((uint32_t) 'M' << 24) | ((uint32_t) 'V' << 16) | ((uint32_t) pseudo_dst); 118 } 119 120 static void mesh_configuration_server_setup_tlv(void){ 121 if (btstack_tlv_singleton_impl) return; 122 btstack_tlv_get_instance(&btstack_tlv_singleton_impl, &btstack_tlv_singleton_context); 123 } 124 125 static void mesh_store_virtual_address(uint16_t pseudo_dest, uint16_t hash, const uint8_t * label_uuid){ 126 mesh_configuration_server_setup_tlv(); 127 128 mesh_persistent_virtual_address_t data; 129 uint32_t tag = mesh_virtual_address_tag_for_pseudo_dst(pseudo_dest); 130 data.hash = hash; 131 memcpy(data.label_uuid, label_uuid, 16); 132 btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &data, sizeof(data)); 133 } 134 135 static void mesh_delete_virtual_address(uint16_t pseudo_dest){ 136 mesh_configuration_server_setup_tlv(); 137 138 uint32_t tag = mesh_virtual_address_tag_for_pseudo_dst(pseudo_dest); 139 btstack_tlv_singleton_impl->delete_tag(btstack_tlv_singleton_context, tag); 140 } 141 142 void mesh_load_virtual_addresses(void){ 143 mesh_configuration_server_setup_tlv(); 144 uint16_t pseudo_dst; 145 for (pseudo_dst = 0x8000; pseudo_dst < (0x8000 + MAX_NR_MESH_VIRTUAL_ADDRESSES); pseudo_dst++){ 146 mesh_virtual_address_tag_for_pseudo_dst(pseudo_dst); 147 mesh_persistent_virtual_address_t data; 148 uint32_t tag = mesh_virtual_address_tag_for_pseudo_dst(pseudo_dst); 149 int virtual_address_len = btstack_tlv_singleton_impl->get_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &data, sizeof(data)); 150 if (virtual_address_len == 0) return; 151 152 mesh_virtual_address_t * virtual_address = btstack_memory_mesh_virtual_address_get(); 153 if (virtual_address == NULL) return; 154 155 virtual_address->pseudo_dst = pseudo_dst; 156 virtual_address->hash = data.hash; 157 memcpy(virtual_address->label_uuid, data.label_uuid, 16); 158 mesh_virtual_address_add(virtual_address); 159 } 160 } 161 162 void mesh_delete_virtual_addresses(void){ 163 uint16_t pseudo_dest; 164 for (pseudo_dest = 0x8000; pseudo_dest < (0x8000 + MAX_NR_MESH_VIRTUAL_ADDRESSES); pseudo_dest++){ 165 mesh_delete_virtual_address(pseudo_dest); 166 } 167 } 168 169 static void mesh_virtual_address_decrease_refcount(mesh_virtual_address_t * virtual_address){ 170 if (virtual_address == NULL){ 171 log_error("virtual_address == NULL"); 172 } 173 // decrease refcount 174 virtual_address->ref_count--; 175 // Free virtual address if ref count reaches zero 176 if (virtual_address->ref_count > 0) return; 177 // delete from TLV 178 mesh_delete_virtual_address(virtual_address->pseudo_dst); 179 // remove from list 180 mesh_virtual_address_remove(virtual_address); 181 // free memory 182 btstack_memory_mesh_virtual_address_free(virtual_address); 183 } 184 185 static void mesh_virtual_address_increase_refcount(mesh_virtual_address_t * virtual_address){ 186 if (virtual_address == NULL){ 187 log_error("virtual_address == NULL"); 188 } 189 virtual_address->ref_count++; 190 if (virtual_address->ref_count > 1) return; 191 // store in TLV 192 mesh_store_virtual_address(virtual_address->pseudo_dst, virtual_address->hash, virtual_address->label_uuid); 193 } 194 195 static int mesh_model_is_configuration_server(uint32_t model_identifier){ 196 return mesh_model_is_bluetooth_sig(model_identifier) && (mesh_model_get_model_id(model_identifier) == MESH_SIG_MODEL_ID_CONFIGURATION_SERVER); 197 } 198 199 // Configuration Model Subscriptions (helper) 200 201 // Model to Appkey List 202 203 static uint32_t mesh_model_subscription_tag_for_index(uint16_t internal_model_id){ 204 return ((uint32_t) 'M' << 24) | ((uint32_t) 'S' << 16) | ((uint32_t) internal_model_id); 205 } 206 207 static void mesh_model_load_subscriptions(mesh_model_t * mesh_model){ 208 mesh_configuration_server_setup_tlv(); 209 uint32_t tag = mesh_model_subscription_tag_for_index(mesh_model->mid); 210 btstack_tlv_singleton_impl->get_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &mesh_model->subscriptions, sizeof(mesh_model->subscriptions)); 211 // update ref count 212 213 // increase ref counts for virtual subscriptions 214 uint16_t i; 215 for (i = 0; i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL ; i++){ 216 uint16_t src = mesh_model->subscriptions[i]; 217 if (mesh_network_address_virtual(src)){ 218 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_pseudo_dst(src); 219 mesh_virtual_address_increase_refcount(virtual_address); 220 } 221 } 222 } 223 224 static void mesh_model_store_subscriptions(mesh_model_t * model){ 225 mesh_configuration_server_setup_tlv(); 226 uint32_t tag = mesh_model_subscription_tag_for_index(model->mid); 227 btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &model->subscriptions, sizeof(model->subscriptions)); 228 } 229 230 static void mesh_model_delete_subscriptions(mesh_model_t * model){ 231 mesh_configuration_server_setup_tlv(); 232 uint32_t tag = mesh_model_subscription_tag_for_index(model->mid); 233 btstack_tlv_singleton_impl->delete_tag(btstack_tlv_singleton_context, tag); 234 } 235 236 void mesh_load_subscriptions(void){ 237 printf("Load Model Subscription Lists\n"); 238 // iterate over elements and models 239 mesh_element_iterator_t element_it; 240 mesh_element_iterator_init(&element_it); 241 while (mesh_element_iterator_has_next(&element_it)){ 242 mesh_element_t * element = mesh_element_iterator_next(&element_it); 243 mesh_model_iterator_t model_it; 244 mesh_model_iterator_init(&model_it, element); 245 while (mesh_model_iterator_has_next(&model_it)){ 246 mesh_model_t * model = mesh_model_iterator_next(&model_it); 247 mesh_model_load_subscriptions(model); 248 } 249 } 250 } 251 252 void mesh_delete_subscriptions(void){ 253 printf("Delete Model Subscription Lists\n"); 254 mesh_configuration_server_setup_tlv(); 255 // iterate over elements and models 256 mesh_element_iterator_t element_it; 257 mesh_element_iterator_init(&element_it); 258 while (mesh_element_iterator_has_next(&element_it)){ 259 mesh_element_t * element = mesh_element_iterator_next(&element_it); 260 mesh_model_iterator_t model_it; 261 mesh_model_iterator_init(&model_it, element); 262 while (mesh_model_iterator_has_next(&model_it)){ 263 mesh_model_t * model = mesh_model_iterator_next(&model_it); 264 mesh_model_delete_subscriptions(model); 265 } 266 } 267 } 268 269 static uint8_t mesh_model_add_subscription(mesh_model_t * mesh_model, uint16_t address){ 270 uint16_t i; 271 for (i=0;i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL;i++){ 272 if (mesh_model->subscriptions[i] == address) return MESH_FOUNDATION_STATUS_SUCCESS; 273 } 274 for (i=0;i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL;i++){ 275 if (mesh_model->subscriptions[i] == MESH_ADDRESS_UNSASSIGNED) { 276 mesh_model->subscriptions[i] = address; 277 return MESH_FOUNDATION_STATUS_SUCCESS; 278 } 279 } 280 return MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 281 } 282 283 static void mesh_model_delete_subscription(mesh_model_t * mesh_model, uint16_t address){ 284 uint16_t i; 285 for (i=0;i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL;i++){ 286 if (mesh_model->subscriptions[i] == address) { 287 mesh_model->subscriptions[i] = MESH_ADDRESS_UNSASSIGNED; 288 } 289 } 290 } 291 292 static void mesh_model_delete_all_subscriptions(mesh_model_t * mesh_model){ 293 uint16_t i; 294 for (i=0;i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL;i++){ 295 mesh_model->subscriptions[i] = MESH_ADDRESS_UNSASSIGNED; 296 } 297 } 298 299 static void mesh_subcription_decrease_virtual_address_ref_count(mesh_model_t *mesh_model){ 300 // decrease ref counts for current virtual subscriptions 301 uint16_t i; 302 for (i = 0; i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL ; i++){ 303 uint16_t src = mesh_model->subscriptions[i]; 304 if (mesh_network_address_virtual(src)){ 305 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_pseudo_dst(src); 306 mesh_virtual_address_decrease_refcount(virtual_address); 307 } 308 } 309 } 310 311 // Model Publication 312 313 static uint32_t mesh_model_publication_tag_for_index(uint16_t internal_model_id){ 314 return ((uint32_t) 'M' << 24) | ((uint32_t) 'P' << 16) | ((uint32_t) internal_model_id); 315 } 316 317 static void mesh_model_load_publication(mesh_model_t * mesh_model){ 318 mesh_configuration_server_setup_tlv(); 319 if (mesh_model->publication_model == NULL) return; 320 321 uint32_t tag = mesh_model_publication_tag_for_index(mesh_model->mid); 322 btstack_tlv_singleton_impl->get_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &mesh_model->publication_model, sizeof(mesh_publication_model_t)); 323 324 // increase ref counts for current virtual publicataion address 325 uint16_t src = mesh_model->publication_model->address; 326 if (mesh_network_address_virtual(src)){ 327 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_pseudo_dst(src); 328 mesh_virtual_address_increase_refcount(virtual_address); 329 } 330 331 mesh_model_publication_start(mesh_model); 332 } 333 334 static void mesh_model_store_publication(mesh_model_t * mesh_model){ 335 mesh_configuration_server_setup_tlv(); 336 if (mesh_model->publication_model == NULL) return; 337 uint32_t tag = mesh_model_publication_tag_for_index(mesh_model->mid); 338 btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &mesh_model->subscriptions, sizeof(mesh_publication_model_t)); 339 } 340 341 static void mesh_model_delete_publication(mesh_model_t * mesh_model){ 342 mesh_configuration_server_setup_tlv(); 343 if (mesh_model->publication_model == NULL) return; 344 uint32_t tag = mesh_model_publication_tag_for_index(mesh_model->mid); 345 btstack_tlv_singleton_impl->delete_tag(btstack_tlv_singleton_context, tag); 346 } 347 348 void mesh_load_publications(void){ 349 printf("Load Model Publications\n"); 350 // iterate over elements and models 351 mesh_element_iterator_t element_it; 352 mesh_element_iterator_init(&element_it); 353 while (mesh_element_iterator_has_next(&element_it)){ 354 mesh_element_t * element = mesh_element_iterator_next(&element_it); 355 mesh_model_iterator_t model_it; 356 mesh_model_iterator_init(&model_it, element); 357 while (mesh_model_iterator_has_next(&model_it)){ 358 mesh_model_t * model = mesh_model_iterator_next(&model_it); 359 mesh_model_load_publication(model); 360 } 361 } 362 } 363 364 void mesh_delete_publications(void){ 365 printf("Delete Model Publications\n"); 366 mesh_configuration_server_setup_tlv(); 367 // iterate over elements and models 368 mesh_element_iterator_t element_it; 369 mesh_element_iterator_init(&element_it); 370 while (mesh_element_iterator_has_next(&element_it)){ 371 mesh_element_t * element = mesh_element_iterator_next(&element_it); 372 mesh_model_iterator_t model_it; 373 mesh_model_iterator_init(&model_it, element); 374 while (mesh_model_iterator_has_next(&model_it)){ 375 mesh_model_t * model = mesh_model_iterator_next(&model_it); 376 mesh_model_delete_publication(model); 377 } 378 } 379 } 380 381 // AppKeys Helper 382 static void mesh_configuration_server_delete_appkey(mesh_transport_key_t * transport_key){ 383 uint16_t appkey_index = transport_key->appkey_index; 384 385 // iterate over elements and models 386 mesh_element_iterator_t element_it; 387 mesh_element_iterator_init(&element_it); 388 while (mesh_element_iterator_has_next(&element_it)){ 389 mesh_element_t * element = mesh_element_iterator_next(&element_it); 390 mesh_model_iterator_t model_it; 391 mesh_model_iterator_init(&model_it, element); 392 while (mesh_model_iterator_has_next(&model_it)){ 393 mesh_model_t * mesh_model = mesh_model_iterator_next(&model_it); 394 395 // remove from Model to AppKey List 396 mesh_model_unbind_appkey(mesh_model, appkey_index); 397 398 // stop publishing if this AppKey was used 399 if (mesh_model->publication_model != NULL){ 400 mesh_publication_model_t * publication_model = mesh_model->publication_model; 401 if (publication_model->appkey_index == appkey_index){ 402 publication_model->address = MESH_ADDRESS_UNSASSIGNED; 403 publication_model->appkey_index = MESH_APPKEY_INVALID; 404 mesh_model_store_publication(mesh_model); 405 } 406 } 407 } 408 } 409 410 mesh_access_appkey_finalize(transport_key); 411 } 412 413 // Foundatiopn Message 414 415 const mesh_access_message_t mesh_foundation_config_beacon_status = { 416 MESH_FOUNDATION_OPERATION_BEACON_STATUS, "1" 417 }; 418 const mesh_access_message_t mesh_foundation_config_default_ttl_status = { 419 MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS, "1" 420 }; 421 const mesh_access_message_t mesh_foundation_config_friend_status = { 422 MESH_FOUNDATION_OPERATION_FRIEND_STATUS, "1" 423 }; 424 const mesh_access_message_t mesh_foundation_config_gatt_proxy_status = { 425 MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS, "1" 426 }; 427 const mesh_access_message_t mesh_foundation_config_relay_status = { 428 MESH_FOUNDATION_OPERATION_RELAY_STATUS, "11" 429 }; 430 const mesh_access_message_t mesh_foundation_config_model_publication_status = { 431 MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS, "1222111m" 432 }; 433 const mesh_access_message_t mesh_foundation_config_model_subscription_status = { 434 MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS, "122m" 435 }; 436 const mesh_access_message_t mesh_foundation_config_netkey_status = { 437 MESH_FOUNDATION_OPERATION_NETKEY_STATUS, "12" 438 }; 439 const mesh_access_message_t mesh_foundation_config_appkey_status = { 440 MESH_FOUNDATION_OPERATION_APPKEY_STATUS, "13" 441 }; 442 const mesh_access_message_t mesh_foundation_config_model_app_status = { 443 MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS, "122m" 444 }; 445 const mesh_access_message_t mesh_foundation_node_reset_status = { 446 MESH_FOUNDATION_OPERATION_NODE_RESET_STATUS, "" 447 }; 448 const mesh_access_message_t mesh_foundation_config_heartbeat_publication_status = { 449 MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_STATUS, "1211122" 450 }; 451 const mesh_access_message_t mesh_foundation_config_network_transmit_status = { 452 MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_STATUS, "11" 453 }; 454 const mesh_access_message_t mesh_foundation_node_identity_status = { 455 MESH_FOUNDATION_OPERATION_NODE_IDENTITY_STATUS, "121" 456 }; 457 const mesh_access_message_t mesh_key_refresh_phase_status = { 458 MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_STATUS, "121" 459 }; 460 const mesh_access_message_t mesh_foundation_low_power_node_poll_timeout_status = { 461 MESH_FOUNDATION_OPERATION_LOW_POWER_NODE_POLL_TIMEOUT_STATUS, "23" 462 }; 463 const mesh_access_message_t mesh_foundation_config_heartbeat_subscription_status = { 464 MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_STATUS, "1221111" 465 }; 466 467 static void config_server_send_message(uint16_t netkey_index, uint16_t dest, mesh_pdu_t *pdu){ 468 // Configuration Server is on primary element and can only use DeviceKey 469 uint16_t appkey_index = MESH_DEVICE_KEY_INDEX; 470 uint16_t src = mesh_node_get_primary_element_address(); 471 uint8_t ttl = mesh_foundation_default_ttl_get(); 472 mesh_upper_transport_setup_access_pdu_header(pdu, netkey_index, appkey_index, ttl, src, dest, 0); 473 mesh_access_send_unacknowledged_pdu(pdu); 474 } 475 476 static void config_composition_data_status(uint16_t netkey_index, uint16_t dest){ 477 478 printf("Received Config Composition Data Get -> send Config Composition Data Status\n"); 479 480 mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_STATUS); 481 if (!transport_pdu) return; 482 483 // page 0 484 mesh_access_transport_add_uint8(transport_pdu, 0); 485 486 // CID 487 mesh_access_transport_add_uint16(transport_pdu, BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH); 488 // PID 489 mesh_access_transport_add_uint16(transport_pdu, 0); 490 // VID 491 mesh_access_transport_add_uint16(transport_pdu, 0); 492 // CRPL - number of protection list entries 493 mesh_access_transport_add_uint16(transport_pdu, 1); 494 // Features - Relay, Proxy, Friend, Lower Power, ... 495 mesh_access_transport_add_uint16(transport_pdu, 0); 496 497 mesh_element_iterator_t element_it; 498 mesh_element_iterator_init(&element_it); 499 while (mesh_element_iterator_has_next(&element_it)){ 500 mesh_element_t * element = mesh_element_iterator_next(&element_it); 501 502 // Loc 503 mesh_access_transport_add_uint16(transport_pdu, element->loc); 504 // NumS 505 mesh_access_transport_add_uint8( transport_pdu, element->models_count_sig); 506 // NumV 507 mesh_access_transport_add_uint8( transport_pdu, element->models_count_vendor); 508 509 mesh_model_iterator_t model_it; 510 511 // SIG Models 512 mesh_model_iterator_init(&model_it, element); 513 while (mesh_model_iterator_has_next(&model_it)){ 514 mesh_model_t * model = mesh_model_iterator_next(&model_it); 515 if (!mesh_model_is_bluetooth_sig(model->model_identifier)) continue; 516 mesh_access_transport_add_uint16(transport_pdu, model->model_identifier); 517 } 518 // Vendor Models 519 mesh_model_iterator_init(&model_it, element); 520 while (mesh_model_iterator_has_next(&model_it)){ 521 mesh_model_t * model = mesh_model_iterator_next(&model_it); 522 if (mesh_model_is_bluetooth_sig(model->model_identifier)) continue; 523 mesh_access_transport_add_uint32(transport_pdu, model->model_identifier); 524 } 525 } 526 527 // send as segmented access pdu 528 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 529 } 530 531 static void config_composition_data_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 532 UNUSED(mesh_model); 533 config_composition_data_status(mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 534 535 mesh_access_message_processed(pdu); 536 } 537 538 static void config_model_beacon_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 539 UNUSED(mesh_model); 540 // setup message 541 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_config_beacon_status, 542 mesh_foundation_beacon_get()); 543 if (!transport_pdu) return; 544 545 // send as segmented access pdu 546 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 547 } 548 549 static void config_beacon_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 550 config_model_beacon_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 551 552 mesh_access_message_processed(pdu); 553 } 554 555 static void config_beacon_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 556 mesh_access_parser_state_t parser; 557 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 558 559 uint8_t beacon_enabled = mesh_access_parser_get_u8(&parser); 560 561 // beacon valid 562 if (beacon_enabled >= MESH_FOUNDATION_STATE_NOT_SUPPORTED) return; 563 564 // store 565 mesh_foundation_beacon_set(beacon_enabled); 566 mesh_foundation_state_store(); 567 568 // 569 config_model_beacon_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 570 571 mesh_access_message_processed(pdu); 572 } 573 574 static void config_model_default_ttl_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 575 UNUSED(mesh_model); 576 // setup message 577 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 578 &mesh_foundation_config_default_ttl_status, mesh_foundation_default_ttl_get()); 579 if (!transport_pdu) return; 580 581 // send as segmented access pdu 582 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 583 } 584 585 static void config_default_ttl_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 586 config_model_default_ttl_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 587 588 mesh_access_message_processed(pdu); 589 } 590 591 static void config_default_ttl_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 592 mesh_access_parser_state_t parser; 593 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 594 595 uint8_t new_ttl = mesh_access_parser_get_u8(&parser); 596 597 // ttl valid 598 if (new_ttl > 0x7f || new_ttl == 0x01) return; 599 // store 600 mesh_foundation_default_ttl_set(new_ttl); 601 mesh_foundation_state_store(); 602 603 // 604 config_model_default_ttl_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 605 606 mesh_access_message_processed(pdu); 607 } 608 609 static void config_friend_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 610 UNUSED(mesh_model); 611 612 // setup message 613 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 614 &mesh_foundation_config_friend_status, mesh_foundation_friend_get()); 615 if (!transport_pdu) return; 616 617 // send as segmented access pdu 618 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 619 } 620 621 static void config_friend_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 622 config_friend_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 623 624 mesh_access_message_processed(pdu); 625 } 626 627 static void config_friend_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 628 mesh_access_parser_state_t parser; 629 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 630 631 uint8_t new_friend_state = mesh_access_parser_get_u8(&parser); 632 633 // validate 634 if (new_friend_state >= MESH_FOUNDATION_STATE_NOT_SUPPORTED) return; 635 636 // store if supported 637 if (mesh_foundation_friend_get() != MESH_FOUNDATION_STATE_NOT_SUPPORTED){ 638 mesh_foundation_friend_set(new_friend_state); 639 mesh_foundation_state_store(); 640 } 641 642 // 643 config_friend_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 644 645 mesh_access_message_processed(pdu); 646 } 647 648 static void config_model_gatt_proxy_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 649 UNUSED(mesh_model); 650 // setup message 651 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 652 &mesh_foundation_config_gatt_proxy_status, mesh_foundation_gatt_proxy_get()); 653 if (!transport_pdu) return; 654 655 // send as segmented access pdu 656 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 657 } 658 659 static void config_gatt_proxy_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 660 config_model_gatt_proxy_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 661 662 mesh_access_message_processed(pdu); 663 } 664 665 static void config_gatt_proxy_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 666 mesh_access_parser_state_t parser; 667 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 668 669 uint8_t enabled = mesh_access_parser_get_u8(&parser); 670 671 // ttl valid 672 if (enabled > 1) return; 673 // store 674 mesh_foundation_gatt_proxy_set(enabled); 675 mesh_foundation_state_store(); 676 677 // 678 config_model_gatt_proxy_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 679 680 mesh_access_message_processed(pdu); 681 682 // trigger heartbeat emit on change 683 mesh_configuration_server_feature_changed(); 684 } 685 686 static void config_model_relay_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 687 UNUSED(mesh_model); 688 689 // setup message 690 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_config_relay_status, 691 mesh_foundation_relay_get(), 692 mesh_foundation_relay_retransmit_get()); 693 if (!transport_pdu) return; 694 695 // send as segmented access pdu 696 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 697 } 698 699 static void config_relay_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 700 config_model_relay_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 701 702 mesh_access_message_processed(pdu); 703 } 704 705 static void config_relay_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 706 707 mesh_access_parser_state_t parser; 708 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 709 710 // check if valid 711 uint8_t relay = mesh_access_parser_get_u8(&parser); 712 uint8_t relay_retransmit = mesh_access_parser_get_u8(&parser); 713 714 // check if valid 715 if (relay > 1) return; 716 717 // only update if supported 718 if (mesh_foundation_relay_get() != MESH_FOUNDATION_STATE_NOT_SUPPORTED){ 719 mesh_foundation_relay_set(relay); 720 mesh_foundation_relay_retransmit_set(relay_retransmit); 721 mesh_foundation_state_store(); 722 } 723 724 // 725 config_model_relay_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 726 727 mesh_access_message_processed(pdu); 728 729 // trigger heartbeat emit on change 730 mesh_configuration_server_feature_changed(); 731 } 732 733 static void config_model_network_transmit_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest){ 734 UNUSED(mesh_model); 735 736 // setup message 737 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 738 &mesh_foundation_config_network_transmit_status, mesh_foundation_network_transmit_get()); 739 if (!transport_pdu) return; 740 741 // send as segmented access pdu 742 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 743 } 744 745 static void config_model_network_transmit_get_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu){ 746 config_model_network_transmit_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 747 748 mesh_access_message_processed(pdu); 749 } 750 751 static void config_model_network_transmit_set_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu){ 752 mesh_access_parser_state_t parser; 753 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 754 755 uint8_t new_ttl = mesh_access_parser_get_u8(&parser); 756 757 // store 758 mesh_foundation_network_transmit_set(new_ttl); 759 mesh_foundation_state_store(); 760 761 // 762 config_model_network_transmit_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 763 764 mesh_access_message_processed(pdu); 765 } 766 767 // NetKey List 768 769 void config_nekey_list_set_max(uint16_t max){ 770 config_netkey_list_max = max; 771 } 772 773 static void config_netkey_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, uint16_t new_netkey_index){ 774 UNUSED(mesh_model); 775 776 // setup message 777 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 778 &mesh_foundation_config_netkey_status, status, new_netkey_index); 779 if (!transport_pdu) return; 780 781 // send as segmented access pdu 782 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 783 } 784 785 static void config_netkey_list(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest) { 786 UNUSED(mesh_model); 787 788 mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(MESH_FOUNDATION_OPERATION_NETKEY_LIST); 789 if (!transport_pdu) return; 790 791 // add list of netkey indexes 792 mesh_network_key_iterator_t it; 793 mesh_network_key_iterator_init(&it); 794 while (mesh_network_key_iterator_has_more(&it)){ 795 mesh_network_key_t * network_key = mesh_network_key_iterator_get_next(&it); 796 mesh_access_transport_add_uint16(transport_pdu, network_key->netkey_index); 797 } 798 799 // send as segmented access pdu 800 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 801 } 802 803 static void config_netkey_add_derived(void * arg){ 804 mesh_subnet_t * subnet = (mesh_subnet_t *) arg; 805 806 // store network key 807 mesh_store_network_key(subnet->old_key); 808 809 // add key to NetKey List 810 mesh_network_key_add(subnet->old_key); 811 812 // add subnet 813 mesh_subnet_add(subnet); 814 815 #ifdef ENABLE_MESH_PROXY_SERVER 816 mesh_proxy_start_advertising_with_network_id(); 817 #endif 818 819 config_netkey_status(mesh_model_get_configuration_server(), mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), MESH_FOUNDATION_STATUS_SUCCESS, subnet->netkey_index); 820 mesh_access_message_processed(access_pdu_in_process); 821 } 822 823 static void config_netkey_add_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu){ 824 mesh_access_parser_state_t parser; 825 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 826 827 // get params 828 uint8_t new_netkey[16]; 829 uint16_t new_netkey_index = mesh_access_parser_get_u16(&parser); 830 mesh_access_parser_get_key(&parser, new_netkey); 831 832 uint8_t status; 833 834 const mesh_subnet_t * existing_subnet = mesh_subnet_get_by_netkey_index(new_netkey_index); 835 if (existing_subnet == NULL){ 836 837 // check limit for pts 838 uint16_t internal_index = mesh_network_key_get_free_index(); 839 if (internal_index == 0 || (config_netkey_list_max && mesh_network_key_list_count() >= config_netkey_list_max)){ 840 status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 841 } else { 842 843 // allocate new key and subnet 844 mesh_network_key_t * new_network_key = btstack_memory_mesh_network_key_get(); 845 mesh_subnet_t * new_subnet = btstack_memory_mesh_subnet_get(); 846 847 if (new_network_key == NULL || new_subnet == NULL){ 848 if (new_network_key != NULL){ 849 btstack_memory_mesh_network_key_free(new_network_key); 850 } 851 if (new_subnet != NULL){ 852 btstack_memory_mesh_subnet_free(new_subnet); 853 } 854 status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 855 856 } else { 857 858 // setup key 859 new_network_key->internal_index = internal_index; 860 new_network_key->netkey_index = new_netkey_index; 861 memcpy(new_network_key->net_key, new_netkey, 16); 862 863 // setup subnet 864 new_subnet->old_key = new_network_key; 865 new_subnet->netkey_index = new_netkey_index; 866 new_subnet->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE; 867 868 // derive other keys 869 access_pdu_in_process = pdu; 870 mesh_network_key_derive(&configuration_server_cmac_request, new_network_key, config_netkey_add_derived, new_network_key); 871 return; 872 } 873 } 874 875 } else { 876 // network key for netkey index already exists 877 if (memcmp(existing_subnet->old_key->net_key, new_netkey, 16) == 0){ 878 // same netkey 879 status = MESH_FOUNDATION_STATUS_SUCCESS; 880 } else { 881 // different netkey 882 status = MESH_FOUNDATION_STATUS_KEY_INDEX_ALREADY_STORED; 883 } 884 } 885 886 // report status 887 config_netkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, new_netkey_index); 888 mesh_access_message_processed(access_pdu_in_process); 889 } 890 891 static void config_netkey_update_derived(void * arg){ 892 mesh_subnet_t * subnet = (mesh_subnet_t *) arg; 893 894 // store network key 895 mesh_store_network_key(subnet->new_key); 896 897 // add key to NetKey List 898 mesh_network_key_add(subnet->new_key); 899 900 // update subnet - Key Refresh Phase 1 901 subnet->key_refresh = MESH_KEY_REFRESH_FIRST_PHASE; 902 903 // report status 904 config_netkey_status(mesh_model_get_configuration_server(), mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), MESH_FOUNDATION_STATUS_SUCCESS, subnet->netkey_index); 905 mesh_access_message_processed(access_pdu_in_process); 906 } 907 908 static void config_netkey_update_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu) { 909 mesh_access_parser_state_t parser; 910 mesh_access_parser_init(&parser, (mesh_pdu_t *) pdu); 911 912 // get params 913 uint8_t new_netkey[16]; 914 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 915 mesh_access_parser_get_key(&parser, new_netkey); 916 917 // get existing subnet 918 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index); 919 if (subnet == NULL){ 920 config_netkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX, netkey_index); 921 mesh_access_message_processed(access_pdu_in_process); 922 return; 923 } 924 925 // setup new key 926 uint16_t internal_index = mesh_network_key_get_free_index(); 927 mesh_network_key_t * new_network_key = btstack_memory_mesh_network_key_get(); 928 if (internal_index == 0 || new_network_key == NULL){ 929 config_netkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES, netkey_index); 930 mesh_access_message_processed(access_pdu_in_process); 931 return; 932 } 933 934 // setup new key 935 new_network_key->internal_index = internal_index; 936 new_network_key->netkey_index = netkey_index; 937 new_network_key->version = (uint8_t)(subnet->old_key->version + 1); 938 memcpy(new_network_key->net_key, new_netkey, 16); 939 940 // store in subnet (not active yet) 941 subnet->new_key = new_network_key; 942 943 // derive other keys 944 access_pdu_in_process = pdu; 945 mesh_network_key_derive(&configuration_server_cmac_request, new_network_key, config_netkey_update_derived, subnet); 946 } 947 948 static void config_netkey_delete_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu) { 949 mesh_access_parser_state_t parser; 950 mesh_access_parser_init(&parser, (mesh_pdu_t *) pdu); 951 952 // get params 953 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 954 955 // get existing network_key 956 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 957 958 // remove subnet 959 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index); 960 if (subnet != NULL){ 961 // A NetKey shall not be deleted from the NetKey List using a message secured with this NetKey. 962 if (mesh_subnet_list_count() > 1 && subnet->netkey_index != netkey_index){ 963 964 // remove all appkeys for this netkey 965 mesh_transport_key_iterator_t it; 966 mesh_transport_key_iterator_init(&it, netkey_index); 967 while (mesh_transport_key_iterator_has_more(&it)){ 968 mesh_transport_key_t * transport_key = mesh_transport_key_iterator_get_next(&it); 969 mesh_configuration_server_delete_appkey(transport_key); 970 } 971 972 // delete old/current key 973 mesh_access_netkey_finalize(subnet->old_key); 974 subnet->old_key = NULL; 975 976 // delete new key 977 if (subnet->new_key != NULL){ 978 mesh_access_netkey_finalize(subnet->new_key); 979 subnet->new_key = NULL; 980 } 981 982 // remove subnet 983 mesh_subnet_remove(subnet); 984 btstack_memory_mesh_subnet_free(subnet); 985 986 } else { 987 // we cannot remove the last network key 988 status = MESH_FOUNDATION_STATUS_CANNOT_REMOVE; 989 } 990 } 991 config_netkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index); 992 } 993 994 static void config_netkey_get_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu){ 995 config_netkey_list(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 996 mesh_access_message_processed(pdu); 997 } 998 999 // AppKey List 1000 1001 static void config_appkey_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint32_t netkey_and_appkey_index, uint8_t status){ 1002 UNUSED(mesh_model); 1003 1004 // setup message 1005 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_config_appkey_status, 1006 status, netkey_and_appkey_index); 1007 if (!transport_pdu) return; 1008 1009 // send as segmented access pdu 1010 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1011 } 1012 1013 static void config_appkey_list(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint32_t netkey_index_of_list){ 1014 UNUSED(mesh_model); 1015 1016 mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(MESH_FOUNDATION_OPERATION_APPKEY_LIST); 1017 if (!transport_pdu) return; 1018 1019 // check netkey_index is valid 1020 mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index_of_list); 1021 uint8_t status; 1022 if (network_key == NULL){ 1023 status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX; 1024 } else { 1025 status = MESH_FOUNDATION_STATUS_SUCCESS; 1026 } 1027 mesh_access_transport_add_uint8(transport_pdu, status); 1028 mesh_access_transport_add_uint16(transport_pdu, netkey_index_of_list); 1029 1030 // add list of appkey indexes 1031 mesh_transport_key_iterator_t it; 1032 mesh_transport_key_iterator_init(&it, netkey_index_of_list); 1033 while (mesh_transport_key_iterator_has_more(&it)){ 1034 mesh_transport_key_t * transport_key = mesh_transport_key_iterator_get_next(&it); 1035 mesh_access_transport_add_uint16(transport_pdu, transport_key->appkey_index); 1036 } 1037 1038 // send as segmented access pdu 1039 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1040 } 1041 1042 static void config_appkey_add_or_update_aid(void *arg){ 1043 mesh_transport_key_t * transport_key = (mesh_transport_key_t *) arg; 1044 1045 printf("Config Appkey Add/Update: NetKey Index 0x%04x, AppKey Index 0x%04x, AID %02x: ", transport_key->netkey_index, transport_key->appkey_index, transport_key->aid); 1046 printf_hexdump(transport_key->key, 16); 1047 1048 // store in TLV 1049 mesh_store_app_key(transport_key); 1050 1051 // add app key 1052 mesh_transport_key_add(transport_key); 1053 1054 uint32_t netkey_and_appkey_index = (transport_key->appkey_index << 12) | transport_key->netkey_index; 1055 config_appkey_status(mesh_model_get_configuration_server(), mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_SUCCESS); 1056 1057 mesh_access_message_processed(access_pdu_in_process); 1058 } 1059 1060 static void config_appkey_add_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1061 1062 mesh_access_parser_state_t parser; 1063 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1064 1065 // netkey and appkey index 1066 uint32_t netkey_and_appkey_index = mesh_access_parser_get_u24(&parser); 1067 uint16_t netkey_index = netkey_and_appkey_index & 0xfff; 1068 uint16_t appkey_index = netkey_and_appkey_index >> 12; 1069 1070 // actual key 1071 uint8_t appkey[16]; 1072 mesh_access_parser_get_key(&parser, appkey); 1073 1074 // check netkey_index is valid 1075 mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index); 1076 if (network_key == NULL){ 1077 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX); 1078 mesh_access_message_processed(pdu); 1079 return; 1080 } 1081 1082 // check if appkey already exists 1083 mesh_transport_key_t * transport_key = mesh_transport_key_get(appkey_index); 1084 if (transport_key){ 1085 uint8_t status; 1086 if (transport_key->netkey_index != netkey_index){ 1087 // already stored but with different netkey 1088 status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX; 1089 } else if (memcmp(transport_key->key, appkey, 16) == 0){ 1090 // key identical 1091 status = MESH_FOUNDATION_STATUS_SUCCESS; 1092 } else { 1093 // key differs 1094 status = MESH_FOUNDATION_STATUS_KEY_INDEX_ALREADY_STORED; 1095 } 1096 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, status); 1097 mesh_access_message_processed(pdu); 1098 return; 1099 } 1100 1101 // create app key (first get free slot in transport key table) 1102 mesh_transport_key_t * app_key = NULL; 1103 uint16_t internal_index = mesh_transport_key_get_free_index(); 1104 if (internal_index > 0){ 1105 app_key = btstack_memory_mesh_transport_key_get(); 1106 } 1107 if (app_key == NULL) { 1108 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES); 1109 mesh_access_message_processed(pdu); 1110 return; 1111 } 1112 1113 // store data 1114 app_key->internal_index = internal_index; 1115 app_key->akf = 1; 1116 app_key->appkey_index = appkey_index; 1117 app_key->netkey_index = netkey_index; 1118 app_key->version = 0; 1119 app_key->old_key = 0; 1120 1121 memcpy(app_key->key, appkey, 16); 1122 1123 // calculate AID 1124 access_pdu_in_process = pdu; 1125 mesh_transport_key_calc_aid(&configuration_server_cmac_request, app_key, config_appkey_add_or_update_aid, app_key); 1126 } 1127 1128 static void config_appkey_update_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1129 1130 mesh_access_parser_state_t parser; 1131 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1132 1133 // netkey and appkey index 1134 uint32_t netkey_and_appkey_index = mesh_access_parser_get_u24(&parser); 1135 uint16_t netkey_index = netkey_and_appkey_index & 0xfff; 1136 uint16_t appkey_index = netkey_and_appkey_index >> 12; 1137 1138 // actual key 1139 uint8_t appkey[16]; 1140 mesh_access_parser_get_key(&parser, appkey); 1141 1142 1143 // for PTS testing 1144 // check netkey_index is valid 1145 mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index); 1146 if (network_key == NULL){ 1147 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX); 1148 mesh_access_message_processed(pdu); 1149 return; 1150 } 1151 1152 // check if appkey already exists 1153 mesh_transport_key_t * existing_app_key = mesh_transport_key_get(appkey_index); 1154 if (!existing_app_key) { 1155 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INVALID_APPKEY_INDEX); 1156 mesh_access_message_processed(pdu); 1157 return; 1158 } 1159 1160 if (existing_app_key->netkey_index != netkey_index){ 1161 // already stored but with different netkey 1162 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INVALID_BINDING); 1163 mesh_access_message_processed(pdu); 1164 return; 1165 } 1166 1167 if (memcmp(existing_app_key->key, appkey, 16) == 0){ 1168 // key identical 1169 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_SUCCESS); 1170 mesh_access_message_processed(pdu); 1171 return; 1172 } 1173 1174 // create app key 1175 mesh_transport_key_t * new_app_key = NULL; 1176 uint16_t internal_index = mesh_transport_key_get_free_index(); 1177 if (internal_index > 0){ 1178 new_app_key = btstack_memory_mesh_transport_key_get(); 1179 } 1180 if (new_app_key == NULL) { 1181 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES); 1182 mesh_access_message_processed(pdu); 1183 return; 1184 } 1185 1186 // store data 1187 new_app_key->internal_index = internal_index; 1188 new_app_key->appkey_index = appkey_index; 1189 new_app_key->netkey_index = netkey_index; 1190 new_app_key->key_refresh = 1; 1191 new_app_key->version = (uint8_t)(existing_app_key->version + 1); 1192 memcpy(new_app_key->key, appkey, 16); 1193 1194 // mark old key 1195 existing_app_key->old_key = 1; 1196 1197 // calculate AID 1198 access_pdu_in_process = pdu; 1199 mesh_transport_key_calc_aid(&configuration_server_cmac_request, new_app_key, config_appkey_add_or_update_aid, new_app_key); 1200 } 1201 1202 static void config_appkey_delete_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1203 mesh_access_parser_state_t parser; 1204 mesh_access_parser_init(&parser, (mesh_pdu_t *) pdu); 1205 1206 // netkey and appkey index 1207 uint32_t netkey_and_appkey_index = mesh_access_parser_get_u24(&parser); 1208 uint16_t netkey_index = netkey_and_appkey_index & 0xfff; 1209 uint16_t appkey_index = netkey_and_appkey_index >> 12; 1210 1211 // check netkey_index is valid 1212 mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index); 1213 if (network_key == NULL){ 1214 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX); 1215 mesh_access_message_processed(pdu); 1216 return; 1217 } 1218 1219 // check if appkey already exists 1220 mesh_transport_key_t * transport_key = mesh_transport_key_get(appkey_index); 1221 if (transport_key){ 1222 mesh_configuration_server_delete_appkey(transport_key); 1223 } 1224 1225 config_appkey_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_and_appkey_index, MESH_FOUNDATION_STATUS_SUCCESS); 1226 mesh_access_message_processed(pdu); 1227 } 1228 1229 static void config_appkey_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1230 mesh_access_parser_state_t parser; 1231 mesh_access_parser_init(&parser, (mesh_pdu_t *) pdu); 1232 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 1233 1234 config_appkey_list(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), netkey_index); 1235 mesh_access_message_processed(pdu); 1236 } 1237 1238 // Configuration Model Subscriptions (messages) 1239 1240 static void config_model_subscription_list_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, uint16_t element_address, uint32_t model_identifier, mesh_model_t * target_model){ 1241 UNUSED(mesh_model); 1242 1243 uint16_t opcode; 1244 if (mesh_model_is_bluetooth_sig(model_identifier)){ 1245 opcode = MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_LIST; 1246 } else { 1247 opcode = MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_LIST; 1248 } 1249 1250 mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(opcode); 1251 if (!transport_pdu) return; 1252 1253 // setup segmented message 1254 mesh_access_transport_add_uint8(transport_pdu, status); 1255 mesh_access_transport_add_uint16(transport_pdu, element_address); 1256 mesh_access_transport_add_model_identifier(transport_pdu, model_identifier); 1257 1258 if (target_model != NULL){ 1259 uint16_t i; 1260 for (i = 0; i < MAX_NR_MESH_SUBSCRIPTION_PER_MODEL; i++){ 1261 if (target_model->subscriptions[i] == MESH_ADDRESS_UNSASSIGNED) continue; 1262 if (mesh_network_address_virtual(target_model->subscriptions[i])) continue; 1263 mesh_access_transport_add_uint16(transport_pdu, target_model->subscriptions[i]); 1264 } 1265 } 1266 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1267 } 1268 1269 static void config_model_subscription_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1270 mesh_access_parser_state_t parser; 1271 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1272 1273 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1274 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1275 1276 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1277 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1278 1279 config_model_subscription_list_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, model_identifier, target_model); 1280 mesh_access_message_processed(pdu); 1281 } 1282 1283 static void config_model_subscription_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, uint16_t element_address, uint16_t address, uint32_t model_identifier){ 1284 UNUSED(mesh_model); 1285 1286 // setup message 1287 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_config_model_subscription_status, 1288 status, element_address, address, model_identifier); 1289 if (!transport_pdu) return; 1290 // send as segmented access pdu 1291 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1292 } 1293 1294 static void config_model_subscription_add_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1295 mesh_access_parser_state_t parser; 1296 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1297 1298 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1299 uint16_t address = mesh_access_parser_get_u16(&parser); 1300 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1301 1302 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1303 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1304 1305 if (target_model != NULL){ 1306 if (mesh_network_address_group(address) && !mesh_network_address_all_nodes(address)){ 1307 status = mesh_model_add_subscription(target_model, address); 1308 if (status == MESH_FOUNDATION_STATUS_SUCCESS){ 1309 mesh_model_store_subscriptions(target_model); 1310 } 1311 } else { 1312 status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS; 1313 } 1314 } 1315 1316 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, address, model_identifier); 1317 mesh_access_message_processed(pdu); 1318 } 1319 1320 static void config_model_subscription_virtual_address_add_hash(void *arg){ 1321 mesh_model_t * target_model = (mesh_model_t*) arg; 1322 mesh_model_t * mesh_model = mesh_model_get_configuration_server(); 1323 1324 // add if not exists 1325 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_label_uuid(configuration_server_label_uuid); 1326 if (virtual_address == NULL){ 1327 virtual_address = mesh_virtual_address_register(configuration_server_label_uuid, configuration_server_hash); 1328 } 1329 1330 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1331 uint16_t pseudo_dst = MESH_ADDRESS_UNSASSIGNED; 1332 if (virtual_address == NULL){ 1333 status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 1334 } else { 1335 pseudo_dst = virtual_address->pseudo_dst; 1336 if (!mesh_model_contains_subscription(target_model, pseudo_dst)){ 1337 status = mesh_model_add_subscription(target_model, pseudo_dst); 1338 if (status == MESH_FOUNDATION_STATUS_SUCCESS){ 1339 mesh_virtual_address_increase_refcount(virtual_address); 1340 mesh_model_store_subscriptions(target_model); 1341 } 1342 } 1343 } 1344 1345 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), status, configuration_server_element_address, pseudo_dst, target_model->model_identifier); 1346 mesh_access_message_processed(access_pdu_in_process); 1347 return; 1348 } 1349 1350 static void config_model_subscription_virtual_address_add_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1351 mesh_access_parser_state_t parser; 1352 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1353 1354 // ElementAddress - Address of the element - should be us 1355 configuration_server_element_address = mesh_access_parser_get_u16(&parser); 1356 1357 // store label uuid 1358 mesh_access_parser_get_label_uuid(&parser, configuration_server_label_uuid); 1359 1360 // Model Identifier 1361 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1362 1363 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1364 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(configuration_server_element_address, model_identifier, &status); 1365 1366 if (target_model == NULL){ 1367 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, configuration_server_element_address, MESH_ADDRESS_UNSASSIGNED, model_identifier); 1368 mesh_access_message_processed(pdu); 1369 return; 1370 } 1371 1372 access_pdu_in_process = pdu; 1373 mesh_virtual_address(&configuration_server_cmac_request, configuration_server_label_uuid, &configuration_server_hash, &config_model_subscription_virtual_address_add_hash, target_model); 1374 } 1375 1376 static void config_model_subscription_overwrite_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1377 mesh_access_parser_state_t parser; 1378 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1379 1380 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1381 uint16_t address = mesh_access_parser_get_u16(&parser); 1382 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1383 1384 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1385 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1386 1387 if (target_model != NULL){ 1388 if (mesh_network_address_group(address) && !mesh_network_address_all_nodes(address)){ 1389 mesh_subcription_decrease_virtual_address_ref_count(target_model); 1390 mesh_model_delete_all_subscriptions(mesh_model); 1391 mesh_model_add_subscription(mesh_model, address); 1392 mesh_model_store_subscriptions(target_model); 1393 } else { 1394 status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS; 1395 } 1396 } 1397 1398 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, address, model_identifier); 1399 mesh_access_message_processed(pdu); 1400 } 1401 1402 static void config_model_subscription_virtual_address_overwrite_hash(void *arg){ 1403 mesh_model_t * target_model = (mesh_model_t*) arg; 1404 mesh_model_t * mesh_model = mesh_model_get_configuration_server(); 1405 1406 // add if not exists 1407 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_label_uuid(configuration_server_label_uuid); 1408 if (virtual_address == NULL){ 1409 virtual_address = mesh_virtual_address_register(configuration_server_label_uuid, configuration_server_hash); 1410 } 1411 1412 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1413 uint16_t pseudo_dst = MESH_ADDRESS_UNSASSIGNED; 1414 if (virtual_address == NULL){ 1415 status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 1416 } else { 1417 1418 // increase refcount first to avoid flash delete + add in a row 1419 mesh_virtual_address_increase_refcount(virtual_address); 1420 1421 // decrease ref counts for virtual addresses in subscription 1422 mesh_subcription_decrease_virtual_address_ref_count(target_model); 1423 1424 // clear subscriptions 1425 mesh_model_delete_all_subscriptions(target_model); 1426 1427 // add new subscription (successfull if MAX_NR_MESH_SUBSCRIPTION_PER_MODEL > 0) 1428 pseudo_dst = virtual_address->pseudo_dst; 1429 mesh_model_add_subscription(target_model, pseudo_dst); 1430 1431 mesh_model_store_subscriptions(target_model); 1432 } 1433 1434 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), status, configuration_server_element_address, pseudo_dst, target_model->model_identifier); 1435 mesh_access_message_processed(access_pdu_in_process); 1436 return; 1437 } 1438 1439 static void config_model_subscription_virtual_address_overwrite_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1440 mesh_access_parser_state_t parser; 1441 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1442 1443 // ElementAddress - Address of the element - should be us 1444 configuration_server_element_address = mesh_access_parser_get_u16(&parser); 1445 1446 // store label uuid 1447 mesh_access_parser_get_label_uuid(&parser, configuration_server_label_uuid); 1448 1449 // Model Identifier 1450 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1451 1452 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1453 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(configuration_server_element_address, model_identifier, &status); 1454 1455 if (target_model == NULL){ 1456 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, configuration_server_element_address, MESH_ADDRESS_UNSASSIGNED, model_identifier); 1457 mesh_access_message_processed(pdu); 1458 return; 1459 } 1460 access_pdu_in_process = pdu; 1461 mesh_virtual_address(&configuration_server_cmac_request, configuration_server_label_uuid, &configuration_server_hash, &config_model_subscription_virtual_address_overwrite_hash, target_model); 1462 } 1463 1464 static void config_model_subscription_delete_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1465 mesh_access_parser_state_t parser; 1466 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1467 1468 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1469 uint16_t address = mesh_access_parser_get_u16(&parser); 1470 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1471 1472 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1473 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1474 1475 if (target_model != NULL){ 1476 if (mesh_network_address_group(address) && !mesh_network_address_all_nodes(address)){ 1477 mesh_model_delete_subscription(target_model, address); 1478 mesh_model_store_subscriptions(target_model); 1479 } else { 1480 status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS; 1481 } 1482 } 1483 1484 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, address, model_identifier); 1485 mesh_access_message_processed(pdu); 1486 } 1487 1488 static void config_model_subscription_virtual_address_delete_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1489 mesh_access_parser_state_t parser; 1490 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1491 1492 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1493 mesh_access_parser_get_label_uuid(&parser, configuration_server_label_uuid); 1494 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1495 1496 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_label_uuid(configuration_server_label_uuid); 1497 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1498 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1499 1500 if ((target_model != NULL) && (virtual_address != NULL) && mesh_model_contains_subscription(target_model, virtual_address->pseudo_dst)){ 1501 mesh_virtual_address_decrease_refcount(virtual_address); 1502 mesh_model_delete_subscription(target_model, virtual_address->pseudo_dst); 1503 mesh_model_store_subscriptions(target_model); 1504 } 1505 1506 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, virtual_address->hash, model_identifier); 1507 mesh_access_message_processed(pdu); 1508 } 1509 1510 static void config_model_subscription_delete_all_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 1511 mesh_access_parser_state_t parser; 1512 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1513 1514 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1515 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1516 1517 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1518 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1519 1520 if (target_model != NULL){ 1521 mesh_subcription_decrease_virtual_address_ref_count(target_model); 1522 mesh_model_delete_all_subscriptions(target_model); 1523 mesh_model_store_subscriptions(target_model); 1524 } 1525 1526 config_model_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, MESH_ADDRESS_UNSASSIGNED, model_identifier); 1527 mesh_access_message_processed(pdu); 1528 } 1529 1530 // Configuration Model to AppKey List 1531 1532 static void config_model_app_status(mesh_model_t * mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, uint16_t element_address, uint16_t appkey_index, uint32_t model_identifier){ 1533 UNUSED(mesh_model); 1534 1535 // setup message 1536 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_config_model_app_status, 1537 status, element_address, appkey_index, model_identifier); 1538 if (!transport_pdu) return; 1539 1540 // send as segmented access pdu 1541 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1542 } 1543 1544 static void config_model_app_list(mesh_model_t * config_server_model, uint16_t netkey_index, uint16_t dest, uint8_t status, uint16_t element_address, uint32_t model_identifier, mesh_model_t * mesh_model){ 1545 UNUSED(config_server_model); 1546 1547 uint16_t opcode; 1548 if (mesh_model_is_bluetooth_sig(model_identifier)){ 1549 opcode = MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_LIST; 1550 } else { 1551 opcode = MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_LIST; 1552 } 1553 mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(opcode); 1554 if (!transport_pdu) return; 1555 1556 mesh_access_transport_add_uint8(transport_pdu, status); 1557 mesh_access_transport_add_uint16(transport_pdu, element_address); 1558 if (mesh_model_is_bluetooth_sig(model_identifier)) { 1559 mesh_access_transport_add_uint16(transport_pdu, mesh_model_get_model_id(model_identifier)); 1560 } else { 1561 mesh_access_transport_add_uint32(transport_pdu, model_identifier); 1562 } 1563 1564 // add list of appkey indexes 1565 if (mesh_model){ 1566 uint16_t i; 1567 for (i=0;i<MAX_NR_MESH_APPKEYS_PER_MODEL;i++){ 1568 uint16_t appkey_index = mesh_model->appkey_indices[i]; 1569 if (appkey_index == MESH_APPKEY_INVALID) continue; 1570 mesh_access_transport_add_uint16(transport_pdu, appkey_index); 1571 } 1572 } 1573 1574 // send as segmented access pdu 1575 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1576 } 1577 1578 static void config_model_app_bind_handler(mesh_model_t *config_server_model, mesh_pdu_t * pdu) { 1579 mesh_access_parser_state_t parser; 1580 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1581 1582 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1583 uint16_t appkey_index = mesh_access_parser_get_u16(&parser); 1584 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1585 1586 uint8_t status; 1587 do { 1588 // validate address and look up model 1589 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1590 if (target_model == NULL) break; 1591 1592 // validate app key exists 1593 mesh_transport_key_t * app_key = mesh_transport_key_get(appkey_index); 1594 if (!app_key){ 1595 status = MESH_FOUNDATION_STATUS_INVALID_APPKEY_INDEX; 1596 break; 1597 } 1598 1599 // Configuration Server only allows device keys 1600 if (mesh_model_is_configuration_server(model_identifier)){ 1601 status = MESH_FOUNDATION_STATUS_CANNOT_BIND; 1602 break; 1603 } 1604 status = mesh_model_bind_appkey(target_model, appkey_index); 1605 1606 } while (0); 1607 1608 config_model_app_status(config_server_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, appkey_index, model_identifier); 1609 mesh_access_message_processed(pdu); 1610 } 1611 1612 static void config_model_app_unbind_handler(mesh_model_t *config_server_model, mesh_pdu_t * pdu) { 1613 mesh_access_parser_state_t parser; 1614 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1615 1616 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1617 uint16_t appkey_index = mesh_access_parser_get_u16(&parser); 1618 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1619 1620 uint8_t status; 1621 do { 1622 // validate address and look up model 1623 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1624 if (target_model == NULL) break; 1625 1626 // validate app key exists 1627 mesh_transport_key_t * app_key = mesh_transport_key_get(appkey_index); 1628 if (!app_key){ 1629 status = MESH_FOUNDATION_STATUS_INVALID_APPKEY_INDEX; 1630 break; 1631 } 1632 mesh_model_unbind_appkey(target_model, appkey_index); 1633 status = MESH_FOUNDATION_STATUS_SUCCESS; 1634 } while (0); 1635 1636 config_model_app_status(config_server_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, appkey_index, model_identifier); 1637 mesh_access_message_processed(pdu); 1638 } 1639 1640 static void config_model_app_get_handler(mesh_model_t *config_server_model, mesh_pdu_t * pdu){ 1641 mesh_access_parser_state_t parser; 1642 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1643 1644 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1645 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1646 1647 uint8_t status; 1648 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1649 config_model_app_list(config_server_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, model_identifier, target_model); 1650 mesh_access_message_processed(pdu); 1651 } 1652 1653 // Model Publication 1654 1655 static void config_model_publication_changed(mesh_model_t *mesh_model, mesh_publication_model_t * new_publication_model){ 1656 1657 // stop publication 1658 mesh_model_publication_stop(mesh_model); 1659 1660 // update model publication state 1661 memcpy(mesh_model->publication_model, &configuration_server_publication_model, sizeof(mesh_publication_model_t)); 1662 1663 // store 1664 mesh_model_store_publication(mesh_model); 1665 1666 // start publication if address is set (nothing happens if period = 0 and retransmit = 0) 1667 if (new_publication_model->address == MESH_ADDRESS_UNSASSIGNED) return; 1668 1669 // start to publish 1670 mesh_model_publication_start(mesh_model); 1671 } 1672 1673 1674 static void 1675 config_model_publication_status(mesh_model_t *mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, 1676 uint16_t element_address, uint32_t model_identifier, mesh_publication_model_t *publication_model) { 1677 UNUSED(mesh_model); 1678 1679 // setup message 1680 uint16_t app_key_index_and_credential_flag = (publication_model->friendship_credential_flag << 12) | publication_model->appkey_index; 1681 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 1682 &mesh_foundation_config_model_app_status, status, element_address, publication_model->address, 1683 app_key_index_and_credential_flag, 1684 publication_model->ttl, publication_model->period, publication_model->retransmit, model_identifier); 1685 if (!transport_pdu) return; 1686 1687 // send as segmented access pdu 1688 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1689 } 1690 1691 static void 1692 config_model_publication_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1693 1694 // set defaults 1695 memset(&configuration_server_publication_model, 0, sizeof(mesh_publication_model_t)); 1696 1697 mesh_access_parser_state_t parser; 1698 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1699 1700 // ElementAddress - Address of the element - should be us 1701 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1702 1703 // PublishAddress, 16 bit 1704 configuration_server_publication_model.address = mesh_access_parser_get_u16(&parser); 1705 1706 // AppKeyIndex (12), CredentialFlag (1), RFU (3) 1707 uint16_t temp = mesh_access_parser_get_u16(&parser); 1708 configuration_server_publication_model.appkey_index = temp & 0x0fff; 1709 configuration_server_publication_model.friendship_credential_flag = (temp >> 12) & 1; 1710 1711 // TTL 1712 configuration_server_publication_model.ttl = mesh_access_parser_get_u8(&parser); 1713 1714 // Period 1715 configuration_server_publication_model.period = mesh_access_parser_get_u8(&parser); 1716 1717 // Retransmit 1718 configuration_server_publication_model.retransmit = mesh_access_parser_get_u8(&parser); 1719 1720 // Model Identifier 1721 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1722 uint8_t status; 1723 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1724 1725 // TODO validate params 1726 1727 if (target_model){ 1728 if (target_model->publication_model == NULL){ 1729 status = MESH_FOUNDATION_STATUS_CANNOT_SET; 1730 } else { 1731 1732 // decrease ref count if old virtual address 1733 if (mesh_network_address_virtual(configuration_server_publication_model.address)) { 1734 mesh_virtual_address_t * current_virtual_address = mesh_virtual_address_for_pseudo_dst(configuration_server_publication_model.address); 1735 mesh_virtual_address_decrease_refcount(current_virtual_address); 1736 } 1737 1738 // restart publication 1739 config_model_publication_changed(target_model, &configuration_server_publication_model); 1740 } 1741 } 1742 1743 // send status 1744 config_model_publication_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, element_address, model_identifier, &configuration_server_publication_model); 1745 mesh_access_message_processed(pdu); 1746 } 1747 1748 static void config_model_publication_virtual_address_set_hash(void *arg){ 1749 mesh_model_t *mesh_model = (mesh_model_t*) arg; 1750 1751 // add if not exist 1752 mesh_virtual_address_t * virtual_address = mesh_virtual_address_for_label_uuid(configuration_server_label_uuid); 1753 if (virtual_address == NULL){ 1754 virtual_address = mesh_virtual_address_register(configuration_server_label_uuid, configuration_server_hash); 1755 } 1756 1757 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1758 if (virtual_address == NULL){ 1759 status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES; 1760 } else { 1761 1762 // increase ref count if new virtual address 1763 mesh_virtual_address_increase_refcount(virtual_address); 1764 1765 // decrease ref count if old virtual address 1766 if (mesh_network_address_virtual(configuration_server_publication_model.address)) { 1767 mesh_virtual_address_t * current_virtual_address = mesh_virtual_address_for_pseudo_dst(configuration_server_publication_model.address); 1768 mesh_virtual_address_decrease_refcount(current_virtual_address); 1769 } 1770 1771 configuration_server_publication_model.address = virtual_address->pseudo_dst; 1772 mesh_virtual_address_increase_refcount(virtual_address); 1773 1774 // restart publication 1775 config_model_publication_changed(configuration_server_target_model, &configuration_server_publication_model); 1776 } 1777 1778 // send status 1779 config_model_publication_status(mesh_model, mesh_pdu_netkey_index(access_pdu_in_process), mesh_pdu_src(access_pdu_in_process), status, configuration_server_element_address, configuration_server_model_identifier, &configuration_server_publication_model); 1780 1781 mesh_access_message_processed(access_pdu_in_process); 1782 } 1783 1784 static void 1785 config_model_publication_virtual_address_set_handler(mesh_model_t *mesh_model, 1786 mesh_pdu_t * pdu) { 1787 1788 // set defaults 1789 memset(&configuration_server_publication_model, 0, sizeof(mesh_publication_model_t)); 1790 1791 mesh_access_parser_state_t parser; 1792 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1793 1794 // ElementAddress - Address of the element 1795 configuration_server_element_address = mesh_access_parser_get_u16(&parser); 1796 1797 // store label uuid 1798 mesh_access_parser_get_label_uuid(&parser, configuration_server_label_uuid); 1799 1800 // AppKeyIndex (12), CredentialFlag (1), RFU (3) 1801 uint16_t temp = mesh_access_parser_get_u16(&parser); 1802 configuration_server_publication_model.appkey_index = temp & 0x0fff; 1803 configuration_server_publication_model.friendship_credential_flag = (temp >> 12) & 1; 1804 configuration_server_publication_model.ttl = mesh_access_parser_get_u8(&parser); 1805 configuration_server_publication_model.period = mesh_access_parser_get_u8(&parser); 1806 configuration_server_publication_model.retransmit = mesh_access_parser_get_u8(&parser); 1807 1808 // Model Identifier 1809 configuration_server_model_identifier = mesh_access_parser_get_model_identifier(&parser); 1810 1811 uint8_t status; 1812 configuration_server_target_model = mesh_access_model_for_address_and_model_identifier(configuration_server_element_address, configuration_server_model_identifier, &status); 1813 1814 // model exists, but no publication model 1815 if (configuration_server_target_model != NULL && configuration_server_target_model->publication_model == NULL){ 1816 status = MESH_FOUNDATION_STATUS_CANNOT_SET; 1817 } 1818 1819 // on error, no need to calculate virtual address hash 1820 if (status != MESH_FOUNDATION_STATUS_SUCCESS){ 1821 config_model_publication_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, configuration_server_element_address, configuration_server_model_identifier, &configuration_server_publication_model); 1822 mesh_access_message_processed(pdu); 1823 return; 1824 } 1825 1826 access_pdu_in_process = pdu; 1827 mesh_virtual_address(&configuration_server_cmac_request, configuration_server_label_uuid, &configuration_server_publication_model.address, &config_model_publication_virtual_address_set_hash, mesh_model); 1828 } 1829 1830 static void 1831 config_model_publication_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1832 1833 1834 mesh_access_parser_state_t parser; 1835 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1836 1837 // ElementAddress - Address of the element - should be us 1838 uint16_t element_address = mesh_access_parser_get_u16(&parser); 1839 1840 // Model Identifier 1841 uint32_t model_identifier = mesh_access_parser_get_model_identifier(&parser); 1842 1843 uint8_t status; 1844 mesh_model_t * target_model = mesh_access_model_for_address_and_model_identifier(element_address, model_identifier, &status); 1845 1846 mesh_publication_model_t * publication_model; 1847 1848 if (target_model == NULL){ 1849 // use defaults 1850 memset(&configuration_server_publication_model, 0, sizeof(mesh_publication_model_t)); 1851 publication_model = &configuration_server_publication_model; 1852 } else { 1853 publication_model = target_model->publication_model; 1854 } 1855 1856 config_model_publication_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, configuration_server_element_address, model_identifier, publication_model); 1857 mesh_access_message_processed(pdu); 1858 } 1859 1860 // Heartbeat Publication 1861 1862 static void config_heartbeat_publication_emit(mesh_heartbeat_publication_t * mesh_heartbeat_publication){ 1863 1864 printf("CONFIG_SERVER_HEARTBEAT: Emit (dest %04x, count %u, period %u ms)\n", 1865 mesh_heartbeat_publication->destination, 1866 mesh_heartbeat_publication->count, 1867 mesh_heartbeat_publication->period_ms); 1868 1869 // active features 1870 mesh_heartbeat_publication->active_features = mesh_foundation_get_features(); 1871 1872 mesh_network_pdu_t * network_pdu = mesh_network_pdu_get(); 1873 if (network_pdu){ 1874 uint8_t data[3]; 1875 data[0] = mesh_heartbeat_publication->ttl; 1876 big_endian_store_16(data, 1, mesh_heartbeat_publication->active_features); 1877 mesh_upper_transport_setup_control_pdu((mesh_pdu_t *) network_pdu, mesh_heartbeat_publication->netkey_index, 1878 mesh_heartbeat_publication->ttl, mesh_node_get_primary_element_address(), mesh_heartbeat_publication->destination, 1879 MESH_TRANSPORT_OPCODE_HEARTBEAT, data, sizeof(data)); 1880 mesh_upper_transport_send_control_pdu((mesh_pdu_t *) network_pdu); 1881 } 1882 1883 // forever 1884 if (mesh_heartbeat_publication->count < 0xffffu) { 1885 mesh_heartbeat_publication->count--; 1886 } 1887 } 1888 void mesh_configuration_server_feature_changed(void){ 1889 mesh_model_t * mesh_model = mesh_model_get_configuration_server(); 1890 mesh_heartbeat_publication_t * mesh_heartbeat_publication = &((mesh_configuration_server_model_context_t*) mesh_model->model_data)->heartbeat_publication; 1891 1892 // active features 1893 uint16_t active_features = mesh_foundation_get_features(); 1894 if (mesh_heartbeat_publication->active_features == active_features) return; 1895 config_heartbeat_publication_emit(mesh_heartbeat_publication); 1896 } 1897 1898 static void config_heartbeat_publication_timeout_handler(btstack_timer_source_t * ts){ 1899 1900 mesh_heartbeat_publication_t * mesh_heartbeat_publication = (mesh_heartbeat_publication_t*) ts; 1901 1902 // emit beat 1903 config_heartbeat_publication_emit(mesh_heartbeat_publication); 1904 1905 // all sent? 1906 if (mesh_heartbeat_publication->count == 0) return; 1907 1908 // periodic publication? 1909 if (mesh_heartbeat_publication->period_ms == 0) return; 1910 1911 btstack_run_loop_set_timer(ts, mesh_heartbeat_publication->period_ms); 1912 btstack_run_loop_add_timer(ts); 1913 } 1914 1915 static void config_heartbeat_publication_status(mesh_model_t *mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, mesh_heartbeat_publication_t * mesh_heartbeat_publication){ 1916 UNUSED(mesh_model); 1917 1918 // setup message 1919 uint8_t count_log = heartbeat_count_log(mesh_heartbeat_publication->count); 1920 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 1921 &mesh_foundation_config_heartbeat_publication_status, 1922 status, 1923 mesh_heartbeat_publication->destination, 1924 count_log, 1925 mesh_heartbeat_publication->period_log, 1926 mesh_heartbeat_publication->ttl, 1927 mesh_heartbeat_publication->features, 1928 mesh_heartbeat_publication->netkey_index); 1929 if (!transport_pdu) return; 1930 printf("MESH config_heartbeat_publication_status count = %u => count_log = %u\n", mesh_heartbeat_publication->count, count_log); 1931 1932 // send as segmented access pdu 1933 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 1934 } 1935 1936 static void config_heartbeat_publication_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1937 1938 mesh_heartbeat_publication_t requested_publication; 1939 1940 mesh_access_parser_state_t parser; 1941 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 1942 1943 // Destination address for Heartbeat messages 1944 requested_publication.destination = mesh_access_parser_get_u16(&parser); 1945 // Number of Heartbeat messages to be sent 1946 requested_publication.count = heartbeat_pwr2(mesh_access_parser_get_u8(&parser)); 1947 // Period for sending Heartbeat messages 1948 requested_publication.period_log = mesh_access_parser_get_u8(&parser); 1949 // TTL to be used when sending Heartbeat messages 1950 requested_publication.ttl = mesh_access_parser_get_u8(&parser); 1951 // Bit field indicating features that trigger Heartbeat messages when changed 1952 requested_publication.features = mesh_access_parser_get_u16(&parser) & MESH_HEARTBEAT_FEATURES_SUPPORTED_MASK; 1953 // NetKey Index 1954 requested_publication.netkey_index = mesh_access_parser_get_u16(&parser); 1955 1956 // store period as ms 1957 requested_publication.period_ms = heartbeat_pwr2(requested_publication.period_log) * 1000; 1958 1959 mesh_heartbeat_publication_t * mesh_heartbeat_publication = &((mesh_configuration_server_model_context_t*) mesh_model->model_data)->heartbeat_publication; 1960 1961 // validate fields 1962 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 1963 mesh_network_key_t * network_key = mesh_network_key_list_get(requested_publication.netkey_index); 1964 if (network_key == NULL){ 1965 status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX; 1966 } else { 1967 printf("MESH config_heartbeat_publication_set, destination %x, count = %x, period = %u s\n", 1968 requested_publication.destination, requested_publication.count, requested_publication.period_ms); 1969 1970 // accept update 1971 memcpy(mesh_heartbeat_publication, &requested_publication, sizeof(mesh_heartbeat_publication_t)); 1972 } 1973 1974 config_heartbeat_publication_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, mesh_heartbeat_publication); 1975 1976 mesh_access_message_processed(pdu); 1977 1978 if (status != MESH_FOUNDATION_STATUS_SUCCESS) return; 1979 1980 // check if heartbeats should be disabled 1981 if (mesh_heartbeat_publication->destination == MESH_ADDRESS_UNSASSIGNED || mesh_heartbeat_publication->period_log == 0) { 1982 btstack_run_loop_remove_timer(&mesh_heartbeat_publication->timer); 1983 printf("MESH config_heartbeat_publication_set, disable\n"); 1984 return; 1985 } 1986 1987 // NOTE: defer first heartbeat to allow config status getting sent first 1988 btstack_run_loop_set_timer_handler(&mesh_heartbeat_publication->timer, config_heartbeat_publication_timeout_handler); 1989 btstack_run_loop_set_timer_context(&mesh_heartbeat_publication->timer, mesh_heartbeat_publication); 1990 btstack_run_loop_set_timer(&mesh_heartbeat_publication->timer, 2000); 1991 btstack_run_loop_add_timer(&mesh_heartbeat_publication->timer); 1992 } 1993 1994 static void config_heartbeat_publication_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 1995 mesh_heartbeat_publication_t * mesh_heartbeat_publication = &((mesh_configuration_server_model_context_t*) mesh_model->model_data)->heartbeat_publication; 1996 config_heartbeat_publication_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), MESH_FOUNDATION_STATUS_SUCCESS, mesh_heartbeat_publication); 1997 mesh_access_message_processed(pdu); 1998 } 1999 2000 // Heartbeat Subscription 2001 2002 static void config_heartbeat_subscription_status(mesh_model_t *mesh_model, uint16_t netkey_index, uint16_t dest, uint8_t status, mesh_heartbeat_subscription_t * mesh_heartbeat_subscription){ 2003 UNUSED(mesh_model); 2004 2005 // setup message 2006 uint8_t count_log = heartbeat_count_log(mesh_heartbeat_subscription->count_log); 2007 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 2008 &mesh_foundation_config_heartbeat_subscription_status, 2009 status, 2010 mesh_heartbeat_subscription->source, 2011 mesh_heartbeat_subscription->destination, 2012 mesh_heartbeat_subscription->period_log, 2013 count_log, 2014 mesh_heartbeat_subscription->min_hops, 2015 mesh_heartbeat_subscription->max_hops); 2016 if (!transport_pdu) return; 2017 printf("MESH config_heartbeat_subscription_status count = %u => count_log = %u\n", mesh_heartbeat_subscription->count_log, count_log); 2018 2019 // send as segmented access pdu 2020 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 2021 } 2022 static int config_heartbeat_subscription_enabled(mesh_heartbeat_subscription_t * mesh_heartbeat_subscription){ 2023 return mesh_network_address_unicast(mesh_heartbeat_subscription->source) && mesh_heartbeat_subscription->period_log > 0 && 2024 (mesh_network_address_unicast(mesh_heartbeat_subscription->destination) || mesh_network_address_group(mesh_heartbeat_subscription->destination)); 2025 } 2026 2027 static void config_heartbeat_subscription_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 2028 mesh_access_parser_state_t parser; 2029 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 2030 2031 mesh_heartbeat_subscription_t requested_subscription; 2032 2033 // Destination address for Heartbeat messages 2034 requested_subscription.source = mesh_access_parser_get_u16(&parser); 2035 // Destination address for Heartbeat messages 2036 requested_subscription.destination = mesh_access_parser_get_u16(&parser); 2037 // Period for sending Heartbeat messages 2038 requested_subscription.period_log = mesh_access_parser_get_u8(&parser); 2039 2040 uint8_t status = MESH_FOUNDATION_STATUS_SUCCESS; 2041 if (requested_subscription.period_log > 0x11u){ 2042 status = MESH_FOUNDATION_STATUS_CANNOT_SET; 2043 } else if ((requested_subscription.source != MESH_ADDRESS_UNSASSIGNED) && 2044 !mesh_network_address_unicast(requested_subscription.source)){ 2045 status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS; 2046 } else if ((requested_subscription.destination != MESH_ADDRESS_UNSASSIGNED) && 2047 !mesh_network_address_unicast(requested_subscription.destination) && 2048 !mesh_network_address_group(requested_subscription.destination)){ 2049 status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS; 2050 } 2051 2052 if (status != MESH_FOUNDATION_STATUS_SUCCESS){ 2053 config_heartbeat_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, &requested_subscription); 2054 mesh_access_message_processed(pdu); 2055 return; 2056 } 2057 2058 mesh_heartbeat_subscription_t * mesh_heartbeat_subscription = &((mesh_configuration_server_model_context_t*) mesh_model->model_data)->heartbeat_subscription; 2059 2060 if (config_heartbeat_subscription_enabled(mesh_heartbeat_subscription)){ 2061 requested_subscription.count_log = 0u; 2062 requested_subscription.min_hops = 0x7Fu; 2063 requested_subscription.max_hops = 0u; 2064 } else { 2065 requested_subscription.source = MESH_ADDRESS_UNSASSIGNED; 2066 requested_subscription.destination = MESH_ADDRESS_UNSASSIGNED; 2067 requested_subscription.period_log = 0u; 2068 requested_subscription.count_log = 0u; 2069 requested_subscription.min_hops = 0u; 2070 requested_subscription.max_hops = 0u; 2071 } 2072 2073 // accept request 2074 memcpy(mesh_heartbeat_subscription, &requested_subscription, sizeof(mesh_heartbeat_subscription_t)); 2075 2076 printf("MESH config_heartbeat_subscription_set, destination %x, count = %x, period = %u s\n", 2077 mesh_heartbeat_subscription->destination, mesh_heartbeat_subscription->count_log, heartbeat_pwr2(mesh_heartbeat_subscription->period_log)); 2078 2079 config_heartbeat_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, mesh_heartbeat_subscription); 2080 mesh_access_message_processed(pdu); 2081 } 2082 2083 2084 static void config_heartbeat_subscription_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu) { 2085 mesh_heartbeat_subscription_t * mesh_heartbeat_subscription = &((mesh_configuration_server_model_context_t*) mesh_model->model_data)->heartbeat_subscription; 2086 config_heartbeat_subscription_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), MESH_FOUNDATION_STATUS_SUCCESS, mesh_heartbeat_subscription); 2087 mesh_access_message_processed(pdu); 2088 } 2089 2090 // KeyRefresh Phase 2091 2092 static void config_key_refresh_phase_status(mesh_model_t *mesh_model, uint16_t netkey_index_dest, uint16_t dest, uint8_t status, uint16_t netkey_index, 2093 mesh_key_refresh_state_t key_refresh_state){ 2094 UNUSED(mesh_model); 2095 2096 // setup message 2097 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 2098 &mesh_key_refresh_phase_status, 2099 status, 2100 netkey_index, 2101 key_refresh_state); 2102 if (!transport_pdu) return; 2103 2104 // send as segmented access pdu 2105 config_server_send_message(netkey_index_dest, dest, (mesh_pdu_t *) transport_pdu); 2106 } 2107 2108 static void config_key_refresh_phase_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 2109 mesh_access_parser_state_t parser; 2110 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 2111 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 2112 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index); 2113 2114 uint8_t status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX; 2115 mesh_key_refresh_state_t key_refresh_state = MESH_KEY_REFRESH_NOT_ACTIVE; 2116 2117 if (subnet != NULL){ 2118 status = MESH_FOUNDATION_STATUS_SUCCESS; 2119 key_refresh_state = subnet->key_refresh; 2120 } 2121 2122 config_key_refresh_phase_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, key_refresh_state); 2123 mesh_access_message_processed(pdu); 2124 } 2125 2126 static void config_key_refresh_phase_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 2127 mesh_access_parser_state_t parser; 2128 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 2129 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 2130 uint8_t key_refresh_phase_transition = mesh_access_parser_get_u8(&parser); 2131 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index); 2132 2133 uint8_t status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX; 2134 2135 if (subnet != NULL){ 2136 status = MESH_FOUNDATION_STATUS_SUCCESS; 2137 2138 switch (key_refresh_phase_transition){ 2139 case 0x02: 2140 switch (subnet->key_refresh){ 2141 case MESH_KEY_REFRESH_FIRST_PHASE: 2142 case MESH_KEY_REFRESH_SECOND_PHASE: 2143 subnet->key_refresh = MESH_KEY_REFRESH_SECOND_PHASE; 2144 break; 2145 default: 2146 break; 2147 } 2148 break; 2149 case 0x03: 2150 switch (subnet->key_refresh){ 2151 case MESH_KEY_REFRESH_FIRST_PHASE: 2152 case MESH_KEY_REFRESH_SECOND_PHASE: 2153 // key refresh phase 3 entered 2154 mesh_access_key_refresh_revoke_keys(subnet); 2155 subnet->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE; 2156 break; 2157 default: 2158 break; 2159 } 2160 break; 2161 default: 2162 status = MESH_FOUNDATION_STATUS_CANNOT_SET; 2163 break; 2164 } 2165 } 2166 2167 config_key_refresh_phase_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, subnet->key_refresh); 2168 mesh_access_message_processed(pdu); 2169 } 2170 2171 2172 static void config_node_reset_status(mesh_model_t *mesh_model, uint16_t netkey_index, uint16_t dest){ 2173 UNUSED(mesh_model); 2174 2175 // setup message 2176 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_node_reset_status); 2177 if (!transport_pdu) return; 2178 2179 // send as segmented access pdu 2180 config_server_send_message(netkey_index, dest, (mesh_pdu_t *) transport_pdu); 2181 } 2182 2183 static void config_node_reset_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 2184 mesh_node_reset(); 2185 config_node_reset_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu)); 2186 mesh_access_message_processed(pdu); 2187 } 2188 2189 static void low_power_node_poll_timeout_status(mesh_model_t *mesh_model, uint16_t netkey_index_dest, uint16_t dest, uint8_t status){ 2190 UNUSED(mesh_model); 2191 2192 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 2193 &mesh_foundation_low_power_node_poll_timeout_status, 2194 status, 2195 0, // The unicast address of the Low Power node 2196 0); // The current value of the PollTimeout timer of the Low Power node 2197 if (!transport_pdu) return; 2198 printf("TODO: send unicast address of the Low Power node and the current value of the PollTimeout timer, instead of 0s\n"); 2199 // send as segmented access pdu 2200 config_server_send_message(netkey_index_dest, dest, (mesh_pdu_t *) transport_pdu); 2201 } 2202 2203 static void config_low_power_node_poll_timeout_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 2204 mesh_access_parser_state_t parser; 2205 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 2206 printf("TODO: implement get the current value of PollTimeout timer of the Low Power node within a Friend node\n"); 2207 low_power_node_poll_timeout_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), MESH_FOUNDATION_STATUS_SUCCESS); 2208 mesh_access_message_processed(pdu); 2209 } 2210 2211 static void config_node_identity_status(mesh_model_t *mesh_model, uint16_t netkey_index_dest, uint16_t dest, uint8_t status, uint16_t netkey_index, 2212 mesh_node_identity_state_t node_identity_state){ 2213 UNUSED(mesh_model); 2214 2215 // setup message 2216 mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message( 2217 &mesh_foundation_node_identity_status, 2218 status, 2219 netkey_index, 2220 node_identity_state); 2221 if (!transport_pdu) return; 2222 2223 // send as segmented access pdu 2224 config_server_send_message(netkey_index_dest, dest, (mesh_pdu_t *) transport_pdu); 2225 } 2226 2227 static void config_node_identity_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 2228 mesh_access_parser_state_t parser; 2229 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 2230 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 2231 2232 mesh_node_identity_state_t node_identity_state = MESH_NODE_IDENTITY_STATE_ADVERTISING_NOT_SUPPORTED; 2233 uint8_t status = mesh_proxy_get_advertising_with_node_id_status(netkey_index, &node_identity_state); 2234 2235 config_node_identity_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, node_identity_state); 2236 mesh_access_message_processed(pdu); 2237 } 2238 2239 static void config_node_identity_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ 2240 mesh_access_parser_state_t parser; 2241 mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); 2242 uint16_t netkey_index = mesh_access_parser_get_u16(&parser); 2243 mesh_node_identity_state_t node_identity_state = (mesh_node_identity_state_t) mesh_access_parser_get_u8(&parser); 2244 2245 uint8_t status = mesh_proxy_set_advertising_with_node_id(netkey_index, node_identity_state); 2246 2247 config_node_identity_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, node_identity_state); 2248 mesh_access_message_processed(pdu); 2249 } 2250 2251 // 2252 2253 const static mesh_operation_t mesh_configuration_server_model_operations[] = { 2254 { MESH_FOUNDATION_OPERATION_APPKEY_ADD, 19, config_appkey_add_handler }, 2255 { MESH_FOUNDATION_OPERATION_APPKEY_DELETE, 3, config_appkey_delete_handler }, 2256 { MESH_FOUNDATION_OPERATION_APPKEY_GET, 2, config_appkey_get_handler }, 2257 { MESH_FOUNDATION_OPERATION_APPKEY_UPDATE, 19, config_appkey_update_handler }, 2258 { MESH_FOUNDATION_OPERATION_NETKEY_ADD, 18, config_netkey_add_handler }, 2259 { MESH_FOUNDATION_OPERATION_NETKEY_UPDATE, 18, config_netkey_update_handler }, 2260 { MESH_FOUNDATION_OPERATION_NETKEY_DELETE, 2, config_netkey_delete_handler }, 2261 { MESH_FOUNDATION_OPERATION_NETKEY_GET, 0, config_netkey_get_handler }, 2262 { MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_GET, 1, config_composition_data_get_handler }, 2263 { MESH_FOUNDATION_OPERATION_BEACON_GET, 0, config_beacon_get_handler }, 2264 { MESH_FOUNDATION_OPERATION_BEACON_SET, 1, config_beacon_set_handler }, 2265 { MESH_FOUNDATION_OPERATION_DEFAULT_TTL_GET, 0, config_default_ttl_get_handler }, 2266 { MESH_FOUNDATION_OPERATION_DEFAULT_TTL_SET, 1, config_default_ttl_set_handler }, 2267 { MESH_FOUNDATION_OPERATION_FRIEND_GET, 0, config_friend_get_handler }, 2268 { MESH_FOUNDATION_OPERATION_FRIEND_SET, 1, config_friend_set_handler }, 2269 { MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_GET, 0, config_model_network_transmit_get_handler }, 2270 { MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_SET, 1, config_model_network_transmit_set_handler }, 2271 { MESH_FOUNDATION_OPERATION_GATT_PROXY_GET, 0, config_gatt_proxy_get_handler }, 2272 { MESH_FOUNDATION_OPERATION_GATT_PROXY_SET, 1, config_gatt_proxy_set_handler }, 2273 { MESH_FOUNDATION_OPERATION_RELAY_GET, 0, config_relay_get_handler }, 2274 { MESH_FOUNDATION_OPERATION_RELAY_SET, 1, config_relay_set_handler }, 2275 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_ADD, 6, config_model_subscription_add_handler }, 2276 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_ADD, 20, config_model_subscription_virtual_address_add_handler }, 2277 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_DELETE, 6, config_model_subscription_delete_handler }, 2278 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_DELETE, 20, config_model_subscription_virtual_address_delete_handler }, 2279 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_OVERWRITE, 6, config_model_subscription_overwrite_handler }, 2280 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_OVERWRITE,20, config_model_subscription_virtual_address_overwrite_handler }, 2281 { MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_DELETE_ALL, 4, config_model_subscription_delete_all_handler }, 2282 { MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_GET, 4, config_model_subscription_get_handler }, 2283 { MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_GET, 6, config_model_subscription_get_handler }, 2284 { MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_GET, 4, config_model_app_get_handler }, 2285 { MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_GET, 6, config_model_app_get_handler }, 2286 { MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_SET, 11, config_model_publication_set_handler }, 2287 { MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_VIRTUAL_ADDRESS_SET, 25, config_model_publication_virtual_address_set_handler }, 2288 { MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_GET, 4, config_model_publication_get_handler }, 2289 { MESH_FOUNDATION_OPERATION_MODEL_APP_BIND, 6, config_model_app_bind_handler }, 2290 { MESH_FOUNDATION_OPERATION_MODEL_APP_UNBIND, 6, config_model_app_unbind_handler }, 2291 { MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_GET, 0, config_heartbeat_publication_get_handler }, 2292 { MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_SET, 9, config_heartbeat_publication_set_handler }, 2293 { MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_GET, 0, config_heartbeat_subscription_get_handler}, 2294 { MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_SET, 5, config_heartbeat_subscription_set_handler}, 2295 { MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_GET, 2, config_key_refresh_phase_get_handler }, 2296 { MESH_FOUNDATION_OPERATION_KEY_REFRESH_PHASE_SET, 3, config_key_refresh_phase_set_handler }, 2297 { MESH_FOUNDATION_OPERATION_NODE_RESET, 0, config_node_reset_handler }, 2298 { MESH_FOUNDATION_OPERATION_LOW_POWER_NODE_POLL_TIMEOUT_GET, 2, config_low_power_node_poll_timeout_get_handler }, 2299 { MESH_FOUNDATION_OPERATION_NODE_IDENTITY_GET, 2, config_node_identity_get_handler }, 2300 { MESH_FOUNDATION_OPERATION_NODE_IDENTITY_SET, 3, config_node_identity_set_handler }, 2301 { 0, 0, NULL } 2302 }; 2303 2304 const mesh_operation_t * mesh_configuration_server_get_operations(void){ 2305 return mesh_configuration_server_model_operations; 2306 } 2307 2308 static uint32_t mesh_tag_for_prov_data(void){ 2309 return ((uint32_t) 'P' << 24) | ((uint32_t) 'R' << 16) | ((uint32_t) 'O' << 8) | (uint32_t)'V'; 2310 } 2311 2312 void mesh_node_reset(void){ 2313 mesh_configuration_server_setup_tlv(); 2314 2315 // PROV 2316 btstack_tlv_singleton_impl->delete_tag(btstack_tlv_singleton_context, mesh_tag_for_prov_data()); 2317 // everything else 2318 mesh_delete_network_keys(); 2319 mesh_delete_app_keys(); 2320 mesh_delete_appkey_lists(); 2321 mesh_delete_virtual_addresses(); 2322 mesh_delete_subscriptions(); 2323 mesh_delete_publications(); 2324 } 2325 2326 typedef struct { 2327 uint16_t unicast_address; 2328 uint8_t flags; 2329 uint8_t device_key[16]; 2330 2331 } mesh_persistent_provisioning_data_t; 2332 2333 void mesh_node_store_provisioning_data(mesh_provisioning_data_t * provisioning_data){ 2334 2335 // fill persistent prov data 2336 mesh_persistent_provisioning_data_t persistent_provisioning_data; 2337 2338 persistent_provisioning_data.unicast_address = provisioning_data->unicast_address; 2339 memcpy(persistent_provisioning_data.device_key, provisioning_data->device_key, 16); 2340 2341 // store in tlv 2342 btstack_tlv_get_instance(&btstack_tlv_singleton_impl, &btstack_tlv_singleton_context); 2343 btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, mesh_tag_for_prov_data(), (uint8_t *) &persistent_provisioning_data, sizeof(mesh_persistent_provisioning_data_t)); 2344 2345 // store IV Index and sequence number 2346 mesh_store_iv_index_after_provisioning(provisioning_data->iv_index); 2347 2348 // store primary network key 2349 mesh_store_network_key(provisioning_data->network_key); 2350 } 2351 2352 int mesh_node_startup_from_tlv(void){ 2353 2354 mesh_persistent_provisioning_data_t persistent_provisioning_data; 2355 btstack_tlv_get_instance(&btstack_tlv_singleton_impl, &btstack_tlv_singleton_context); 2356 2357 // load provisioning data 2358 uint32_t prov_len = btstack_tlv_singleton_impl->get_tag(btstack_tlv_singleton_context, mesh_tag_for_prov_data(), (uint8_t *) &persistent_provisioning_data, sizeof(mesh_persistent_provisioning_data_t)); 2359 printf("Provisioning data available: %u\n", prov_len ? 1 : 0); 2360 if (prov_len){ 2361 2362 // copy into mesh_provisioning_data 2363 mesh_provisioning_data_t provisioning_data; 2364 memcpy(provisioning_data.device_key, persistent_provisioning_data.device_key, 16); 2365 provisioning_data.unicast_address = persistent_provisioning_data.unicast_address; 2366 provisioning_data.flags = persistent_provisioning_data.flags; 2367 provisioning_data.network_key = NULL; 2368 2369 // load iv index 2370 uint32_t iv_index; 2371 uint32_t sequence_number; 2372 int ok = mesh_load_iv_index_and_sequence_number(&iv_index, &sequence_number); 2373 if (ok){ 2374 // bump sequence number to account for interval updates 2375 sequence_number += MESH_SEQUENCE_NUMBER_STORAGE_INTERVAL; 2376 mesh_sequence_number_set(sequence_number); 2377 mesh_store_iv_index_and_sequence_number(); 2378 log_info("IV Index: %08x, Sequence Number %08x", (int) iv_index, (int) sequence_number); 2379 provisioning_data.iv_index = iv_index; 2380 } 2381 2382 // load network keys 2383 mesh_load_network_keys(); 2384 // load app keys 2385 mesh_load_app_keys(); 2386 // load model to appkey bindings 2387 mesh_load_appkey_lists(); 2388 // load virtual addresses 2389 mesh_load_virtual_addresses(); 2390 // load model subscriptions 2391 mesh_load_subscriptions(); 2392 // load model publications 2393 mesh_load_publications(); 2394 // load foundation state 2395 mesh_foundation_state_load(); 2396 2397 mesh_access_setup_from_provisioning_data(&provisioning_data); 2398 2399 #if defined(ENABLE_MESH_ADV_BEARER) || defined(ENABLE_MESH_PB_ADV) 2400 // start sending Secure Network Beacon 2401 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(0); 2402 if (subnet){ 2403 beacon_secure_network_start(subnet); 2404 } 2405 #endif 2406 return 1; 2407 } else { 2408 mesh_access_setup_without_provisiong_data(); 2409 return 0; 2410 } 2411 } 2412 2413