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