1 /* 2 * Copyright (C) 2018 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_network.c" 39 40 #include <stdint.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include "mesh/beacon.h" 45 #include "provisioning.h" 46 #include "provisioning_device.h" 47 #include "mesh_keys.h" 48 #include "btstack_util.h" 49 #include "btstack_memory.h" 50 #include "btstack_event.h" 51 52 #ifdef ENABLE_MESH_ADV_BEARER 53 #include "mesh/adv_bearer.h" 54 #endif 55 56 #ifdef ENABLE_MESH_GATT_BEARER 57 #include "mesh/gatt_bearer.h" 58 #endif 59 60 // configuration 61 #define MESH_NETWORK_CACHE_SIZE 2 62 // #define ENABLE_MESH_RELAY 63 64 // debug config 65 // #define LOG_NETWORK 66 67 // structs 68 69 // globals 70 71 static uint32_t global_iv_index; 72 static uint16_t mesh_network_primary_address; 73 static uint16_t mesh_network_num_elements; 74 static void (*mesh_network_higher_layer_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu); 75 static void (*mesh_network_proxy_message_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu); 76 77 // shared send/receive crypto 78 static int mesh_crypto_active; 79 80 // crypto requests 81 static union { 82 btstack_crypto_ccm_t ccm; 83 btstack_crypto_aes128_t aes128; 84 } mesh_network_crypto_request; 85 86 static const mesh_network_key_t * current_network_key; 87 88 // PECB calculation 89 static uint8_t encryption_block[16]; 90 static uint8_t obfuscation_block[16]; 91 92 // Network Nonce 93 static uint8_t network_nonce[13]; 94 95 // INCOMING // 96 97 // unprocessed network pdu - added by mesh_network_pdus_received_message 98 static btstack_linked_list_t network_pdus_received; 99 100 // in validation 101 static mesh_network_pdu_t * network_pdu_in_validation; 102 static mesh_network_key_iterator_t validation_network_key_it; 103 104 // OUTGOING // 105 106 // Network PDUs queued by mesh_network_send 107 static btstack_linked_list_t network_pdus_queued; 108 109 // Network PDUs ready to send 110 static btstack_linked_list_t network_pdus_outgoing; 111 112 // Network PDU ready to send via gatt/adv bearer 113 static mesh_network_pdu_t * actual_bearer_network_pdu; 114 115 // mesh network cache - we use 32-bit 'hashes' 116 static uint32_t mesh_network_cache[MESH_NETWORK_CACHE_SIZE]; 117 static int mesh_network_cache_index; 118 119 // prototypes 120 121 static void mesh_network_run(void); 122 static void process_network_pdu_validate(mesh_network_pdu_t * network_pdu); 123 124 // network caching 125 static uint32_t mesh_network_cache_hash(mesh_network_pdu_t * network_pdu){ 126 // - The SEQ field is a 24-bit integer that when combined with the IV Index, 127 // shall be a unique value for each new Network PDU originated by this node (=> SRC) 128 // - IV updates only rarely 129 // => 16 bit SRC, 1 bit IVI, 15 bit SEQ 130 uint8_t ivi = network_pdu->data[0] >> 7; 131 uint16_t seq = big_endian_read_16(network_pdu->data, 3); 132 uint16_t src = big_endian_read_16(network_pdu->data, 5); 133 return (src << 16) | (ivi << 15) | (seq & 0x7fff); 134 } 135 136 static int mesh_network_cache_find(uint32_t hash){ 137 int i; 138 for (i = 0; i < MESH_NETWORK_CACHE_SIZE; i++) { 139 if (mesh_network_cache[i] == hash) { 140 return 1; 141 } 142 } 143 return 0; 144 } 145 146 static void mesh_network_cache_add(uint32_t hash){ 147 mesh_network_cache[mesh_network_cache_index++] = hash; 148 if (mesh_network_cache_index >= MESH_NETWORK_CACHE_SIZE){ 149 mesh_network_cache_index = 0; 150 } 151 } 152 153 // common helper 154 int mesh_network_address_unicast(uint16_t addr){ 155 return addr < 0x8000; 156 } 157 158 int mesh_network_address_virtual(uint16_t addr){ 159 return (addr & 0xC000) == 0x8000; // 0b10xx xxxx xxxx xxxx 160 } 161 162 int mesh_network_address_group(uint16_t addr){ 163 return (addr & 0xC000) == 0xC000; // 0b11xx xxxx xxxx xxxx 164 } 165 166 int mesh_network_address_all_proxies(uint16_t addr){ 167 return addr == MESH_ADDRESS_ALL_PROXIES; 168 } 169 170 int mesh_network_address_all_nodes(uint16_t addr){ 171 return addr == MESH_ADDRESS_ALL_NODES; 172 } 173 174 int mesh_network_address_all_friends(uint16_t addr){ 175 return addr == MESH_ADDRESS_ALL_FRIENDS; 176 } 177 178 int mesh_network_address_all_relays(uint16_t addr){ 179 return addr == MESH_ADDRESS_ALL_RELAYS; 180 } 181 182 int mesh_network_addresses_valid(uint8_t ctl, uint16_t src, uint16_t dst){ 183 // printf("CTL: %u\n", ctl); 184 // printf("SRC: %04x\n", src); 185 // printf("DST: %04x\n", dst); 186 if (src == 0){ 187 // printf("SRC Unassigned Addr -> ignore\n"); 188 return 0; 189 } 190 if ((src & 0xC000) == 0x8000){ 191 // printf("SRC Virtual Addr -> ignore\n"); 192 return 0; 193 } 194 if ((src & 0xC000) == 0xC000){ 195 // printf("SRC Group Addr -> ignore\n"); 196 return 0; 197 } 198 if (dst == 0){ 199 // printf("DST Unassigned Addr -> ignore\n"); 200 return 0; 201 } 202 if ( ((dst & 0xC000) == 0x8000) && (ctl == 1)){ 203 // printf("DST Virtual Addr in CONTROL -> ignore\n"); 204 return 0; 205 } 206 if ( (0xFF00 <= dst) && (dst <= 0xfffb) && (ctl == 0) ){ 207 // printf("DST RFU Group Addr in MESSAGE -> ignore\n"); 208 return 0; 209 } 210 // printf("SRC + DST Addr valid\n"); 211 return 1; 212 } 213 214 static void mesh_network_create_nonce(uint8_t * nonce, const mesh_network_pdu_t * pdu, uint32_t iv_index){ 215 unsigned int pos = 0; 216 nonce[pos++] = 0x0; // Network Nonce 217 memcpy(&nonce[pos], &pdu->data[1], 6); 218 pos += 6; 219 big_endian_store_16(nonce, pos, 0); 220 pos += 2; 221 big_endian_store_32(nonce, pos, iv_index); 222 } 223 224 static void mesh_proxy_create_nonce(uint8_t * nonce, const mesh_network_pdu_t * pdu, uint32_t iv_index){ 225 unsigned int pos = 0; 226 nonce[pos++] = 0x3; // Proxy Nonce 227 nonce[pos++] = 0; 228 memcpy(&nonce[pos], &pdu->data[2], 5); 229 pos += 5; 230 big_endian_store_16(nonce, pos, 0); 231 pos += 2; 232 big_endian_store_32(nonce, pos, iv_index); 233 } 234 235 // NID/IVI | obfuscated (CTL/TTL, SEQ (24), SRC (16) ), encrypted ( DST(16), TransportPDU), MIC(32 or 64) 236 237 static void mesh_network_send_d(mesh_network_pdu_t * network_pdu){ 238 239 #ifdef LOG_NETWORK 240 printf("TX-D-NetworkPDU (%p): ", network_pdu); 241 printf_hexdump(network_pdu->data, network_pdu->len); 242 #endif 243 244 // add to queue 245 btstack_linked_list_add_tail(&network_pdus_outgoing, (btstack_linked_item_t *) network_pdu); 246 247 // go 248 mesh_network_run(); 249 } 250 251 // new 252 static void mesh_network_send_c(void *arg){ 253 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg; 254 255 // obfuscate 256 unsigned int i; 257 for (i=0;i<6;i++){ 258 network_pdu->data[1+i] ^= obfuscation_block[i]; 259 } 260 261 #ifdef LOG_NETWORK 262 printf("TX-C-NetworkPDU (%p): ", network_pdu); 263 printf_hexdump(network_pdu->data, network_pdu->len); 264 #endif 265 266 // crypto done 267 mesh_crypto_active = 0; 268 269 // done 270 (network_pdu->callback)(network_pdu); 271 } 272 273 static void mesh_network_send_b(void *arg){ 274 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg; 275 276 uint32_t iv_index = global_iv_index; 277 278 // store NetMIC 279 uint8_t net_mic[8]; 280 btstack_crypto_ccm_get_authentication_value(&mesh_network_crypto_request.ccm, net_mic); 281 282 // store MIC 283 uint8_t net_mic_len = network_pdu->data[1] & 0x80 ? 8 : 4; 284 memcpy(&network_pdu->data[network_pdu->len], net_mic, net_mic_len); 285 network_pdu->len += net_mic_len; 286 287 #ifdef LOG_NETWORK 288 printf("TX-B-NetworkPDU (%p): ", network_pdu); 289 printf_hexdump(network_pdu->data, network_pdu->len); 290 #endif 291 292 // calc PECB 293 memset(encryption_block, 0, 5); 294 big_endian_store_32(encryption_block, 5, iv_index); 295 memcpy(&encryption_block[9], &network_pdu->data[7], 7); 296 btstack_crypto_aes128_encrypt(&mesh_network_crypto_request.aes128, current_network_key->privacy_key, encryption_block, obfuscation_block, &mesh_network_send_c, network_pdu); 297 } 298 299 static void mesh_network_send_a(mesh_network_pdu_t * network_pdu){ 300 301 mesh_crypto_active = 1; 302 303 // lookup network by netkey_index 304 current_network_key = mesh_network_key_list_get(network_pdu->netkey_index); 305 if (!current_network_key) { 306 mesh_crypto_active = 0; 307 // notify upper layer 308 (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu); 309 // run again 310 mesh_network_run(); 311 return; 312 } 313 314 // get network nonce 315 if (network_pdu->flags & 1){ 316 mesh_proxy_create_nonce(network_nonce, network_pdu, global_iv_index); 317 #ifdef LOG_NETWORK 318 printf("TX-ProxyNonce: "); 319 printf_hexdump(network_nonce, 13); 320 #endif 321 } else { 322 mesh_network_create_nonce(network_nonce, network_pdu, global_iv_index); 323 #ifdef LOG_NETWORK 324 printf("TX-NetworkNonce: "); 325 printf_hexdump(network_nonce, 13); 326 #endif 327 } 328 329 #ifdef LOG_NETWORK 330 printf("TX-EncryptionKey: "); 331 printf_hexdump(current_network_key->encryption_key, 16); 332 #endif 333 334 // start ccm 335 uint8_t cypher_len = network_pdu->len - 7; 336 uint8_t net_mic_len = network_pdu->data[1] & 0x80 ? 8 : 4; 337 btstack_crypto_ccm_init(&mesh_network_crypto_request.ccm, current_network_key->encryption_key, network_nonce, cypher_len, 0, net_mic_len); 338 btstack_crypto_ccm_encrypt_block(&mesh_network_crypto_request.ccm, cypher_len, &network_pdu->data[7], &network_pdu->data[7], &mesh_network_send_b, network_pdu); 339 } 340 341 void mesh_network_message_processed_by_higher_layer(mesh_network_pdu_t * network_pdu){ 342 #ifdef ENABLE_MESH_RELAY 343 uint8_t ctl_ttl = network_pdu->data[1]; 344 uint8_t ctl = ctl_ttl >> 7; 345 uint8_t ttl = ctl_ttl & 0x7f; 346 uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4; 347 uint16_t src = big_endian_read_16(network_pdu->data, 5); 348 349 // check if address matches elements on our node and TTL >= 2 350 if (((src < mesh_network_primary_address) || (src > (mesh_network_primary_address + mesh_network_num_elements))) && (ttl >= 2)){ 351 // prepare pdu for resending 352 network_pdu->len -= net_mic_len; 353 network_pdu->data[1] = (ctl << 7) | (ttl - 1); 354 355 // queue up 356 network_pdu->callback = &mesh_network_send_d; 357 btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu); 358 359 // go 360 mesh_network_run(); 361 362 return; 363 } 364 #endif 365 btstack_memory_mesh_network_pdu_free(network_pdu); 366 } 367 368 static void process_network_pdu_done(void){ 369 btstack_memory_mesh_network_pdu_free(network_pdu_in_validation); 370 network_pdu_in_validation = NULL; 371 mesh_crypto_active = 0; 372 373 mesh_network_run(); 374 } 375 376 static void process_network_pdu_validate_d(void * arg){ 377 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg; 378 379 uint8_t ctl_ttl = network_pdu->data[1]; 380 uint8_t ctl = ctl_ttl >> 7; 381 uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4; 382 383 // store NetMIC 384 uint8_t net_mic[8]; 385 btstack_crypto_ccm_get_authentication_value(&mesh_network_crypto_request.ccm, net_mic); 386 #ifdef LOG_NETWORK 387 printf("RX-NetMIC: "); 388 printf_hexdump(net_mic, net_mic_len); 389 #endif 390 // store in pdu 391 memcpy(&network_pdu->data[network_pdu->len-net_mic_len], net_mic, net_mic_len); 392 393 #ifdef LOG_NETWORK 394 uint8_t cypher_len = network_pdu->len - 9 - net_mic_len; 395 printf("RX-Decrypted DST/TransportPDU: "); 396 printf_hexdump(&network_pdu->data[7], 2 + cypher_len); 397 398 printf("RX-Decrypted: "); 399 printf_hexdump(network_pdu->data, network_pdu->len); 400 #endif 401 402 // validate network mic 403 if (memcmp(net_mic, &network_pdu_in_validation->data[network_pdu->len-net_mic_len], net_mic_len) != 0){ 404 // fail 405 printf("RX-NetMIC mismatch, try next key\n"); 406 process_network_pdu_validate(network_pdu); 407 return; 408 } 409 410 // remove NetMIC from payload 411 network_pdu->len -= net_mic_len; 412 413 #ifdef LOG_NETWORK 414 // match 415 printf("RX-NetMIC matches\n"); 416 printf("RX-TTL: 0x%02x\n", network_pdu->data[1] & 0x7f); 417 #endif 418 419 // set netkey_index 420 network_pdu->netkey_index = current_network_key->netkey_index; 421 422 if (network_pdu->flags & 1){ 423 424 // no additional checks for proxy messages 425 (*mesh_network_proxy_message_handler)(MESH_NETWORK_PDU_RECEIVED, network_pdu); 426 427 } else { 428 429 // validate src/dest addresses 430 uint16_t src = big_endian_read_16(network_pdu->data, 5); 431 uint16_t dst = big_endian_read_16(network_pdu->data, 7); 432 int valid = mesh_network_addresses_valid(ctl, src, dst); 433 if (!valid){ 434 printf("RX Address invalid\n"); 435 btstack_memory_mesh_network_pdu_free(network_pdu); 436 process_network_pdu_done(); 437 return; 438 } 439 440 // check cache 441 uint32_t hash = mesh_network_cache_hash(network_pdu); 442 #ifdef LOG_NETWORK 443 printf("RX-Hash: %08x\n", hash); 444 #endif 445 if (mesh_network_cache_find(hash)){ 446 // found in cache, drop 447 printf("Found in cache -> drop packet\n"); 448 btstack_memory_mesh_network_pdu_free(network_pdu); 449 process_network_pdu_done(); 450 return; 451 } 452 453 // store in network cache 454 mesh_network_cache_add(hash); 455 456 // forward to lower transport layer. message is freed by call to mesh_network_message_processed_by_upper_layer 457 (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_RECEIVED, network_pdu); 458 } 459 460 // done 461 process_network_pdu_done(); 462 } 463 464 static uint32_t iv_index_for_pdu(const mesh_network_pdu_t * network_pdu){ 465 // get IV Index and IVI 466 uint32_t iv_index = global_iv_index; 467 int ivi = network_pdu->data[0] >> 7; 468 469 // if least significant bit differs, use previous IV Index 470 if ((iv_index & 1 ) ^ ivi){ 471 iv_index--; 472 #ifdef LOG_NETWORK 473 printf("RX-IV: IVI indicates previous IV index, using 0x%08x\n", iv_index); 474 #endif 475 } 476 return iv_index; 477 } 478 479 static void process_network_pdu_validate_b(void * arg){ 480 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg; 481 482 #ifdef LOG_NETWORK 483 printf("RX-PECB: "); 484 printf_hexdump(obfuscation_block, 6); 485 #endif 486 487 // de-obfuscate 488 unsigned int i; 489 for (i=0;i<6;i++){ 490 network_pdu->data[1+i] = network_pdu_in_validation->data[1+i] ^ obfuscation_block[i]; 491 } 492 493 uint32_t iv_index = iv_index_for_pdu(network_pdu); 494 495 if (network_pdu->flags & 1){ 496 // create network nonce 497 mesh_proxy_create_nonce(network_nonce, network_pdu, iv_index); 498 #ifdef LOG_NETWORK 499 printf("RX-Proxy Nonce: "); 500 printf_hexdump(network_nonce, 13); 501 #endif 502 } else { 503 // create network nonce 504 mesh_network_create_nonce(network_nonce, network_pdu, iv_index); 505 #ifdef LOG_NETWORK 506 printf("RX-Network Nonce: "); 507 printf_hexdump(network_nonce, 13); 508 #endif 509 } 510 511 // 512 uint8_t ctl_ttl = network_pdu->data[1]; 513 uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4; 514 uint8_t cypher_len = network_pdu->len - 7 - net_mic_len; 515 516 #ifdef LOG_NETWORK 517 printf("RX-Cyper len %u, mic len %u\n", cypher_len, net_mic_len); 518 519 printf("RX-Encryption Key: "); 520 printf_hexdump(current_network_key->encryption_key, 16); 521 522 #endif 523 524 btstack_crypto_ccm_init(&mesh_network_crypto_request.ccm, current_network_key->encryption_key, network_nonce, cypher_len, 0, net_mic_len); 525 btstack_crypto_ccm_decrypt_block(&mesh_network_crypto_request.ccm, cypher_len, &network_pdu_in_validation->data[7], &network_pdu->data[7], &process_network_pdu_validate_d, network_pdu); 526 } 527 528 static void process_network_pdu_validate(mesh_network_pdu_t * network_pdu){ 529 if (!mesh_network_key_nid_iterator_has_more(&validation_network_key_it)){ 530 printf("No valid network key found\n"); 531 btstack_memory_mesh_network_pdu_free(network_pdu); 532 process_network_pdu_done(); 533 return; 534 } 535 536 current_network_key = mesh_network_key_nid_iterator_get_next(&validation_network_key_it); 537 538 // calc PECB 539 uint32_t iv_index = iv_index_for_pdu(network_pdu); 540 memset(encryption_block, 0, 5); 541 big_endian_store_32(encryption_block, 5, iv_index); 542 memcpy(&encryption_block[9], &network_pdu_in_validation->data[7], 7); 543 btstack_crypto_aes128_encrypt(&mesh_network_crypto_request.aes128, current_network_key->privacy_key, encryption_block, obfuscation_block, &process_network_pdu_validate_b, network_pdu); 544 } 545 546 547 static void process_network_pdu(mesh_network_pdu_t * network_pdu){ 548 // 549 uint8_t nid_ivi = network_pdu_in_validation->data[0]; 550 551 // setup pdu object 552 network_pdu->data[0] = nid_ivi; 553 network_pdu->len = network_pdu_in_validation->len; 554 network_pdu->flags = network_pdu_in_validation->flags; 555 556 // init provisioning data iterator 557 uint8_t nid = nid_ivi & 0x7f; 558 // uint8_t iv_index = network_pdu_data[0] >> 7; 559 mesh_network_key_nid_iterator_init(&validation_network_key_it, nid); 560 561 process_network_pdu_validate(network_pdu); 562 } 563 564 // static void mesh_network_encrypt_and_obfuscate(mesh_network_pdu_t * network_pdu, void (*callback)(mesh_network_pdu_t * network_pdu)){ 565 // network_pdu->callback = callback; 566 // } 567 568 static void mesh_network_run(void){ 569 if (!btstack_linked_list_empty(&network_pdus_outgoing)){ 570 actual_bearer_network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_outgoing); 571 572 int send_to_next_bearer = 1; 573 #ifdef ENABLE_MESH_GATT_BEARER 574 // request to send via gatt 575 if (send_to_next_bearer){ 576 send_to_next_bearer = 0; 577 gatt_bearer_request_can_send_now_for_mesh_network_pdu(); 578 } 579 #endif 580 #ifdef ENABLE_MESH_ADV_BEARER 581 // request to send via adv 582 if (send_to_next_bearer){ 583 send_to_next_bearer = 0; 584 adv_bearer_request_can_send_now_for_mesh_message(); 585 } 586 #endif 587 if (send_to_next_bearer == 1){ 588 // TODO: notify done 589 } 590 } 591 592 if (mesh_crypto_active) return; 593 594 if (!btstack_linked_list_empty(&network_pdus_received)){ 595 mesh_network_pdu_t * decode_pdu = mesh_network_pdu_get(); 596 if (!decode_pdu) return; 597 // get encoded network pdu and start processing 598 mesh_crypto_active = 1; 599 network_pdu_in_validation = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_received); 600 process_network_pdu(decode_pdu); 601 return; 602 } 603 604 if (!btstack_linked_list_empty(&network_pdus_queued)){ 605 // get queued network pdu and start processing 606 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_queued); 607 mesh_network_send_a(network_pdu); 608 return; 609 } 610 } 611 612 #ifdef ENABLE_MESH_ADV_BEARER 613 static void mesh_adv_message_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 614 mesh_network_pdu_t * network_pdu; 615 616 switch (packet_type){ 617 case MESH_NETWORK_PACKET: 618 // check len. minimal transport PDU len = 1, 32 bit NetMIC -> 13 bytes 619 if (size < 13) break; 620 621 #ifdef LOG_NETWORK 622 printf("received mesh message (len %u): ", size); 623 printf_hexdump(packet, size); 624 #endif 625 mesh_network_received_message(packet, size); 626 break; 627 628 case HCI_EVENT_PACKET: 629 switch(packet[0]){ 630 case HCI_EVENT_MESH_META: 631 switch(packet[2]){ 632 case MESH_SUBEVENT_CAN_SEND_NOW: 633 if (actual_bearer_network_pdu == NULL) break; 634 #ifdef LOG_NETWORK 635 printf("TX-E-NetworkPDU (%p): ", actual_bearer_network_pdu); 636 printf_hexdump(actual_bearer_network_pdu->data, actual_bearer_network_pdu->len); 637 #endif 638 adv_bearer_send_mesh_message(actual_bearer_network_pdu->data, actual_bearer_network_pdu->len); 639 network_pdu = actual_bearer_network_pdu; 640 actual_bearer_network_pdu = NULL; 641 642 // notify upper layer 643 (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu); 644 645 // check if more to send 646 mesh_network_run(); 647 break; 648 default: 649 break; 650 } 651 break; 652 default: 653 break; 654 } 655 break; 656 } 657 } 658 #endif 659 660 #ifdef ENABLE_MESH_GATT_BEARER 661 void mesh_gatt_handle_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 662 mesh_network_pdu_t * network_pdu; 663 switch (packet_type){ 664 case HCI_EVENT_PACKET: 665 switch(packet[0]){ 666 case HCI_EVENT_MESH_META: 667 switch(packet[2]){ 668 case MESH_SUBEVENT_CAN_SEND_NOW: 669 if (actual_bearer_network_pdu == NULL) break; 670 #ifdef LOG_NETWORK 671 printf("G-TX-E-NetworkPDU (%p): ", actual_bearer_network_pdu); 672 printf_hexdump(actual_bearer_network_pdu->data, actual_bearer_network_pdu->len); 673 #endif 674 gatt_bearer_send_mesh_network_pdu(actual_bearer_network_pdu->data, actual_bearer_network_pdu->len); 675 break; 676 677 case MESH_SUBEVENT_MESSAGE_SENT: 678 if (actual_bearer_network_pdu == NULL) break; 679 #ifdef ENABLE_MESH_ADV_BEARER 680 // request to send via adv bearer 681 adv_bearer_request_can_send_now_for_mesh_message(); 682 break; 683 #else 684 // notify upper layer 685 network_pdu = actual_bearer_network_pdu; 686 actual_bearer_network_pdu = NULL; 687 (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu); 688 #endif 689 break; 690 default: 691 break; 692 } 693 break; 694 default: 695 break; 696 } 697 break; 698 } 699 } 700 701 702 static void mesh_proxy_packet_handler_network_pdu(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 703 switch (packet_type){ 704 case MESH_PROXY_DATA_PACKET: 705 printf("mesh: Received network PDU (proxy)\n"); 706 printf_hexdump(packet, size); 707 mesh_network_received_message(packet, size); 708 break; 709 case HCI_EVENT_PACKET: 710 switch (hci_event_packet_get_type(packet)){ 711 case HCI_EVENT_MESH_META: 712 switch (hci_event_mesh_meta_get_subevent_code(packet)){ 713 case MESH_SUBEVENT_CAN_SEND_NOW: 714 mesh_gatt_handle_event(packet_type, channel, packet, size); 715 break; 716 case MESH_SUBEVENT_MESSAGE_SENT: 717 mesh_gatt_handle_event(packet_type, channel, packet, size); 718 break; 719 case MESH_SUBEVENT_PROXY_CONNECTED: 720 printf("mesh: MESH_PROXY_CONNECTED\n"); 721 break; 722 default: 723 break; 724 } 725 break; 726 default: 727 break; 728 } 729 break; 730 default: 731 break; 732 } 733 } 734 #endif 735 736 void mesh_network_init(void){ 737 #ifdef ENABLE_MESH_ADV_BEARER 738 adv_bearer_register_for_mesh_message(&mesh_adv_message_handler); 739 #endif 740 #ifdef ENABLE_MESH_GATT_BEARER 741 gatt_bearer_register_for_mesh_network_pdu(&mesh_proxy_packet_handler_network_pdu); 742 #endif 743 } 744 745 void mesh_network_set_higher_layer_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu)){ 746 mesh_network_higher_layer_handler = packet_handler; 747 } 748 749 void mesh_network_set_proxy_message_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu)){ 750 mesh_network_proxy_message_handler = packet_handler; 751 } 752 753 void mesh_network_set_primary_element_address(uint16_t addr){ 754 mesh_network_primary_address = addr; 755 mesh_network_num_elements = 1; 756 } 757 758 void mesh_network_received_message(const uint8_t * pdu_data, uint8_t pdu_len){ 759 // verify len 760 if (pdu_len > 29) return; 761 762 // allocate network_pdu 763 mesh_network_pdu_t * network_pdu = mesh_network_pdu_get(); 764 if (!network_pdu) return; 765 766 // store data 767 memcpy(network_pdu->data, pdu_data, pdu_len); 768 network_pdu->len = pdu_len; 769 network_pdu->flags = 0; // Network PDU 770 771 // add to list and go 772 btstack_linked_list_add_tail(&network_pdus_received, (btstack_linked_item_t *) network_pdu); 773 mesh_network_run(); 774 775 } 776 777 void mesh_network_process_proxy_message(const uint8_t * pdu_data, uint8_t pdu_len){ 778 // verify len 779 if (pdu_len > 29) return; 780 781 // allocate network_pdu 782 mesh_network_pdu_t * network_pdu = mesh_network_pdu_get(); 783 if (!network_pdu) return; 784 785 // store data 786 memcpy(network_pdu->data, pdu_data, pdu_len); 787 network_pdu->len = pdu_len; 788 network_pdu->flags = 1; // Network PDU 789 790 // add to list and go 791 btstack_linked_list_add_tail(&network_pdus_received, (btstack_linked_item_t *) network_pdu); 792 mesh_network_run(); 793 } 794 795 void mesh_network_send_pdu(mesh_network_pdu_t * network_pdu){ 796 #ifdef LOG_NETWORK 797 printf("TX-A-NetworkPDU (%p): ", network_pdu); 798 printf_hexdump(network_pdu->data, network_pdu->len); 799 #endif 800 801 if (network_pdu->len > 29){ 802 printf("too long, %u\n", network_pdu->len); 803 return; 804 } 805 806 // setup callback 807 network_pdu->callback = &mesh_network_send_d; 808 network_pdu->flags = 0; 809 810 // queue up 811 btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu); 812 813 // go 814 mesh_network_run(); 815 } 816 817 void mesh_network_encrypt_proxy_message(mesh_network_pdu_t * network_pdu, void (* callback)(mesh_network_pdu_t * callback)){ 818 printf("ProxyPDU(unencrypted): "); 819 printf_hexdump(network_pdu->data, network_pdu->len); 820 821 // setup callback 822 network_pdu->callback = callback; 823 network_pdu->flags = 1; 824 825 // queue up 826 btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu); 827 828 // go 829 mesh_network_run(); 830 } 831 832 /* 833 * @brief Setup network pdu header 834 * @param netkey_index 835 * @param ctl 836 * @param ttl 837 * @param seq 838 * @param dest 839 */ 840 void mesh_network_setup_pdu(mesh_network_pdu_t * network_pdu, uint16_t netkey_index, uint8_t nid, uint8_t ctl, uint8_t ttl, uint32_t seq, uint16_t src, uint16_t dest, const uint8_t * transport_pdu_data, uint8_t transport_pdu_len){ 841 memset(network_pdu, 0, sizeof(mesh_network_pdu_t)); 842 // set netkey_index 843 network_pdu->netkey_index = netkey_index; 844 // setup header 845 network_pdu->data[network_pdu->len++] = (global_iv_index << 7) | nid; 846 uint8_t ctl_ttl = (ctl << 7) | (ttl & 0x7f); 847 network_pdu->data[network_pdu->len++] = ctl_ttl; 848 big_endian_store_24(network_pdu->data, 2, seq); 849 network_pdu->len += 3; 850 big_endian_store_16(network_pdu->data, network_pdu->len, src); 851 network_pdu->len += 2; 852 big_endian_store_16(network_pdu->data, network_pdu->len, dest); 853 network_pdu->len += 2; 854 memcpy(&network_pdu->data[network_pdu->len], transport_pdu_data, transport_pdu_len); 855 network_pdu->len += transport_pdu_len; 856 } 857 858 /* 859 * @brief Setup network pdu header 860 * @param netkey_index 861 * @param ctl 862 * @param ttl 863 * @param seq 864 * @param dest 865 */ 866 void mesh_network_setup_pdu_header(mesh_network_pdu_t * network_pdu, uint16_t netkey_index, uint8_t nid, uint8_t ctl, uint8_t ttl, uint32_t seq, uint16_t src, uint16_t dest){ 867 // set netkey_index 868 network_pdu->netkey_index = netkey_index; 869 // setup header 870 network_pdu->data[0] = (global_iv_index << 7) | nid; 871 uint8_t ctl_ttl = (ctl << 7) | (ttl & 0x7f); 872 network_pdu->data[1] = ctl_ttl; 873 big_endian_store_24(network_pdu->data, 2, seq); 874 big_endian_store_16(network_pdu->data, 5, src); 875 big_endian_store_16(network_pdu->data, 7, dest); 876 } 877 878 void mesh_set_iv_index(uint32_t iv_index){ 879 global_iv_index = iv_index; 880 } 881 882 uint32_t mesh_get_iv_index(void){ 883 return global_iv_index; 884 } 885 886 // Network PDU Getter 887 uint8_t mesh_network_nid(mesh_network_pdu_t * network_pdu){ 888 return network_pdu->data[0] & 0x7f; 889 } 890 uint16_t mesh_network_control(mesh_network_pdu_t * network_pdu){ 891 return network_pdu->data[1] & 0x80; 892 } 893 uint8_t mesh_network_ttl(mesh_network_pdu_t * network_pdu){ 894 return network_pdu->data[1] & 0x7f; 895 } 896 uint32_t mesh_network_seq(mesh_network_pdu_t * network_pdu){ 897 return big_endian_read_24(network_pdu->data, 2); 898 } 899 uint16_t mesh_network_src(mesh_network_pdu_t * network_pdu){ 900 return big_endian_read_16(network_pdu->data, 5); 901 } 902 uint16_t mesh_network_dst(mesh_network_pdu_t * network_pdu){ 903 return big_endian_read_16(network_pdu->data, 7); 904 } 905 int mesh_network_segmented(mesh_network_pdu_t * network_pdu){ 906 return network_pdu->data[9] & 0x80; 907 } 908 uint8_t * mesh_network_pdu_data(mesh_network_pdu_t * network_pdu){ 909 return &network_pdu->data[9]; 910 } 911 uint8_t mesh_network_pdu_len(mesh_network_pdu_t * network_pdu){ 912 return network_pdu->len - 9; 913 } 914 915 static void mesh_network_dump_network_pdu(mesh_network_pdu_t * network_pdu){ 916 if (network_pdu){ 917 printf("- %p: ", network_pdu); printf_hexdump(network_pdu->data, network_pdu->len); 918 } 919 } 920 static void mesh_network_dump_network_pdus(const char * name, btstack_linked_list_t * list){ 921 printf("List: %s:\n", name); 922 btstack_linked_list_iterator_t it; 923 btstack_linked_list_iterator_init(&it, list); 924 while (btstack_linked_list_iterator_has_next(&it)){ 925 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t*) btstack_linked_list_iterator_next(&it); 926 mesh_network_dump_network_pdu(network_pdu); 927 } 928 } 929 static void mesh_network_reset_network_pdus(btstack_linked_list_t * list){ 930 while (!btstack_linked_list_empty(list)){ 931 mesh_network_pdu_t * pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(list); 932 btstack_memory_mesh_network_pdu_free(pdu); 933 } 934 } 935 void mesh_network_dump(void){ 936 mesh_network_dump_network_pdus("network_pdus_received", &network_pdus_received); 937 mesh_network_dump_network_pdus("network_pdus_queued", &network_pdus_queued); 938 mesh_network_dump_network_pdus("network_pdus_outgoing", &network_pdus_outgoing); 939 printf("network_pdu_in_validation: \n"); 940 mesh_network_dump_network_pdu(network_pdu_in_validation); 941 } 942 void mesh_network_reset(void){ 943 mesh_network_reset_network_pdus(&network_pdus_received); 944 mesh_network_reset_network_pdus(&network_pdus_queued); 945 mesh_network_reset_network_pdus(&network_pdus_outgoing); 946 } 947 948 // buffer pool 949 mesh_network_pdu_t * mesh_network_pdu_get(void){ 950 mesh_network_pdu_t * network_pdu = btstack_memory_mesh_network_pdu_get(); 951 if (network_pdu) { 952 memset(network_pdu, 0, sizeof(mesh_network_pdu_t)); 953 network_pdu->pdu_header.pdu_type = MESH_PDU_TYPE_NETWORK; 954 } 955 return network_pdu; 956 } 957 958 void mesh_network_pdu_free(mesh_network_pdu_t * network_pdu){ 959 btstack_memory_mesh_network_pdu_free(network_pdu); 960 } 961