xref: /btstack/src/mesh/mesh_network.c (revision eac63103677b32b01a82b6c6340c75e35f4ea54a)
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 <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 
44 #include "btstack_debug.h"
45 #include "btstack_event.h"
46 #include "btstack_memory.h"
47 #include "btstack_util.h"
48 
49 #include "mesh/beacon.h"
50 #include "mesh/mesh_foundation.h"
51 #include "mesh/mesh_iv_index_seq_number.h"
52 #include "mesh/mesh_keys.h"
53 #include "mesh/mesh_node.h"
54 #include "mesh/provisioning.h"
55 #include "mesh/provisioning_device.h"
56 
57 #ifdef ENABLE_MESH_ADV_BEARER
58 #include "mesh/adv_bearer.h"
59 #endif
60 
61 #ifdef ENABLE_MESH_GATT_BEARER
62 #include "mesh/gatt_bearer.h"
63 #endif
64 
65 // configuration
66 #define MESH_NETWORK_CACHE_SIZE 2
67 
68 // debug config
69 // #define LOG_NETWORK
70 
71 static void mesh_network_dump_network_pdus(const char * name, btstack_linked_list_t * list);
72 
73 // structs
74 
75 // globals
76 
77 static void (*mesh_network_higher_layer_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu);
78 static void (*mesh_network_proxy_message_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu);
79 
80 #ifdef ENABLE_MESH_GATT_BEARER
81 static hci_con_handle_t gatt_bearer_con_handle;
82 #endif
83 
84 // shared send/receive crypto
85 static int mesh_crypto_active;
86 
87 // crypto requests
88 static union {
89     btstack_crypto_ccm_t         ccm;
90     btstack_crypto_aes128_t      aes128;
91 } mesh_network_crypto_request;
92 
93 static const mesh_network_key_t *  current_network_key;
94 
95 // PECB calculation
96 static uint8_t encryption_block[16];
97 static uint8_t obfuscation_block[16];
98 
99 // Subnets
100 static btstack_linked_list_t subnets;
101 
102 // Network Nonce
103 static uint8_t network_nonce[13];
104 
105 // INCOMING //
106 
107 // unprocessed network pdu - added by mesh_network_pdus_received_message
108 static btstack_linked_list_t        network_pdus_received;
109 
110 // in validation
111 static mesh_network_pdu_t *         incoming_pdu_raw;
112 static mesh_network_pdu_t *         incoming_pdu_decoded;
113 static mesh_network_key_iterator_t  validation_network_key_it;
114 
115 // OUTGOING //
116 
117 // Network PDUs queued by mesh_network_send
118 static btstack_linked_list_t network_pdus_queued;
119 
120 // Network PDU about to get send via all bearers when encrypted
121 static mesh_network_pdu_t * outgoing_pdu;
122 
123 // Network PDUs ready to send via GATT Bearer
124 static btstack_linked_list_t network_pdus_outgoing_gatt;
125 
126 #ifdef ENABLE_MESH_GATT_BEARER
127 static mesh_network_pdu_t * gatt_bearer_network_pdu;
128 #endif
129 
130 // Network PDUs ready to send via ADV Bearer
131 static btstack_linked_list_t network_pdus_outgoing_adv;
132 
133 #ifdef ENABLE_MESH_ADV_BEARER
134 static mesh_network_pdu_t * adv_bearer_network_pdu;
135 #endif
136 
137 
138 // mesh network cache - we use 32-bit 'hashes'
139 static uint32_t mesh_network_cache[MESH_NETWORK_CACHE_SIZE];
140 static int      mesh_network_cache_index;
141 
142 // prototypes
143 
144 static void mesh_network_run(void);
145 static void process_network_pdu_validate(void);
146 
147 // network caching
148 static uint32_t mesh_network_cache_hash(mesh_network_pdu_t * network_pdu){
149     // - The SEQ field is a 24-bit integer that when combined with the IV Index,
150     // shall be a unique value for each new Network PDU originated by this node (=> SRC)
151     // - IV updates only rarely
152     // => 16 bit SRC, 1 bit IVI, 15 bit SEQ
153     uint8_t  ivi = network_pdu->data[0] >> 7;
154     uint16_t seq = big_endian_read_16(network_pdu->data, 3);
155     uint16_t src = big_endian_read_16(network_pdu->data, 5);
156     return (src << 16) | (ivi << 15) | (seq & 0x7fff);
157 }
158 
159 static int mesh_network_cache_find(uint32_t hash){
160     int i;
161     for (i = 0; i < MESH_NETWORK_CACHE_SIZE; i++) {
162         if (mesh_network_cache[i] == hash) {
163             return 1;
164         }
165     }
166     return 0;
167 }
168 
169 static void mesh_network_cache_add(uint32_t hash){
170     mesh_network_cache[mesh_network_cache_index++] = hash;
171     if (mesh_network_cache_index >= MESH_NETWORK_CACHE_SIZE){
172         mesh_network_cache_index = 0;
173     }
174 }
175 
176 // common helper
177 int mesh_network_address_unicast(uint16_t addr){
178     return addr != MESH_ADDRESS_UNSASSIGNED && (addr < 0x8000);
179 }
180 
181 int mesh_network_address_virtual(uint16_t addr){
182     return (addr & 0xC000) == 0x8000;   // 0b10xx xxxx xxxx xxxx
183 }
184 
185 int mesh_network_address_group(uint16_t addr){
186     return (addr & 0xC000) == 0xC000;   // 0b11xx xxxx xxxx xxxx
187 }
188 
189 int mesh_network_address_all_proxies(uint16_t addr){
190     return addr == MESH_ADDRESS_ALL_PROXIES;
191 }
192 
193 int mesh_network_address_all_nodes(uint16_t addr){
194     return addr == MESH_ADDRESS_ALL_NODES;
195 }
196 
197 int mesh_network_address_all_friends(uint16_t addr){
198     return addr == MESH_ADDRESS_ALL_FRIENDS;
199 }
200 
201 int mesh_network_address_all_relays(uint16_t addr){
202     return addr == MESH_ADDRESS_ALL_RELAYS;
203 }
204 
205 int mesh_network_addresses_valid(uint8_t ctl, uint16_t src, uint16_t dst){
206     // printf("CTL: %u\n", ctl);
207     // printf("SRC: %04x\n", src);
208     // printf("DST: %04x\n", dst);
209     if (src == 0){
210         // printf("SRC Unassigned Addr -> ignore\n");
211         return 0;
212     }
213     if ((src & 0xC000) == 0x8000){
214         // printf("SRC Virtual Addr -> ignore\n");
215         return 0;
216     }
217     if ((src & 0xC000) == 0xC000){
218         // printf("SRC Group Addr -> ignore\n");
219         return 0;
220     }
221     if (dst == 0){
222         // printf("DST Unassigned Addr -> ignore\n");
223         return 0;
224     }
225     if ( ((dst & 0xC000) == 0x8000) && (ctl == 1)){
226         // printf("DST Virtual Addr in CONTROL -> ignore\n");
227         return 0;
228     }
229     if ( (0xFF00 <= dst) && (dst <= 0xfffb) && (ctl == 0) ){
230         // printf("DST RFU Group Addr in MESSAGE -> ignore\n");
231         return 0;
232     }
233     // printf("SRC + DST Addr valid\n");
234     return 1;
235 }
236 
237 static void mesh_network_create_nonce(uint8_t * nonce, const mesh_network_pdu_t * pdu, uint32_t iv_index){
238     unsigned int pos = 0;
239     nonce[pos++] = 0x0;      // Network Nonce
240     memcpy(&nonce[pos], &pdu->data[1], 6);
241     pos += 6;
242     big_endian_store_16(nonce, pos, 0);
243     pos += 2;
244     big_endian_store_32(nonce, pos, iv_index);
245 }
246 
247 static void mesh_proxy_create_nonce(uint8_t * nonce, const mesh_network_pdu_t * pdu, uint32_t iv_index){
248     unsigned int pos = 0;
249     nonce[pos++] = 0x3;      // Proxy Nonce
250     nonce[pos++] = 0;
251     memcpy(&nonce[pos], &pdu->data[2], 5);
252     pos += 5;
253     big_endian_store_16(nonce, pos, 0);
254     pos += 2;
255     big_endian_store_32(nonce, pos, iv_index);
256 }
257 
258 // NID/IVI | obfuscated (CTL/TTL, SEQ (24), SRC (16) ), encrypted ( DST(16), TransportPDU), MIC(32 or 64)
259 
260 static void mesh_network_send_complete(mesh_network_pdu_t * network_pdu){
261 #ifdef LOG_NETWORK
262     printf("TX-F-NetworkPDU (%p): ", network_pdu);
263     printf_hexdump(network_pdu->data, network_pdu->len);
264 #endif
265     // notify higher layer
266     (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu);
267 }
268 
269 static void mesh_network_send_d(mesh_network_pdu_t * network_pdu){
270 
271 #ifdef LOG_NETWORK
272     printf("TX-D-NetworkPDU (%p): ", network_pdu);
273     printf_hexdump(network_pdu->data, network_pdu->len);
274 #endif
275 
276     // add to queue
277     btstack_linked_list_add_tail(&network_pdus_outgoing_gatt, (btstack_linked_item_t *) network_pdu);
278 
279     // go
280     mesh_network_run();
281 }
282 
283 // new
284 static void mesh_network_send_c(void *arg){
285     UNUSED(arg);
286 
287     // obfuscate
288     unsigned int i;
289     for (i=0;i<6;i++){
290         outgoing_pdu->data[1+i] ^= obfuscation_block[i];
291     }
292 
293 #ifdef LOG_NETWORK
294     printf("TX-C-NetworkPDU (%p): ", outgoing_pdu);
295     printf_hexdump(outgoing_pdu->data, outgoing_pdu->len);
296 #endif
297 
298     // crypto done
299     mesh_crypto_active = 0;
300 
301     // done
302     mesh_network_pdu_t * network_pdu = outgoing_pdu;
303     outgoing_pdu = NULL;
304     (network_pdu->callback)(network_pdu);
305 }
306 
307 static void mesh_network_send_b(void *arg){
308     UNUSED(arg);
309 
310     uint32_t iv_index = mesh_get_iv_index_for_tx();
311 
312     // store NetMIC
313     uint8_t net_mic[8];
314     btstack_crypto_ccm_get_authentication_value(&mesh_network_crypto_request.ccm, net_mic);
315 
316     // store MIC
317     uint8_t net_mic_len = outgoing_pdu->data[1] & 0x80 ? 8 : 4;
318     memcpy(&outgoing_pdu->data[outgoing_pdu->len], net_mic, net_mic_len);
319     outgoing_pdu->len += net_mic_len;
320 
321 #ifdef LOG_NETWORK
322     printf("TX-B-NetworkPDU (%p): ", outgoing_pdu);
323     printf_hexdump(outgoing_pdu->data, outgoing_pdu->len);
324 #endif
325 
326     // calc PECB
327     memset(encryption_block, 0, 5);
328     big_endian_store_32(encryption_block, 5, iv_index);
329     memcpy(&encryption_block[9], &outgoing_pdu->data[7], 7);
330     btstack_crypto_aes128_encrypt(&mesh_network_crypto_request.aes128, current_network_key->privacy_key, encryption_block, obfuscation_block, &mesh_network_send_c, NULL);
331 }
332 
333 static void mesh_network_send_a(void){
334 
335     mesh_crypto_active = 1;
336 
337     uint32_t iv_index = mesh_get_iv_index_for_tx();
338 
339     // lookup subnet by netkey_index
340     mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(outgoing_pdu->netkey_index);
341     if (!subnet) {
342         mesh_crypto_active = 0;
343         mesh_network_pdu_t * network_pdu = outgoing_pdu;
344         outgoing_pdu = NULL;
345         // notify upper layer
346         mesh_network_send_complete(network_pdu);
347         // run again
348         mesh_network_run();
349         return;
350     }
351 
352     // get network key to use for sending
353     current_network_key = mesh_subnet_get_outgoing_network_key(subnet);
354 
355 #ifdef LOG_NETWORK
356     printf("TX-A-NetworkPDU (%p): ", outgoing_pdu);
357     printf_hexdump(outgoing_pdu->data, outgoing_pdu->len);
358 #endif
359 
360     // get network nonce
361     if (outgoing_pdu->flags & MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION){
362         mesh_proxy_create_nonce(network_nonce, outgoing_pdu, iv_index);
363 #ifdef LOG_NETWORK
364         printf("TX-ProxyNonce:  ");
365         printf_hexdump(network_nonce, 13);
366 #endif
367     } else {
368         mesh_network_create_nonce(network_nonce, outgoing_pdu, iv_index);
369 #ifdef LOG_NETWORK
370         printf("TX-NetworkNonce:  ");
371         printf_hexdump(network_nonce, 13);
372 #endif
373     }
374 
375 #ifdef LOG_NETWORK
376    printf("TX-EncryptionKey: ");
377     printf_hexdump(current_network_key->encryption_key, 16);
378 #endif
379 
380     // start ccm
381     uint8_t cypher_len  = outgoing_pdu->len - 7;
382     uint8_t net_mic_len = outgoing_pdu->data[1] & 0x80 ? 8 : 4;
383     btstack_crypto_ccm_init(&mesh_network_crypto_request.ccm, current_network_key->encryption_key, network_nonce, cypher_len, 0, net_mic_len);
384     btstack_crypto_ccm_encrypt_block(&mesh_network_crypto_request.ccm, cypher_len, &outgoing_pdu->data[7], &outgoing_pdu->data[7], &mesh_network_send_b, NULL);
385 }
386 
387 #if defined(ENABLE_MESH_RELAY) || defined (ENABLE_MESH_PROXY_SERVER)
388 static void mesh_network_relay_message(mesh_network_pdu_t * network_pdu){
389 
390     uint8_t ctl_ttl     = network_pdu->data[1];
391     uint8_t ctl         = ctl_ttl & 0x80;
392     uint8_t ttl         = ctl_ttl & 0x7f;
393 
394 #ifdef LOG_NETWORK
395     printf("TX-Relay-NetworkPDU (%p): ", network_pdu);
396     printf_hexdump(network_pdu->data, network_pdu->len);
397     printf("^^ into network_pdus_queued\n");
398 #endif
399 
400     // prepare pdu for resending
401     network_pdu->data[1] = (ctl << 7) | (ttl - 1);
402     network_pdu->flags |= MESH_NETWORK_PDU_FLAGS_RELAY;
403 
404     // queue up
405     network_pdu->callback = &mesh_network_send_d;
406     btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu);
407 }
408 #endif
409 
410 void mesh_network_message_processed_by_higher_layer(mesh_network_pdu_t * network_pdu){
411 
412 #if defined(ENABLE_MESH_RELAY) || defined (ENABLE_MESH_PROXY_SERVER)
413 
414     // check if address does not matches elements on our node and TTL >= 2
415     uint16_t src     = mesh_network_src(network_pdu);
416     uint8_t  ttl     = mesh_network_ttl(network_pdu);
417 
418     uint16_t mesh_network_primary_address = mesh_node_get_primary_element_address();
419 
420     if (((src < mesh_network_primary_address) || (src > (mesh_network_primary_address + mesh_node_element_count()))) && (ttl >= 2)){
421 
422         if ((network_pdu->flags & MESH_NETWORK_PDU_FLAGS_GATT_BEARER) == 0){
423 
424             // message received via ADV bearer are relayed:
425 
426 #ifdef ENABLE_MESH_RELAY
427             if (mesh_foundation_relay_get() != 0){
428                 // - to ADV bearer, if Relay supported and enabled
429                 mesh_network_relay_message(network_pdu);
430                 mesh_network_run();
431                 return;
432             }
433 #endif
434 
435 #ifdef ENABLE_MESH_PROXY_SERVER
436             if (mesh_foundation_gatt_proxy_get() != 0){
437                 // - to GATT bearer, if Proxy supported and enabled
438                 mesh_network_relay_message(network_pdu);
439                 mesh_network_run();
440                 return;
441             }
442 #endif
443 
444         } else {
445 
446             // messages received via GATT bearer are relayed:
447 
448 #ifdef ENABLE_MESH_PROXY_SERVER
449             if (mesh_foundation_gatt_proxy_get() != 0){
450                 // - to ADV bearer, if Proxy supported and enabled
451                 mesh_network_relay_message(network_pdu);
452                 mesh_network_run();
453                 return;
454             }
455 #endif
456 
457         }
458     }
459 #endif
460 
461     // otherwise, we're done
462     btstack_memory_mesh_network_pdu_free(network_pdu);
463 }
464 
465 static void process_network_pdu_done(void){
466     btstack_memory_mesh_network_pdu_free(incoming_pdu_raw);
467     incoming_pdu_raw = NULL;
468     mesh_crypto_active = 0;
469 
470     mesh_network_run();
471 }
472 
473 static void process_network_pdu_validate_d(void * arg){
474     UNUSED(arg);
475     // mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg;
476 
477     uint8_t ctl_ttl     = incoming_pdu_decoded->data[1];
478     uint8_t ctl         = ctl_ttl >> 7;
479     uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4;
480 
481     // store NetMIC
482     uint8_t net_mic[8];
483     btstack_crypto_ccm_get_authentication_value(&mesh_network_crypto_request.ccm, net_mic);
484 #ifdef LOG_NETWORK
485     printf("RX-NetMIC: ");
486     printf_hexdump(net_mic, net_mic_len);
487 #endif
488     // store in decoded pdu
489     memcpy(&incoming_pdu_decoded->data[incoming_pdu_decoded->len-net_mic_len], net_mic, net_mic_len);
490 
491 #ifdef LOG_NETWORK
492     uint8_t cypher_len  = incoming_pdu_decoded->len - 9 - net_mic_len;
493     printf("RX-Decrypted DST/TransportPDU: ");
494     printf_hexdump(&incoming_pdu_decoded->data[7], 2 + cypher_len);
495 
496     printf("RX-Decrypted: ");
497     printf_hexdump(incoming_pdu_decoded->data, incoming_pdu_decoded->len);
498 #endif
499 
500     // validate network mic
501     if (memcmp(net_mic, &incoming_pdu_raw->data[incoming_pdu_decoded->len-net_mic_len], net_mic_len) != 0){
502         // fail
503         printf("RX-NetMIC mismatch, try next key\n");
504         process_network_pdu_validate();
505         return;
506     }
507 
508     // remove NetMIC from payload
509     incoming_pdu_decoded->len -= net_mic_len;
510 
511 #ifdef LOG_NETWORK
512     // match
513     printf("RX-NetMIC matches\n");
514     printf("RX-TTL: 0x%02x\n", incoming_pdu_decoded->data[1] & 0x7f);
515 #endif
516 
517     // set netkey_index
518     incoming_pdu_decoded->netkey_index = current_network_key->netkey_index;
519 
520     if (incoming_pdu_decoded->flags & MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION){
521 
522         mesh_network_pdu_t * decoded_pdu = incoming_pdu_decoded;
523         incoming_pdu_decoded = NULL;
524 
525         // no additional checks for proxy messages
526         (*mesh_network_proxy_message_handler)(MESH_NETWORK_PDU_RECEIVED, decoded_pdu);
527 
528     } else {
529 
530         // validate src/dest addresses
531         uint16_t src = big_endian_read_16(incoming_pdu_decoded->data, 5);
532         uint16_t dst = big_endian_read_16(incoming_pdu_decoded->data, 7);
533         int valid = mesh_network_addresses_valid(ctl, src, dst);
534         if (!valid){
535             printf("RX Address invalid\n");
536             btstack_memory_mesh_network_pdu_free(incoming_pdu_decoded);
537             incoming_pdu_decoded = NULL;
538             process_network_pdu_done();
539             return;
540         }
541 
542         // check cache
543         uint32_t hash = mesh_network_cache_hash(incoming_pdu_decoded);
544 #ifdef LOG_NETWORK
545         printf("RX-Hash: %08x\n", hash);
546 #endif
547         if (mesh_network_cache_find(hash)){
548             // found in cache, drop
549             printf("Found in cache -> drop packet\n");
550             btstack_memory_mesh_network_pdu_free(incoming_pdu_decoded);
551             incoming_pdu_decoded = NULL;
552             process_network_pdu_done();
553             return;
554         }
555 
556         // store in network cache
557         mesh_network_cache_add(hash);
558 
559         // forward to lower transport layer. message is freed by call to mesh_network_message_processed_by_upper_layer
560         mesh_network_pdu_t * decoded_pdu = incoming_pdu_decoded;
561         incoming_pdu_decoded = NULL;
562         (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_RECEIVED, decoded_pdu);
563     }
564 
565     // done
566     process_network_pdu_done();
567 }
568 
569 static uint32_t iv_index_for_pdu(const mesh_network_pdu_t * network_pdu){
570     // get IV Index and IVI
571     uint32_t iv_index = mesh_get_iv_index();
572     int ivi = network_pdu->data[0] >> 7;
573 
574     // if least significant bit differs, use previous IV Index
575     if ((iv_index & 1 ) ^ ivi){
576         iv_index--;
577 #ifdef LOG_NETWORK
578         printf("RX-IV: IVI indicates previous IV index, using 0x%08x\n", iv_index);
579 #endif
580     }
581     return iv_index;
582 }
583 
584 static void process_network_pdu_validate_b(void * arg){
585     UNUSED(arg);
586 
587 #ifdef LOG_NETWORK
588     printf("RX-PECB: ");
589     printf_hexdump(obfuscation_block, 6);
590 #endif
591 
592     // de-obfuscate
593     unsigned int i;
594     for (i=0;i<6;i++){
595         incoming_pdu_decoded->data[1+i] = incoming_pdu_raw->data[1+i] ^ obfuscation_block[i];
596     }
597 
598     uint32_t iv_index = iv_index_for_pdu(incoming_pdu_raw);
599 
600     if (incoming_pdu_decoded->flags & MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION){
601         // create network nonce
602         mesh_proxy_create_nonce(network_nonce, incoming_pdu_decoded, iv_index);
603 #ifdef LOG_NETWORK
604         printf("RX-Proxy Nonce: ");
605         printf_hexdump(network_nonce, 13);
606 #endif
607     } else {
608         // create network nonce
609         mesh_network_create_nonce(network_nonce, incoming_pdu_decoded, iv_index);
610 #ifdef LOG_NETWORK
611         printf("RX-Network Nonce: ");
612         printf_hexdump(network_nonce, 13);
613 #endif
614     }
615 
616     //
617     uint8_t ctl_ttl     = incoming_pdu_decoded->data[1];
618     uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4;
619     uint8_t cypher_len  = incoming_pdu_decoded->len - 7 - net_mic_len;
620 
621 #ifdef LOG_NETWORK
622     printf("RX-Cyper len %u, mic len %u\n", cypher_len, net_mic_len);
623 
624     printf("RX-Encryption Key: ");
625     printf_hexdump(current_network_key->encryption_key, 16);
626 
627 #endif
628 
629     btstack_crypto_ccm_init(&mesh_network_crypto_request.ccm, current_network_key->encryption_key, network_nonce, cypher_len, 0, net_mic_len);
630     btstack_crypto_ccm_decrypt_block(&mesh_network_crypto_request.ccm, cypher_len, &incoming_pdu_raw->data[7], &incoming_pdu_decoded->data[7], &process_network_pdu_validate_d, incoming_pdu_decoded);
631 }
632 
633 static void process_network_pdu_validate(void){
634     if (!mesh_network_key_nid_iterator_has_more(&validation_network_key_it)){
635         printf("No valid network key found\n");
636         btstack_memory_mesh_network_pdu_free(incoming_pdu_decoded);
637         incoming_pdu_decoded = NULL;
638         process_network_pdu_done();
639         return;
640     }
641 
642     current_network_key = mesh_network_key_nid_iterator_get_next(&validation_network_key_it);
643 
644     // calc PECB
645     uint32_t iv_index = iv_index_for_pdu(incoming_pdu_raw);
646     memset(encryption_block, 0, 5);
647     big_endian_store_32(encryption_block, 5, iv_index);
648     memcpy(&encryption_block[9], &incoming_pdu_raw->data[7], 7);
649     btstack_crypto_aes128_encrypt(&mesh_network_crypto_request.aes128, current_network_key->privacy_key, encryption_block, obfuscation_block, &process_network_pdu_validate_b, NULL);
650 }
651 
652 
653 static void process_network_pdu(void){
654     //
655     uint8_t nid_ivi = incoming_pdu_raw->data[0];
656 
657     // setup pdu object
658     incoming_pdu_decoded->data[0] = nid_ivi;
659     incoming_pdu_decoded->len     = incoming_pdu_raw->len;
660     incoming_pdu_decoded->flags   = incoming_pdu_raw->flags;
661 
662     // init provisioning data iterator
663     uint8_t nid = nid_ivi & 0x7f;
664     // uint8_t iv_index = network_pdu_data[0] >> 7;
665     mesh_network_key_nid_iterator_init(&validation_network_key_it, nid);
666 
667     process_network_pdu_validate();
668 }
669 
670 static void mesh_network_run(void){
671     if (!btstack_linked_list_empty(&network_pdus_outgoing_gatt)){
672 
673 
674 #ifdef ENABLE_MESH_GATT_BEARER
675         if (gatt_bearer_network_pdu == NULL){
676             // move to 'gatt bearer queue'
677             mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_outgoing_gatt);
678 
679 #ifdef LOG_NETWORK
680         printf("network run: pop %p from network_pdus_outgoing_gatt\n", network_pdu);
681 #endif
682         // request to send via gatt if:
683         // proxy active and connected
684         // packet wasn't received via gatt bearer
685             int send_via_gatt = ((mesh_foundation_gatt_proxy_get() != 0) &&
686             (gatt_bearer_con_handle != HCI_CON_HANDLE_INVALID) &&
687                                  ((network_pdu->flags & MESH_NETWORK_PDU_FLAGS_GATT_BEARER) == 0));
688             if (send_via_gatt){
689 #ifdef LOG_NETWORK
690         printf("network run: set %p as gatt_bearer_network_pdu\n", network_pdu);
691 #endif
692 
693                gatt_bearer_network_pdu = network_pdu;
694                 gatt_bearer_request_can_send_now_for_network_pdu();
695             } else {
696 #ifdef LOG_NETWORK
697         printf("network run: push %p to network_pdus_outgoing_adv\n", network_pdu);
698 #endif
699                 btstack_linked_list_add_tail(&network_pdus_outgoing_adv, (btstack_linked_item_t *) network_pdu);
700             }
701         }
702 #else
703         // directly move to 'outgoing adv bearer queue'
704         mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_outgoing_gatt);
705         btstack_linked_list_add_tail(&network_pdus_outgoing_adv, (btstack_linked_item_t *) network_pdu);
706 #endif
707     }
708 
709     if (!btstack_linked_list_empty(&network_pdus_outgoing_adv)){
710 #ifdef ENABLE_MESH_ADV_BEARER
711         if (adv_bearer_network_pdu == NULL){
712             // move to 'adv bearer queue'
713 #ifdef LOG_NETWORK
714             mesh_network_dump_network_pdus("network_pdus_outgoing_adv", &network_pdus_outgoing_adv);
715 #endif
716             mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_outgoing_adv);
717 #ifdef LOG_NETWORK
718             printf("network run: pop %p from network_pdus_outgoing_adv\n", network_pdu);
719             mesh_network_dump_network_pdus("network_pdus_outgoing_adv", &network_pdus_outgoing_adv);
720 #endif
721             adv_bearer_network_pdu = network_pdu;
722             adv_bearer_request_can_send_now_for_network_pdu();
723         }
724 #else
725         // done
726         mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_outgoing_adv);
727         // directly notify upper layer
728         mesh_network_send_complete(network_pdu);
729 #endif
730     }
731 
732     if (mesh_crypto_active) return;
733 
734     if (!btstack_linked_list_empty(&network_pdus_received)){
735         incoming_pdu_decoded = mesh_network_pdu_get();
736         if (!incoming_pdu_decoded) return;
737         // get encoded network pdu and start processing
738         mesh_crypto_active = 1;
739         incoming_pdu_raw = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_received);
740         process_network_pdu();
741         return;
742     }
743 
744     if (!btstack_linked_list_empty(&network_pdus_queued)){
745         // get queued network pdu and start processing
746 #ifdef LOG_NETWORK
747         mesh_network_dump_network_pdus("network_pdus_queued", &network_pdus_queued);
748 #endif
749         outgoing_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_queued);
750 #ifdef LOG_NETWORK
751         printf("network run: pop %p from network_pdus_queued\n", outgoing_pdu);
752         mesh_network_dump_network_pdus("network_pdus_queued", &network_pdus_queued);
753 #endif
754         mesh_network_send_a();
755         return;
756     }
757 }
758 
759 #ifdef ENABLE_MESH_ADV_BEARER
760 static void mesh_adv_bearer_handle_network_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
761     UNUSED(channel);
762     mesh_network_pdu_t * network_pdu;
763     uint8_t  transmission_count;
764     uint16_t transmission_interval;
765     uint8_t  transmit_config;
766 
767     switch (packet_type){
768         case MESH_NETWORK_PACKET:
769             // check len. minimal transport PDU len = 1, 32 bit NetMIC -> 13 bytes
770             if (size < 13) break;
771 
772 #ifdef LOG_NETWORK
773             printf("received network pdu from adv (len %u): ", size);
774             printf_hexdump(packet, size);
775 #endif
776             mesh_network_received_message(packet, size, 0);
777             break;
778 
779         case HCI_EVENT_PACKET:
780             switch(packet[0]){
781                 case HCI_EVENT_MESH_META:
782                     switch(packet[2]){
783                         case MESH_SUBEVENT_CAN_SEND_NOW:
784                             if (adv_bearer_network_pdu == NULL) break;
785 
786                             // Get Transmission config depending on relay flag
787                             if (adv_bearer_network_pdu->flags & MESH_NETWORK_PDU_FLAGS_RELAY){
788                                 transmit_config = mesh_foundation_relay_get();
789                             } else {
790                                 transmit_config = mesh_foundation_network_transmit_get();
791                             }
792                             transmission_count     = (transmit_config & 0x07) + 1;
793                             transmission_interval = (transmit_config >> 3) * 10;
794 
795 #ifdef LOG_NETWORK
796                             printf("TX-E-NetworkPDU count %u, interval %u ms (%p): ", transmission_count, transmission_interval, adv_bearer_network_pdu);
797                             printf_hexdump(adv_bearer_network_pdu->data, adv_bearer_network_pdu->len);
798 #endif
799 
800                             adv_bearer_send_network_pdu(adv_bearer_network_pdu->data, adv_bearer_network_pdu->len, transmission_count, transmission_interval);
801                             network_pdu = adv_bearer_network_pdu;
802                             adv_bearer_network_pdu = NULL;
803 
804                             // notify upper layer
805                             mesh_network_send_complete(network_pdu);
806 
807                             // check if more to send
808                             mesh_network_run();
809                             break;
810                         default:
811                             break;
812                     }
813                     break;
814                 default:
815                     break;
816             }
817             break;
818     }
819 }
820 #endif
821 
822 #ifdef ENABLE_MESH_GATT_BEARER
823 static void mesh_network_gatt_bearer_outgoing_complete(void){
824 
825     if (gatt_bearer_network_pdu == NULL) return;
826 
827     // forward to adv bearer
828     btstack_linked_list_add_tail(&network_pdus_outgoing_adv, (btstack_linked_item_t*) gatt_bearer_network_pdu);
829     gatt_bearer_network_pdu = NULL;
830 
831     mesh_network_run();
832     return;
833 }
834 
835 static void mesh_network_gatt_bearer_handle_network_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
836     UNUSED(channel);
837     switch (packet_type){
838         case MESH_PROXY_DATA_PACKET:
839             if (mesh_foundation_gatt_proxy_get() == 0) break;
840 #ifdef LOG_NETWORK
841             printf("received network pdu from gatt (len %u): ", size);
842             printf_hexdump(packet, size);
843 #endif
844             mesh_network_received_message(packet, size, MESH_NETWORK_PDU_FLAGS_GATT_BEARER);
845             break;
846         case HCI_EVENT_PACKET:
847             switch (hci_event_packet_get_type(packet)){
848                 case HCI_EVENT_MESH_META:
849                     switch (hci_event_mesh_meta_get_subevent_code(packet)){
850                         case MESH_SUBEVENT_PROXY_CONNECTED:
851                             gatt_bearer_con_handle = mesh_subevent_proxy_connected_get_con_handle(packet);
852                             break;
853                         case MESH_SUBEVENT_PROXY_DISCONNECTED:
854                             gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID;
855                             mesh_network_gatt_bearer_outgoing_complete();
856                             break;
857                         case MESH_SUBEVENT_CAN_SEND_NOW:
858                             if (gatt_bearer_network_pdu == NULL) break;
859 #ifdef LOG_NETWORK
860                             printf("G-TX-E-NetworkPDU (%p): ", gatt_bearer_network_pdu);
861                             printf_hexdump(gatt_bearer_network_pdu->data, gatt_bearer_network_pdu->len);
862 #endif
863                             gatt_bearer_send_network_pdu(gatt_bearer_network_pdu->data, gatt_bearer_network_pdu->len);
864                             break;
865 
866                         case MESH_SUBEVENT_MESSAGE_SENT:
867                             mesh_network_gatt_bearer_outgoing_complete();
868                             break;
869                         default:
870                             break;
871                     }
872                     break;
873                 default:
874                     break;
875             }
876             break;
877         default:
878             break;
879     }
880 }
881 #endif
882 
883 #ifdef ENABLE_MESH_GATT_BEARER
884 static void mesh_netework_gatt_bearer_handle_proxy_configuration(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
885     UNUSED(channel);
886     switch (packet_type){
887         case MESH_PROXY_DATA_PACKET:
888             mesh_network_process_proxy_configuration_message(packet, size);
889             break;
890         case HCI_EVENT_PACKET:
891             switch (hci_event_packet_get_type(packet)){
892                 case HCI_EVENT_MESH_META:
893                     switch (hci_event_mesh_meta_get_subevent_code(packet)){
894                         case MESH_SUBEVENT_CAN_SEND_NOW:
895                             // forward to higher layer
896                             (*mesh_network_proxy_message_handler)(MESH_NETWORK_CAN_SEND_NOW, NULL);
897                             break;
898                         default:
899                             break;
900                     }
901                     break;
902                 default:
903                     break;
904             }
905             break;
906         default:
907             break;
908     }
909 }
910 #endif
911 
912 void mesh_network_init(void){
913 #ifdef ENABLE_MESH_ADV_BEARER
914     adv_bearer_register_for_network_pdu(&mesh_adv_bearer_handle_network_event);
915 #endif
916 #ifdef ENABLE_MESH_GATT_BEARER
917     gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID;
918     gatt_bearer_register_for_network_pdu(&mesh_network_gatt_bearer_handle_network_event);
919     gatt_bearer_register_for_mesh_proxy_configuration(&mesh_netework_gatt_bearer_handle_proxy_configuration);
920 #endif
921 }
922 
923 void mesh_network_set_higher_layer_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu)){
924     mesh_network_higher_layer_handler = packet_handler;
925 }
926 
927 void mesh_network_set_proxy_message_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu)){
928     mesh_network_proxy_message_handler = packet_handler;
929 }
930 
931 void mesh_network_received_message(const uint8_t * pdu_data, uint8_t pdu_len, uint8_t flags){
932     // verify len
933     if (pdu_len > 29) return;
934 
935     // allocate network_pdu
936     mesh_network_pdu_t * network_pdu = mesh_network_pdu_get();
937     if (!network_pdu) return;
938 
939     // store data
940     memcpy(network_pdu->data, pdu_data, pdu_len);
941     network_pdu->len = pdu_len;
942     network_pdu->flags = flags;
943 
944     // add to list and go
945     btstack_linked_list_add_tail(&network_pdus_received, (btstack_linked_item_t *) network_pdu);
946     mesh_network_run();
947 
948 }
949 
950 void mesh_network_process_proxy_configuration_message(const uint8_t * pdu_data, uint8_t pdu_len){
951     // verify len
952     if (pdu_len > 29) return;
953 
954     // allocate network_pdu
955     mesh_network_pdu_t * network_pdu = mesh_network_pdu_get();
956     if (!network_pdu) return;
957 
958     // store data
959     memcpy(network_pdu->data, pdu_data, pdu_len);
960     network_pdu->len = pdu_len;
961     network_pdu->flags = MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION; // Network PDU
962 
963     // add to list and go
964     btstack_linked_list_add_tail(&network_pdus_received, (btstack_linked_item_t *) network_pdu);
965     mesh_network_run();
966 }
967 
968 void mesh_network_send_pdu(mesh_network_pdu_t * network_pdu){
969 #ifdef LOG_NETWORK
970     printf("TX-NetworkPDU (%p):   ", network_pdu);
971     printf_hexdump(network_pdu->data, network_pdu->len);
972     printf("^^ into network_pdus_queued\n");
973 #endif
974 
975     if (network_pdu->len > 29){
976         printf("too long, %u\n", network_pdu->len);
977         while(1);
978     }
979 
980     // network pdu without payload and minimal mic = 13 bytes
981     if (network_pdu->len <13){
982         printf("too short, %u\n", network_pdu->len);
983         while(1);
984     }
985 
986     // setup callback
987     network_pdu->callback = &mesh_network_send_d;
988     network_pdu->flags    = 0;
989 
990     // queue up
991     btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu);
992 #ifdef LOG_NETWORK
993     mesh_network_dump_network_pdus("network_pdus_queued", &network_pdus_queued);
994 #endif
995 
996     // go
997     mesh_network_run();
998 }
999 
1000 void mesh_network_encrypt_proxy_configuration_message(mesh_network_pdu_t * network_pdu, void (* callback)(mesh_network_pdu_t * callback)){
1001     printf("ProxyPDU(unencrypted): ");
1002     printf_hexdump(network_pdu->data, network_pdu->len);
1003 
1004     // setup callback
1005     network_pdu->callback = callback;
1006     network_pdu->flags    = MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION;
1007 
1008     // queue up
1009     btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu);
1010 
1011     // go
1012     mesh_network_run();
1013 }
1014 
1015 /*
1016  * @brief Setup network pdu header
1017  * @param netkey_index
1018  * @param ctl
1019  * @param ttl
1020  * @param seq
1021  * @param dest
1022  */
1023 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){
1024     memset(network_pdu, 0, sizeof(mesh_network_pdu_t));
1025     // set netkey_index
1026     network_pdu->netkey_index = netkey_index;
1027     // setup header
1028     network_pdu->data[network_pdu->len++] = (mesh_get_iv_index_for_tx() << 7) |  nid;
1029     uint8_t ctl_ttl = (ctl << 7) | (ttl & 0x7f);
1030     network_pdu->data[network_pdu->len++] = ctl_ttl;
1031     big_endian_store_24(network_pdu->data, 2, seq);
1032     network_pdu->len += 3;
1033     big_endian_store_16(network_pdu->data, network_pdu->len, src);
1034     network_pdu->len += 2;
1035     big_endian_store_16(network_pdu->data, network_pdu->len, dest);
1036     network_pdu->len += 2;
1037     memcpy(&network_pdu->data[network_pdu->len], transport_pdu_data, transport_pdu_len);
1038     network_pdu->len += transport_pdu_len;
1039 }
1040 
1041 /*
1042  * @brief Setup network pdu header
1043  * @param netkey_index
1044  * @param ctl
1045  * @param ttl
1046  * @param seq
1047  * @param dest
1048  */
1049 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){
1050     // set netkey_index
1051     network_pdu->netkey_index = netkey_index;
1052     // setup header
1053     network_pdu->data[0] = (mesh_get_iv_index_for_tx() << 7) |  nid;
1054     uint8_t ctl_ttl = (ctl << 7) | (ttl & 0x7f);
1055     network_pdu->data[1] = ctl_ttl;
1056     big_endian_store_24(network_pdu->data, 2, seq);
1057     big_endian_store_16(network_pdu->data, 5, src);
1058     big_endian_store_16(network_pdu->data, 7, dest);
1059 }
1060 
1061 // Network PDU Getter
1062 uint8_t  mesh_network_nid(mesh_network_pdu_t * network_pdu){
1063     return network_pdu->data[0] & 0x7f;
1064 }
1065 uint16_t mesh_network_control(mesh_network_pdu_t * network_pdu){
1066     return network_pdu->data[1] & 0x80;
1067 }
1068 uint8_t mesh_network_ttl(mesh_network_pdu_t * network_pdu){
1069     return network_pdu->data[1] & 0x7f;
1070 }
1071 uint32_t mesh_network_seq(mesh_network_pdu_t * network_pdu){
1072     return big_endian_read_24(network_pdu->data, 2);
1073 }
1074 uint16_t mesh_network_src(mesh_network_pdu_t * network_pdu){
1075     return big_endian_read_16(network_pdu->data, 5);
1076 }
1077 uint16_t mesh_network_dst(mesh_network_pdu_t * network_pdu){
1078     return big_endian_read_16(network_pdu->data, 7);
1079 }
1080 int mesh_network_segmented(mesh_network_pdu_t * network_pdu){
1081     return network_pdu->data[9] & 0x80;
1082 }
1083 uint8_t mesh_network_control_opcode(mesh_network_pdu_t * network_pdu){
1084     return network_pdu->data[9] & 0x7f;
1085 }
1086 uint8_t * mesh_network_pdu_data(mesh_network_pdu_t * network_pdu){
1087     return &network_pdu->data[9];
1088 }
1089 uint8_t   mesh_network_pdu_len(mesh_network_pdu_t * network_pdu){
1090     return network_pdu->len - 9;
1091 }
1092 
1093 static void mesh_network_dump_network_pdu(mesh_network_pdu_t * network_pdu){
1094     if (network_pdu){
1095         printf("- %p: ", network_pdu); printf_hexdump(network_pdu->data, network_pdu->len);
1096     }
1097 }
1098 static void mesh_network_dump_network_pdus(const char * name, btstack_linked_list_t * list){
1099     printf("List: %s:\n", name);
1100     btstack_linked_list_iterator_t it;
1101     btstack_linked_list_iterator_init(&it, list);
1102     while (btstack_linked_list_iterator_has_next(&it)){
1103         mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t*) btstack_linked_list_iterator_next(&it);
1104         mesh_network_dump_network_pdu(network_pdu);
1105     }
1106 }
1107 static void mesh_network_reset_network_pdus(btstack_linked_list_t * list){
1108     while (!btstack_linked_list_empty(list)){
1109         mesh_network_pdu_t * pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(list);
1110         btstack_memory_mesh_network_pdu_free(pdu);
1111     }
1112 }
1113 void mesh_network_dump(void){
1114     mesh_network_dump_network_pdus("network_pdus_received", &network_pdus_received);
1115     mesh_network_dump_network_pdus("network_pdus_queued", &network_pdus_queued);
1116     mesh_network_dump_network_pdus("network_pdus_outgoing_gatt", &network_pdus_outgoing_gatt);
1117     mesh_network_dump_network_pdus("network_pdus_outgoing_adv", &network_pdus_outgoing_adv);
1118     printf("outgoing_pdu: \n");
1119     mesh_network_dump_network_pdu(outgoing_pdu);
1120     printf("incoming_pdu_raw: \n");
1121     mesh_network_dump_network_pdu(incoming_pdu_raw);
1122     printf("gatt_bearer_network_pdu: \n");
1123     mesh_network_dump_network_pdu(gatt_bearer_network_pdu);
1124     printf("adv_bearer_network_pdu: \n");
1125     mesh_network_dump_network_pdu(adv_bearer_network_pdu);
1126 }
1127 void mesh_network_reset(void){
1128     mesh_network_reset_network_pdus(&network_pdus_received);
1129     mesh_network_reset_network_pdus(&network_pdus_queued);
1130     mesh_network_reset_network_pdus(&network_pdus_outgoing_gatt);
1131     mesh_network_reset_network_pdus(&network_pdus_outgoing_adv);
1132     if (adv_bearer_network_pdu){
1133         mesh_network_pdu_free(adv_bearer_network_pdu);
1134         adv_bearer_network_pdu = NULL;
1135     }
1136     if (gatt_bearer_network_pdu){
1137         mesh_network_pdu_free(gatt_bearer_network_pdu);
1138         gatt_bearer_network_pdu = NULL;
1139     }
1140     if (outgoing_pdu){
1141         mesh_network_pdu_free(outgoing_pdu);
1142         outgoing_pdu = NULL;
1143     }
1144     if (incoming_pdu_raw){
1145         mesh_network_pdu_free(incoming_pdu_raw);
1146         incoming_pdu_raw = NULL;
1147     }
1148     if (incoming_pdu_decoded){
1149         mesh_network_pdu_free(incoming_pdu_decoded);
1150         incoming_pdu_decoded = NULL;
1151     }
1152     mesh_crypto_active = 0;
1153 }
1154 
1155 // buffer pool
1156 mesh_network_pdu_t * mesh_network_pdu_get(void){
1157     mesh_network_pdu_t * network_pdu = btstack_memory_mesh_network_pdu_get();
1158     if (network_pdu) {
1159         memset(network_pdu, 0, sizeof(mesh_network_pdu_t));
1160         network_pdu->pdu_header.pdu_type = MESH_PDU_TYPE_NETWORK;
1161     }
1162     return network_pdu;
1163 }
1164 
1165 void mesh_network_pdu_free(mesh_network_pdu_t * network_pdu){
1166     btstack_memory_mesh_network_pdu_free(network_pdu);
1167 }
1168 
1169 // Mesh Subnet Management
1170 
1171 void mesh_subnet_add(mesh_subnet_t * subnet){
1172     btstack_linked_list_add_tail(&subnets, (btstack_linked_item_t *) subnet);
1173 }
1174 
1175 void mesh_subnet_remove(mesh_subnet_t * subnet){
1176     btstack_linked_list_remove(&subnets, (btstack_linked_item_t *) subnet);
1177 }
1178 
1179 mesh_subnet_t * mesh_subnet_get_by_netkey_index(uint16_t netkey_index){
1180     btstack_linked_list_iterator_t it;
1181     btstack_linked_list_iterator_init(&it, &subnets);
1182     while (btstack_linked_list_iterator_has_next(&it)){
1183         mesh_subnet_t * item = (mesh_subnet_t *) btstack_linked_list_iterator_next(&it);
1184         if (item->netkey_index == netkey_index) return item;
1185     }
1186     return NULL;
1187 }
1188 
1189 int mesh_subnet_list_count(void){
1190     return btstack_linked_list_count(&subnets);
1191 }
1192 
1193 // mesh network key iterator over all keys
1194 void mesh_subnet_iterator_init(mesh_subnet_iterator_t *it){
1195     btstack_linked_list_iterator_init(&it->it, &subnets);
1196 }
1197 
1198 int mesh_subnet_iterator_has_more(mesh_subnet_iterator_t *it){
1199     return btstack_linked_list_iterator_has_next(&it->it);
1200 }
1201 
1202 mesh_subnet_t * mesh_subnet_iterator_get_next(mesh_subnet_iterator_t *it){
1203     return (mesh_subnet_t *) btstack_linked_list_iterator_next(&it->it);
1204 }
1205 
1206 mesh_network_key_t * mesh_subnet_get_outgoing_network_key(mesh_subnet_t * subnet){
1207     switch (subnet->key_refresh){
1208         case MESH_KEY_REFRESH_SECOND_PHASE:
1209             return subnet->new_key;
1210         case MESH_KEY_REFRESH_NOT_ACTIVE:
1211         case MESH_KEY_REFRESH_FIRST_PHASE:
1212         default:
1213             return subnet->old_key;
1214     }
1215 }
1216 
1217 /**
1218  * @brief Setup subnet for given netkey index
1219  */
1220 void mesh_subnet_setup_for_netkey_index(uint16_t netkey_index){
1221     mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index);
1222     if (subnet != NULL) return;
1223 
1224     // find old / new keys
1225     mesh_network_key_t * old_key = NULL;
1226     mesh_network_key_t * new_key = NULL;
1227     mesh_network_key_iterator_t it;
1228     mesh_network_key_iterator_init(&it);
1229     while (mesh_network_key_iterator_has_more(&it)){
1230         mesh_network_key_t * network_key = mesh_network_key_iterator_get_next(&it);
1231         if (network_key->netkey_index != netkey_index) continue;
1232         if (old_key == NULL){
1233             old_key = network_key;
1234             continue;
1235         }
1236         // assign current key depending on key version
1237         if (((int8_t) (network_key->version - new_key->version)) > 0) {
1238             new_key = network_key;
1239         } else {
1240             new_key = old_key;
1241             old_key = network_key;
1242         }
1243     }
1244 
1245     // create subnet for netkey index
1246     subnet = btstack_memory_mesh_subnet_get();
1247     if (subnet == NULL) return;
1248     subnet->netkey_index = netkey_index;
1249     mesh_subnet_add(subnet);
1250 
1251     // set keys
1252     subnet->old_key = old_key;
1253     subnet->new_key = new_key;
1254 
1255     // key refresh
1256     if (new_key == NULL){
1257         // single key -> key refresh not active
1258         subnet->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE;
1259     }
1260     else {
1261         // two keys -> at least phase 1
1262         subnet->key_refresh = MESH_KEY_REFRESH_FIRST_PHASE;
1263     }
1264 }
1265