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