1 /*
2 * Copyright (c) 2019 Tobias Svehagen
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr.h>
8 #include <string.h>
9 #include <stdlib.h>
10
11 #include <settings/settings.h>
12
13 #include <bluetooth/mesh.h>
14
15 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_CDB)
16 #define LOG_MODULE_NAME bt_mesh_cdb
17 #include "common/log.h"
18
19 #include "cdb.h"
20 #include "mesh.h"
21 #include "net.h"
22 #include "rpl.h"
23 #include "settings.h"
24
25 /* Tracking of what storage changes are pending for App and Net Keys. We
26 * track this in a separate array here instead of within the respective
27 * bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key
28 * gets deleted its struct becomes invalid and may be reused for other keys.
29 */
30 struct key_update {
31 uint16_t key_idx:12, /* AppKey or NetKey Index */
32 valid:1, /* 1 if this entry is valid, 0 if not */
33 app_key:1, /* 1 if this is an AppKey, 0 if a NetKey */
34 clear:1; /* 1 if key needs clearing, 0 if storing */
35 };
36
37 /* Tracking of what storage changes are pending for node settings. */
38 struct node_update {
39 uint16_t addr;
40 bool clear;
41 };
42
43 /* Node information for persistent storage. */
44 struct node_val {
45 uint16_t net_idx;
46 uint8_t num_elem;
47 uint8_t flags;
48 #define F_NODE_CONFIGURED 0x01
49 uint8_t uuid[16];
50 uint8_t dev_key[16];
51 } __packed;
52
53 /* NetKey storage information */
54 struct net_key_val {
55 uint8_t kr_flag:1,
56 kr_phase:7;
57 uint8_t val[2][16];
58 } __packed;
59
60 /* AppKey information for persistent storage. */
61 struct app_key_val {
62 uint16_t net_idx;
63 bool updated;
64 uint8_t val[2][16];
65 } __packed;
66
67 /* IV Index & IV Update information for persistent storage. */
68 struct net_val {
69 uint32_t iv_index;
70 bool iv_update;
71 } __packed;
72
73 static struct node_update cdb_node_updates[CONFIG_BT_MESH_CDB_NODE_COUNT];
74 static struct key_update cdb_key_updates[CONFIG_BT_MESH_CDB_SUBNET_COUNT +
75 CONFIG_BT_MESH_CDB_APP_KEY_COUNT];
76
77 struct bt_mesh_cdb bt_mesh_cdb = {
78 .nodes = {
79 [0 ... (CONFIG_BT_MESH_CDB_NODE_COUNT - 1)] = {
80 .addr = BT_MESH_ADDR_UNASSIGNED,
81 }
82 },
83 .subnets = {
84 [0 ... (CONFIG_BT_MESH_CDB_SUBNET_COUNT - 1)] = {
85 .net_idx = BT_MESH_KEY_UNUSED,
86 }
87 },
88 .app_keys = {
89 [0 ... (CONFIG_BT_MESH_CDB_APP_KEY_COUNT - 1)] = {
90 .net_idx = BT_MESH_KEY_UNUSED,
91 }
92 },
93 };
94
95 /*
96 * Check if an address range from addr_start for addr_start + num_elem - 1 is
97 * free for use. When a conflict is found, next will be set to the next address
98 * available after the conflicting range and -EAGAIN will be returned.
99 */
addr_is_free(uint16_t addr_start,uint8_t num_elem,uint16_t * next)100 static int addr_is_free(uint16_t addr_start, uint8_t num_elem, uint16_t *next)
101 {
102 uint16_t addr_end = addr_start + num_elem - 1;
103 uint16_t other_start, other_end;
104 int i;
105
106 if (!BT_MESH_ADDR_IS_UNICAST(addr_start) ||
107 !BT_MESH_ADDR_IS_UNICAST(addr_end) ||
108 num_elem == 0) {
109 return -EINVAL;
110 }
111
112 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
113 struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
114
115 if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
116 continue;
117 }
118
119 other_start = node->addr;
120 other_end = other_start + node->num_elem - 1;
121
122 if (!(addr_end < other_start || addr_start > other_end)) {
123 if (next) {
124 *next = other_end + 1;
125 }
126
127 return -EAGAIN;
128 }
129 }
130
131 return 0;
132 }
133
134 /*
135 * Find the lowest possible starting address that can fit num_elem elements. If
136 * a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be
137 * returned. Otherwise the first address in the range is returned.
138 *
139 * NOTE: This is quite an ineffective algorithm as it might need to look
140 * through the array of nodes N+2 times. A more effective algorithm
141 * could be used if the nodes were stored in a sorted list.
142 */
find_lowest_free_addr(uint8_t num_elem)143 static uint16_t find_lowest_free_addr(uint8_t num_elem)
144 {
145 uint16_t addr = 1, next;
146 int err, i;
147
148 /*
149 * It takes a maximum of node count + 2 to find a free address if there
150 * is any. +1 for our own address and +1 for making sure that the
151 * address range is valid.
152 */
153 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes) + 2; ++i) {
154 err = addr_is_free(addr, num_elem, &next);
155 if (err == 0) {
156 break;
157 } else if (err != -EAGAIN) {
158 addr = BT_MESH_ADDR_UNASSIGNED;
159 break;
160 }
161
162 addr = next;
163 }
164
165 return addr;
166 }
167
cdb_net_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)168 static int cdb_net_set(const char *name, size_t len_rd,
169 settings_read_cb read_cb, void *cb_arg)
170 {
171 struct net_val net;
172 int err;
173
174 if (len_rd == 0) {
175 BT_DBG("val (null)");
176 return 0;
177 }
178
179 err = bt_mesh_settings_set(read_cb, cb_arg, &net, sizeof(net));
180 if (err) {
181 BT_ERR("Failed to set \'cdb_net\'");
182 return err;
183 }
184
185 bt_mesh_cdb.iv_index = net.iv_index;
186
187 if (net.iv_update) {
188 atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS);
189 }
190
191 atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
192
193 return 0;
194 }
195
cdb_node_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)196 static int cdb_node_set(const char *name, size_t len_rd,
197 settings_read_cb read_cb, void *cb_arg)
198 {
199 struct bt_mesh_cdb_node *node;
200 struct node_val val;
201 uint16_t addr;
202 int err;
203
204 if (!name) {
205 BT_ERR("Insufficient number of arguments");
206 return -ENOENT;
207 }
208
209 addr = strtol(name, NULL, 16);
210
211 if (len_rd == 0) {
212 BT_DBG("val (null)");
213 BT_DBG("Deleting node 0x%04x", addr);
214
215 node = bt_mesh_cdb_node_get(addr);
216 if (node) {
217 bt_mesh_cdb_node_del(node, false);
218 }
219
220 return 0;
221 }
222
223 err = bt_mesh_settings_set(read_cb, cb_arg, &val, sizeof(val));
224 if (err) {
225 BT_ERR("Failed to set \'node\'");
226 return err;
227 }
228
229 node = bt_mesh_cdb_node_get(addr);
230 if (!node) {
231 node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem,
232 val.net_idx);
233 }
234
235 if (!node) {
236 BT_ERR("No space for a new node");
237 return -ENOMEM;
238 }
239
240 if (val.flags & F_NODE_CONFIGURED) {
241 atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED);
242 }
243
244 memcpy(node->uuid, val.uuid, 16);
245 memcpy(node->dev_key, val.dev_key, 16);
246
247 BT_DBG("Node 0x%04x recovered from storage", addr);
248
249 return 0;
250 }
251
cdb_subnet_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)252 static int cdb_subnet_set(const char *name, size_t len_rd,
253 settings_read_cb read_cb, void *cb_arg)
254 {
255 struct bt_mesh_cdb_subnet *sub;
256 struct net_key_val key;
257 uint16_t net_idx;
258 int err;
259
260 if (!name) {
261 BT_ERR("Insufficient number of arguments");
262 return -ENOENT;
263 }
264
265 net_idx = strtol(name, NULL, 16);
266 sub = bt_mesh_cdb_subnet_get(net_idx);
267
268 if (len_rd == 0) {
269 BT_DBG("val (null)");
270 if (!sub) {
271 BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
272 return -ENOENT;
273 }
274
275 BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
276 bt_mesh_cdb_subnet_del(sub, false);
277 return 0;
278 }
279
280 err = bt_mesh_settings_set(read_cb, cb_arg, &key, sizeof(key));
281 if (err) {
282 BT_ERR("Failed to set \'net-key\'");
283 return err;
284 }
285
286 if (sub) {
287 BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx);
288
289 sub->kr_phase = key.kr_phase;
290 memcpy(sub->keys[0].net_key, &key.val[0], 16);
291 memcpy(sub->keys[1].net_key, &key.val[1], 16);
292
293 return 0;
294 }
295
296 sub = bt_mesh_cdb_subnet_alloc(net_idx);
297 if (!sub) {
298 BT_ERR("No space to allocate a new subnet");
299 return -ENOMEM;
300 }
301
302 sub->kr_phase = key.kr_phase;
303 memcpy(sub->keys[0].net_key, &key.val[0], 16);
304 memcpy(sub->keys[1].net_key, &key.val[1], 16);
305
306 BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
307
308 return 0;
309 }
310
cdb_app_key_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)311 static int cdb_app_key_set(const char *name, size_t len_rd,
312 settings_read_cb read_cb, void *cb_arg)
313 {
314 struct bt_mesh_cdb_app_key *app;
315 struct app_key_val key;
316 uint16_t app_idx;
317 int err;
318
319 if (!name) {
320 BT_ERR("Insufficient number of arguments");
321 return -ENOENT;
322 }
323
324 app_idx = strtol(name, NULL, 16);
325
326 if (len_rd == 0) {
327 BT_DBG("val (null)");
328 BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
329
330 app = bt_mesh_cdb_app_key_get(app_idx);
331 if (app) {
332 bt_mesh_cdb_app_key_del(app, false);
333 }
334
335 return 0;
336 }
337
338 err = bt_mesh_settings_set(read_cb, cb_arg, &key, sizeof(key));
339 if (err) {
340 BT_ERR("Failed to set \'app-key\'");
341 return err;
342 }
343
344 app = bt_mesh_cdb_app_key_get(app_idx);
345 if (!app) {
346 app = bt_mesh_cdb_app_key_alloc(key.net_idx, app_idx);
347 }
348
349 if (!app) {
350 BT_ERR("No space for a new app key");
351 return -ENOMEM;
352 }
353
354 memcpy(app->keys[0].app_key, key.val[0], 16);
355 memcpy(app->keys[1].app_key, key.val[1], 16);
356
357 BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
358
359 return 0;
360 }
361
cdb_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)362 static int cdb_set(const char *name, size_t len_rd,
363 settings_read_cb read_cb, void *cb_arg)
364 {
365 int len;
366 const char *next;
367
368 if (!name) {
369 BT_ERR("Insufficient number of arguments");
370 return -ENOENT;
371 }
372
373 if (!strcmp(name, "Net")) {
374 return cdb_net_set(name, len_rd, read_cb, cb_arg);
375 }
376
377
378 len = settings_name_next(name, &next);
379
380 if (!next) {
381 BT_ERR("Insufficient number of arguments");
382 return -ENOENT;
383 }
384
385 if (!strncmp(name, "Node", len)) {
386 return cdb_node_set(next, len_rd, read_cb, cb_arg);
387 }
388
389 if (!strncmp(name, "Subnet", len)) {
390 return cdb_subnet_set(next, len_rd, read_cb, cb_arg);
391 }
392
393 if (!strncmp(name, "AppKey", len)) {
394 return cdb_app_key_set(next, len_rd, read_cb, cb_arg);
395 }
396
397 BT_WARN("Unknown module key %s", name);
398 return -ENOENT;
399 }
400
401 BT_MESH_SETTINGS_DEFINE(cdb, "cdb", cdb_set);
402
store_cdb_node(const struct bt_mesh_cdb_node * node)403 static void store_cdb_node(const struct bt_mesh_cdb_node *node)
404 {
405 struct node_val val;
406 char path[30];
407 int err;
408
409 val.net_idx = node->net_idx;
410 val.num_elem = node->num_elem;
411 val.flags = 0;
412
413 if (atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) {
414 val.flags |= F_NODE_CONFIGURED;
415 }
416
417 memcpy(val.uuid, node->uuid, 16);
418 memcpy(val.dev_key, node->dev_key, 16);
419
420 snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", node->addr);
421
422 err = settings_save_one(path, &val, sizeof(val));
423 if (err) {
424 BT_ERR("Failed to store Node %s value", log_strdup(path));
425 } else {
426 BT_DBG("Stored Node %s value", log_strdup(path));
427 }
428 }
429
clear_cdb_node(uint16_t addr)430 static void clear_cdb_node(uint16_t addr)
431 {
432 char path[30];
433 int err;
434
435 BT_DBG("Node 0x%04x", addr);
436
437 snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", addr);
438 err = settings_delete(path);
439 if (err) {
440 BT_ERR("Failed to clear Node 0x%04x", addr);
441 } else {
442 BT_DBG("Cleared Node 0x%04x", addr);
443 }
444 }
445
store_cdb_subnet(const struct bt_mesh_cdb_subnet * sub)446 static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub)
447 {
448 struct net_key_val key;
449 char path[30];
450 int err;
451
452 BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
453 bt_hex(sub->keys[0].net_key, 16));
454
455 memcpy(&key.val[0], sub->keys[0].net_key, 16);
456 memcpy(&key.val[1], sub->keys[1].net_key, 16);
457 key.kr_flag = 0U; /* Deprecated */
458 key.kr_phase = sub->kr_phase;
459
460 snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", sub->net_idx);
461
462 err = settings_save_one(path, &key, sizeof(key));
463 if (err) {
464 BT_ERR("Failed to store Subnet value");
465 } else {
466 BT_DBG("Stored Subnet value");
467 }
468 }
469
clear_cdb_subnet(uint16_t net_idx)470 static void clear_cdb_subnet(uint16_t net_idx)
471 {
472 char path[30];
473 int err;
474
475 BT_DBG("NetKeyIndex 0x%03x", net_idx);
476
477 snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", net_idx);
478 err = settings_delete(path);
479 if (err) {
480 BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx);
481 } else {
482 BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx);
483 }
484 }
485
store_cdb_app_key(const struct bt_mesh_cdb_app_key * app)486 static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app)
487 {
488 struct app_key_val key;
489 char path[30];
490 int err;
491
492 key.net_idx = app->net_idx;
493 key.updated = false;
494 memcpy(key.val[0], app->keys[0].app_key, 16);
495 memcpy(key.val[1], app->keys[1].app_key, 16);
496
497 snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app->app_idx);
498
499 err = settings_save_one(path, &key, sizeof(key));
500 if (err) {
501 BT_ERR("Failed to store AppKey %s value", log_strdup(path));
502 } else {
503 BT_DBG("Stored AppKey %s value", log_strdup(path));
504 }
505 }
506
clear_cdb_app_key(uint16_t app_idx)507 static void clear_cdb_app_key(uint16_t app_idx)
508 {
509 char path[30];
510 int err;
511
512 snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app_idx);
513 err = settings_delete(path);
514 if (err) {
515 BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx);
516 } else {
517 BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx);
518 }
519 }
520
schedule_cdb_store(int flag)521 static void schedule_cdb_store(int flag)
522 {
523 atomic_set_bit(bt_mesh_cdb.flags, flag);
524 bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CDB_PENDING);
525 }
526
update_cdb_net_settings(void)527 static void update_cdb_net_settings(void)
528 {
529 schedule_cdb_store(BT_MESH_CDB_SUBNET_PENDING);
530 }
531
cdb_node_update_find(uint16_t addr,struct node_update ** free_slot)532 static struct node_update *cdb_node_update_find(uint16_t addr,
533 struct node_update **free_slot)
534 {
535 struct node_update *match;
536 int i;
537
538 match = NULL;
539 *free_slot = NULL;
540
541 for (i = 0; i < ARRAY_SIZE(cdb_node_updates); i++) {
542 struct node_update *update = &cdb_node_updates[i];
543
544 if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
545 *free_slot = update;
546 continue;
547 }
548
549 if (update->addr == addr) {
550 match = update;
551 }
552 }
553
554 return match;
555 }
556
update_cdb_node_settings(const struct bt_mesh_cdb_node * node,bool store)557 static void update_cdb_node_settings(const struct bt_mesh_cdb_node *node,
558 bool store)
559 {
560 struct node_update *update, *free_slot;
561
562 BT_DBG("Node 0x%04x", node->addr);
563
564 update = cdb_node_update_find(node->addr, &free_slot);
565 if (update) {
566 update->clear = !store;
567 schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
568 return;
569 }
570
571 if (!free_slot) {
572 if (store) {
573 store_cdb_node(node);
574 } else {
575 clear_cdb_node(node->addr);
576 }
577 return;
578 }
579
580 free_slot->addr = node->addr;
581 free_slot->clear = !store;
582
583 schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
584 }
585
cdb_key_update_find(bool app_key,uint16_t key_idx,struct key_update ** free_slot)586 static struct key_update *cdb_key_update_find(bool app_key, uint16_t key_idx,
587 struct key_update **free_slot)
588 {
589 struct key_update *match;
590 int i;
591
592 match = NULL;
593 *free_slot = NULL;
594
595 for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
596 struct key_update *update = &cdb_key_updates[i];
597
598 if (!update->valid) {
599 *free_slot = update;
600 continue;
601 }
602
603 if (update->app_key != app_key) {
604 continue;
605 }
606
607 if (update->key_idx == key_idx) {
608 match = update;
609 }
610 }
611
612 return match;
613 }
614
update_cdb_subnet_settings(const struct bt_mesh_cdb_subnet * sub,bool store)615 static void update_cdb_subnet_settings(const struct bt_mesh_cdb_subnet *sub,
616 bool store)
617 {
618 struct key_update *update, *free_slot;
619 uint8_t clear = store ? 0U : 1U;
620
621 BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
622
623 update = cdb_key_update_find(false, sub->net_idx, &free_slot);
624 if (update) {
625 update->clear = clear;
626 schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
627 return;
628 }
629
630 if (!free_slot) {
631 if (store) {
632 store_cdb_subnet(sub);
633 } else {
634 clear_cdb_subnet(sub->net_idx);
635 }
636 return;
637 }
638
639 free_slot->valid = 1U;
640 free_slot->key_idx = sub->net_idx;
641 free_slot->app_key = 0U;
642 free_slot->clear = clear;
643
644 schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
645 }
646
update_cdb_app_key_settings(const struct bt_mesh_cdb_app_key * key,bool store)647 static void update_cdb_app_key_settings(const struct bt_mesh_cdb_app_key *key,
648 bool store)
649 {
650 struct key_update *update, *free_slot;
651 uint8_t clear = store ? 0U : 1U;
652
653 BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
654
655 update = cdb_key_update_find(true, key->app_idx, &free_slot);
656 if (update) {
657 update->clear = clear;
658 schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
659 return;
660 }
661
662 if (!free_slot) {
663 if (store) {
664 store_cdb_app_key(key);
665 } else {
666 clear_cdb_app_key(key->app_idx);
667 }
668
669 return;
670 }
671
672 free_slot->valid = 1U;
673 free_slot->key_idx = key->app_idx;
674 free_slot->app_key = 1U;
675 free_slot->clear = clear;
676
677 schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
678 }
679
bt_mesh_cdb_create(const uint8_t key[16])680 int bt_mesh_cdb_create(const uint8_t key[16])
681 {
682 struct bt_mesh_cdb_subnet *sub;
683
684 if (atomic_test_and_set_bit(bt_mesh_cdb.flags,
685 BT_MESH_CDB_VALID)) {
686 return -EALREADY;
687 }
688
689 sub = bt_mesh_cdb_subnet_alloc(BT_MESH_KEY_PRIMARY);
690 if (sub == NULL) {
691 return -ENOMEM;
692 }
693
694 memcpy(sub->keys[0].net_key, key, 16);
695 bt_mesh_cdb.iv_index = 0;
696
697 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
698 update_cdb_net_settings();
699 update_cdb_subnet_settings(sub, true);
700 }
701
702 return 0;
703 }
704
bt_mesh_cdb_clear(void)705 void bt_mesh_cdb_clear(void)
706 {
707 int i;
708
709 atomic_clear_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
710
711 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
712 if (bt_mesh_cdb.nodes[i].addr != BT_MESH_ADDR_UNASSIGNED) {
713 bt_mesh_cdb_node_del(&bt_mesh_cdb.nodes[i], true);
714 }
715 }
716
717 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
718 if (bt_mesh_cdb.subnets[i].net_idx != BT_MESH_KEY_UNUSED) {
719 bt_mesh_cdb_subnet_del(&bt_mesh_cdb.subnets[i], true);
720 }
721 }
722
723 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
724 if (bt_mesh_cdb.app_keys[i].net_idx != BT_MESH_KEY_UNUSED) {
725 bt_mesh_cdb_app_key_del(&bt_mesh_cdb.app_keys[i], true);
726 }
727 }
728
729 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
730 update_cdb_net_settings();
731 }
732 }
733
bt_mesh_cdb_iv_update(uint32_t iv_index,bool iv_update)734 void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update)
735 {
736 BT_DBG("Updating IV index to %d\n", iv_index);
737
738 bt_mesh_cdb.iv_index = iv_index;
739
740 atomic_set_bit_to(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS,
741 iv_update);
742
743 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
744 update_cdb_net_settings();
745 }
746 }
747
bt_mesh_cdb_subnet_alloc(uint16_t net_idx)748 struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx)
749 {
750 struct bt_mesh_cdb_subnet *sub;
751 int i;
752
753 if (bt_mesh_cdb_subnet_get(net_idx) != NULL) {
754 return NULL;
755 }
756
757 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
758 sub = &bt_mesh_cdb.subnets[i];
759
760 if (sub->net_idx != BT_MESH_KEY_UNUSED) {
761 continue;
762 }
763
764 sub->net_idx = net_idx;
765
766 return sub;
767 }
768
769 return NULL;
770 }
771
bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet * sub,bool store)772 void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store)
773 {
774 BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
775
776 if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
777 update_cdb_subnet_settings(sub, false);
778 }
779
780 sub->net_idx = BT_MESH_KEY_UNUSED;
781 memset(sub->keys, 0, sizeof(sub->keys));
782 }
783
bt_mesh_cdb_subnet_get(uint16_t net_idx)784 struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx)
785 {
786 int i;
787
788 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
789 if (bt_mesh_cdb.subnets[i].net_idx == net_idx) {
790 return &bt_mesh_cdb.subnets[i];
791 }
792 }
793
794 return NULL;
795 }
796
bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet * sub)797 void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub)
798 {
799 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
800 update_cdb_subnet_settings(sub, true);
801 }
802 }
803
bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet * sub)804 uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub)
805 {
806 uint8_t flags = 0x00;
807
808 if (sub && SUBNET_KEY_TX_IDX(sub)) {
809 flags |= BT_MESH_NET_FLAG_KR;
810 }
811
812 if (atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS)) {
813 flags |= BT_MESH_NET_FLAG_IVU;
814 }
815
816 return flags;
817 }
818
bt_mesh_cdb_node_alloc(const uint8_t uuid[16],uint16_t addr,uint8_t num_elem,uint16_t net_idx)819 struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
820 uint8_t num_elem, uint16_t net_idx)
821 {
822 int i;
823
824 if (addr == BT_MESH_ADDR_UNASSIGNED) {
825 addr = find_lowest_free_addr(num_elem);
826 if (addr == BT_MESH_ADDR_UNASSIGNED) {
827 return NULL;
828 }
829 } else if (addr_is_free(addr, num_elem, NULL) < 0) {
830 BT_DBG("Address range 0x%04x-0x%04x is not free", addr,
831 addr + num_elem - 1);
832 return NULL;
833 }
834
835 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
836 struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
837
838 if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
839 memcpy(node->uuid, uuid, 16);
840 node->addr = addr;
841 node->num_elem = num_elem;
842 node->net_idx = net_idx;
843 atomic_set(node->flags, 0);
844 return node;
845 }
846 }
847
848 return NULL;
849 }
850
bt_mesh_cdb_node_del(struct bt_mesh_cdb_node * node,bool store)851 void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store)
852 {
853 BT_DBG("Node addr 0x%04x store %u", node->addr, store);
854
855 if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
856 update_cdb_node_settings(node, false);
857 }
858
859 node->addr = BT_MESH_ADDR_UNASSIGNED;
860 memset(node->dev_key, 0, sizeof(node->dev_key));
861 }
862
bt_mesh_cdb_node_get(uint16_t addr)863 struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr)
864 {
865 int i;
866
867 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
868 struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
869
870 if (addr >= node->addr &&
871 addr <= node->addr + node->num_elem - 1) {
872 return node;
873 }
874 }
875
876 return NULL;
877 }
878
bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node * node)879 void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node)
880 {
881 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
882 update_cdb_node_settings(node, true);
883 }
884 }
885
bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func,void * user_data)886 void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data)
887 {
888 int i;
889
890 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
891 if (bt_mesh_cdb.nodes[i].addr == BT_MESH_ADDR_UNASSIGNED) {
892 continue;
893 }
894
895 if (func(&bt_mesh_cdb.nodes[i], user_data) ==
896 BT_MESH_CDB_ITER_STOP) {
897 break;
898 }
899 }
900 }
901
bt_mesh_cdb_app_key_alloc(uint16_t net_idx,uint16_t app_idx)902 struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
903 uint16_t app_idx)
904 {
905 struct bt_mesh_cdb_app_key *key;
906 int i;
907
908 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
909 key = &bt_mesh_cdb.app_keys[i];
910
911 if (key->net_idx != BT_MESH_KEY_UNUSED) {
912 continue;
913 }
914
915 key->net_idx = net_idx;
916 key->app_idx = app_idx;
917
918 return key;
919 }
920
921 return NULL;
922 }
923
bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key * key,bool store)924 void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store)
925 {
926 BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
927
928 if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
929 update_cdb_app_key_settings(key, false);
930 }
931
932 key->net_idx = BT_MESH_KEY_UNUSED;
933 memset(key->keys, 0, sizeof(key->keys));
934 }
935
bt_mesh_cdb_app_key_get(uint16_t app_idx)936 struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx)
937 {
938 int i;
939
940 for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); i++) {
941 struct bt_mesh_cdb_app_key *key = &bt_mesh_cdb.app_keys[i];
942
943 if (key->net_idx != BT_MESH_KEY_UNUSED &&
944 key->app_idx == app_idx) {
945 return key;
946 }
947 }
948
949 return NULL;
950 }
951
bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key * key)952 void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key)
953 {
954 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
955 update_cdb_app_key_settings(key, true);
956 }
957 }
958
clear_cdb_net(void)959 static void clear_cdb_net(void)
960 {
961 int err;
962
963 err = settings_delete("bt/mesh/cdb/Net");
964 if (err) {
965 BT_ERR("Failed to clear Network");
966 } else {
967 BT_DBG("Cleared Network");
968 }
969 }
970
store_cdb_pending_net(void)971 static void store_cdb_pending_net(void)
972 {
973 struct net_val net;
974 int err;
975
976 BT_DBG("");
977
978 net.iv_index = bt_mesh_cdb.iv_index;
979 net.iv_update = atomic_test_bit(bt_mesh_cdb.flags,
980 BT_MESH_CDB_IVU_IN_PROGRESS);
981
982 err = settings_save_one("bt/mesh/cdb/Net", &net, sizeof(net));
983 if (err) {
984 BT_ERR("Failed to store Network value");
985 } else {
986 BT_DBG("Stored Network value");
987 }
988 }
989
store_cdb_pending_nodes(void)990 static void store_cdb_pending_nodes(void)
991 {
992 int i;
993
994 for (i = 0; i < ARRAY_SIZE(cdb_node_updates); ++i) {
995 struct node_update *update = &cdb_node_updates[i];
996
997 if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
998 continue;
999 }
1000
1001 BT_DBG("addr: 0x%04x, clear: %d", update->addr, update->clear);
1002
1003 if (update->clear) {
1004 clear_cdb_node(update->addr);
1005 } else {
1006 struct bt_mesh_cdb_node *node;
1007
1008 node = bt_mesh_cdb_node_get(update->addr);
1009 if (node) {
1010 store_cdb_node(node);
1011 } else {
1012 BT_WARN("Node 0x%04x not found", update->addr);
1013 }
1014 }
1015
1016 update->addr = BT_MESH_ADDR_UNASSIGNED;
1017 }
1018 }
1019
store_cdb_pending_keys(void)1020 static void store_cdb_pending_keys(void)
1021 {
1022 int i;
1023
1024 for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
1025 struct key_update *update = &cdb_key_updates[i];
1026
1027 if (!update->valid) {
1028 continue;
1029 }
1030
1031 if (update->clear) {
1032 if (update->app_key) {
1033 clear_cdb_app_key(update->key_idx);
1034 } else {
1035 clear_cdb_subnet(update->key_idx);
1036 }
1037 } else {
1038 if (update->app_key) {
1039 struct bt_mesh_cdb_app_key *key;
1040
1041 key = bt_mesh_cdb_app_key_get(update->key_idx);
1042 if (key) {
1043 store_cdb_app_key(key);
1044 } else {
1045 BT_WARN("AppKeyIndex 0x%03x not found",
1046 update->key_idx);
1047 }
1048 } else {
1049 struct bt_mesh_cdb_subnet *sub;
1050
1051 sub = bt_mesh_cdb_subnet_get(update->key_idx);
1052 if (sub) {
1053 store_cdb_subnet(sub);
1054 } else {
1055 BT_WARN("NetKeyIndex 0x%03x not found",
1056 update->key_idx);
1057 }
1058 }
1059 }
1060
1061 update->valid = 0U;
1062 }
1063 }
1064
bt_mesh_cdb_pending_store(void)1065 void bt_mesh_cdb_pending_store(void)
1066 {
1067 if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
1068 BT_MESH_CDB_SUBNET_PENDING)) {
1069 if (atomic_test_bit(bt_mesh_cdb.flags,
1070 BT_MESH_CDB_VALID)) {
1071 store_cdb_pending_net();
1072 } else {
1073 clear_cdb_net();
1074 }
1075 }
1076
1077 if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
1078 BT_MESH_CDB_NODES_PENDING)) {
1079 store_cdb_pending_nodes();
1080 }
1081
1082 if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
1083 BT_MESH_CDB_KEYS_PENDING)) {
1084 store_cdb_pending_keys();
1085 }
1086 }
1087