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