1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/bluetooth/mesh.h>
8 #include <zephyr/bluetooth/bluetooth.h>
9 
10 #include "mesh.h"
11 #include "net.h"
12 #include "rpl.h"
13 #include "beacon.h"
14 #include "settings.h"
15 #include "heartbeat.h"
16 #include "friend.h"
17 #include "cfg.h"
18 #include "od_priv_proxy.h"
19 #include "priv_beacon.h"
20 
21 #define LOG_LEVEL CONFIG_BT_MESH_CFG_LOG_LEVEL
22 #include <zephyr/logging/log.h>
23 LOG_MODULE_REGISTER(bt_mesh_cfg);
24 
25 /* Miscellaneous configuration server model states */
26 struct cfg_val {
27 	uint8_t net_transmit;
28 	uint8_t relay;
29 	uint8_t relay_retransmit;
30 	uint8_t beacon;
31 	uint8_t gatt_proxy;
32 	uint8_t frnd;
33 	uint8_t default_ttl;
34 };
35 
bt_mesh_beacon_set(bool beacon)36 void bt_mesh_beacon_set(bool beacon)
37 {
38 	if (atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON) == beacon) {
39 		return;
40 	}
41 
42 	atomic_set_bit_to(bt_mesh.flags, BT_MESH_BEACON, beacon);
43 
44 	if (beacon) {
45 		bt_mesh_beacon_enable();
46 	} else {
47 		/* Beacon timer will stop automatically when all beacons are disabled. */
48 	}
49 
50 	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
51 	    atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
52 		bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
53 	}
54 }
55 
bt_mesh_beacon_enabled(void)56 bool bt_mesh_beacon_enabled(void)
57 {
58 	return atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON);
59 }
60 
feature_set(int feature_flag,enum bt_mesh_feat_state state)61 static int feature_set(int feature_flag, enum bt_mesh_feat_state state)
62 {
63 	if (state != BT_MESH_FEATURE_DISABLED &&
64 	    state != BT_MESH_FEATURE_ENABLED) {
65 		return -EINVAL;
66 	}
67 
68 	if (atomic_test_bit(bt_mesh.flags, feature_flag) ==
69 	    (state == BT_MESH_FEATURE_ENABLED)) {
70 		return -EALREADY;
71 	}
72 
73 	atomic_set_bit_to(bt_mesh.flags, feature_flag,
74 			  (state == BT_MESH_FEATURE_ENABLED));
75 
76 	return 0;
77 }
78 
feature_get(int feature_flag)79 static enum bt_mesh_feat_state feature_get(int feature_flag)
80 {
81 	return atomic_test_bit(bt_mesh.flags, feature_flag) ?
82 		       BT_MESH_FEATURE_ENABLED :
83 		       BT_MESH_FEATURE_DISABLED;
84 }
85 
bt_mesh_priv_beacon_set(enum bt_mesh_feat_state priv_beacon)86 int bt_mesh_priv_beacon_set(enum bt_mesh_feat_state priv_beacon)
87 {
88 	int err;
89 
90 	if (!IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACONS)) {
91 		return -ENOTSUP;
92 	}
93 
94 	err = feature_set(BT_MESH_PRIV_BEACON, priv_beacon);
95 	if (err) {
96 		return err;
97 	}
98 
99 	if (priv_beacon == BT_MESH_FEATURE_ENABLED) {
100 		bt_mesh_beacon_enable();
101 	} else {
102 		/* Beacon timer will stop automatically when all beacons are disabled. */
103 	}
104 
105 	if (IS_ENABLED(CONFIG_BT_SETTINGS) && IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACON_SRV) &&
106 	    atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
107 		bt_mesh_priv_beacon_srv_store_schedule();
108 	}
109 
110 	return 0;
111 }
112 
bt_mesh_priv_beacon_get(void)113 enum bt_mesh_feat_state bt_mesh_priv_beacon_get(void)
114 {
115 	if (!IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACONS)) {
116 		return BT_MESH_FEATURE_NOT_SUPPORTED;
117 	}
118 
119 	return feature_get(BT_MESH_PRIV_BEACON);
120 }
121 
bt_mesh_priv_beacon_update_interval_set(uint8_t interval)122 void bt_mesh_priv_beacon_update_interval_set(uint8_t interval)
123 {
124 #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
125 	bt_mesh.priv_beacon_int = interval;
126 #endif
127 }
128 
bt_mesh_priv_beacon_update_interval_get(void)129 uint8_t bt_mesh_priv_beacon_update_interval_get(void)
130 {
131 #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
132 	return bt_mesh.priv_beacon_int;
133 #else
134 	return 0;
135 #endif
136 }
137 
bt_mesh_od_priv_proxy_get(void)138 int bt_mesh_od_priv_proxy_get(void)
139 {
140 #if IS_ENABLED(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)
141 	return bt_mesh.on_demand_state;
142 #else
143 	return -ENOTSUP;
144 #endif
145 }
146 
bt_mesh_od_priv_proxy_set(uint8_t on_demand_proxy)147 int bt_mesh_od_priv_proxy_set(uint8_t on_demand_proxy)
148 {
149 #if !IS_ENABLED(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)
150 	return -ENOTSUP;
151 #else
152 
153 	if (bt_mesh_priv_gatt_proxy_get() != BT_MESH_FEATURE_NOT_SUPPORTED) {
154 		bt_mesh.on_demand_state = on_demand_proxy;
155 	}
156 
157 	if (IS_ENABLED(CONFIG_BT_SETTINGS) && IS_ENABLED(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) &&
158 	    atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
159 		bt_mesh_od_priv_proxy_srv_store_schedule();
160 	}
161 	return 0;
162 #endif
163 }
164 
node_id_is_running(struct bt_mesh_subnet * sub,void * cb_data)165 static bool node_id_is_running(struct bt_mesh_subnet *sub, void *cb_data)
166 {
167 	return sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING;
168 }
169 
bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy)170 int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy)
171 {
172 	int err;
173 
174 	if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
175 		return -ENOTSUP;
176 	}
177 
178 	err = feature_set(BT_MESH_GATT_PROXY, gatt_proxy);
179 	if (err) {
180 		return err;
181 	}
182 
183 	/* The binding from section 4.2.45.1 disables Private GATT Proxy state when non-private
184 	 * state is enabled.
185 	 */
186 	if (gatt_proxy == BT_MESH_FEATURE_ENABLED) {
187 		feature_set(BT_MESH_PRIV_GATT_PROXY, BT_MESH_FEATURE_DISABLED);
188 	}
189 
190 	if ((gatt_proxy == BT_MESH_FEATURE_ENABLED) ||
191 	    (gatt_proxy == BT_MESH_FEATURE_DISABLED &&
192 	     !bt_mesh_subnet_find(node_id_is_running, NULL))) {
193 		bt_mesh_adv_gatt_update();
194 	}
195 
196 	bt_mesh_hb_feature_changed(BT_MESH_FEAT_PROXY);
197 
198 	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
199 	    atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
200 		bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
201 	}
202 
203 	return 0;
204 }
205 
bt_mesh_gatt_proxy_get(void)206 enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void)
207 {
208 	if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
209 		return BT_MESH_FEATURE_NOT_SUPPORTED;
210 	}
211 
212 	return feature_get(BT_MESH_GATT_PROXY);
213 }
214 
bt_mesh_priv_gatt_proxy_set(enum bt_mesh_feat_state priv_gatt_proxy)215 int bt_mesh_priv_gatt_proxy_set(enum bt_mesh_feat_state priv_gatt_proxy)
216 {
217 	int err;
218 
219 	if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) || !IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACONS)) {
220 		return BT_MESH_FEATURE_NOT_SUPPORTED;
221 	}
222 
223 	/* Reverse binding from section 4.2.45.1 doesn't allow to enable private state if
224 	 * non-private state is enabled.
225 	 */
226 	if (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED) {
227 		return BT_MESH_FEATURE_DISABLED;
228 	}
229 
230 	err = feature_set(BT_MESH_PRIV_GATT_PROXY, priv_gatt_proxy);
231 	if (err) {
232 		return err;
233 	}
234 
235 	if (priv_gatt_proxy == BT_MESH_FEATURE_ENABLED) {
236 		/* Re-generate proxy beacon */
237 		bt_mesh_adv_gatt_update();
238 	}
239 
240 	if (IS_ENABLED(CONFIG_BT_SETTINGS) && IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACON_SRV) &&
241 	    atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
242 		bt_mesh_priv_beacon_srv_store_schedule();
243 	}
244 
245 	return 0;
246 }
247 
bt_mesh_priv_gatt_proxy_get(void)248 enum bt_mesh_feat_state bt_mesh_priv_gatt_proxy_get(void)
249 {
250 	if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) || !IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACONS)) {
251 		return BT_MESH_FEATURE_NOT_SUPPORTED;
252 	}
253 
254 	return feature_get(BT_MESH_PRIV_GATT_PROXY);
255 }
256 
bt_mesh_default_ttl_set(uint8_t default_ttl)257 int bt_mesh_default_ttl_set(uint8_t default_ttl)
258 {
259 	if (default_ttl == 1 || default_ttl > BT_MESH_TTL_MAX) {
260 		return -EINVAL;
261 	}
262 
263 	if (default_ttl == bt_mesh.default_ttl) {
264 		return 0;
265 	}
266 
267 	bt_mesh.default_ttl = default_ttl;
268 
269 	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
270 	    atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
271 		bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
272 	}
273 
274 	return 0;
275 }
276 
bt_mesh_default_ttl_get(void)277 uint8_t bt_mesh_default_ttl_get(void)
278 {
279 	return bt_mesh.default_ttl;
280 }
281 
bt_mesh_friend_set(enum bt_mesh_feat_state friendship)282 int bt_mesh_friend_set(enum bt_mesh_feat_state friendship)
283 {
284 	int err;
285 
286 	if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
287 		return -ENOTSUP;
288 	}
289 
290 	err = feature_set(BT_MESH_FRIEND, friendship);
291 	if (err) {
292 		return err;
293 	}
294 
295 	bt_mesh_hb_feature_changed(BT_MESH_FEAT_FRIEND);
296 
297 	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
298 	    atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
299 		bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
300 	}
301 
302 	if (friendship == BT_MESH_FEATURE_DISABLED) {
303 		bt_mesh_friends_clear();
304 	}
305 
306 	return 0;
307 }
308 
bt_mesh_friend_get(void)309 enum bt_mesh_feat_state bt_mesh_friend_get(void)
310 {
311 	if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
312 		return BT_MESH_FEATURE_NOT_SUPPORTED;
313 	}
314 
315 	return feature_get(BT_MESH_FRIEND);
316 }
317 
bt_mesh_net_transmit_set(uint8_t xmit)318 void bt_mesh_net_transmit_set(uint8_t xmit)
319 {
320 	if (bt_mesh.net_xmit == xmit) {
321 		return;
322 	}
323 
324 	bt_mesh.net_xmit = xmit;
325 
326 	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
327 	    atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
328 		bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
329 	}
330 }
331 
bt_mesh_net_transmit_get(void)332 uint8_t bt_mesh_net_transmit_get(void)
333 {
334 	return bt_mesh.net_xmit;
335 }
336 
bt_mesh_relay_set(enum bt_mesh_feat_state relay,uint8_t xmit)337 int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit)
338 {
339 	int err;
340 
341 	if (!IS_ENABLED(CONFIG_BT_MESH_RELAY)) {
342 		return -ENOTSUP;
343 	}
344 
345 	err = feature_set(BT_MESH_RELAY, relay);
346 	if (err == -EINVAL) {
347 		return err;
348 	}
349 
350 	if (err == -EALREADY && bt_mesh.relay_xmit == xmit) {
351 		return -EALREADY;
352 	}
353 
354 	bt_mesh.relay_xmit = xmit;
355 	bt_mesh_hb_feature_changed(BT_MESH_FEAT_RELAY);
356 
357 	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
358 	    atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
359 		bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING);
360 	}
361 
362 	return 0;
363 }
364 
bt_mesh_relay_get(void)365 enum bt_mesh_feat_state bt_mesh_relay_get(void)
366 {
367 	return feature_get(BT_MESH_RELAY);
368 }
369 
bt_mesh_relay_retransmit_get(void)370 uint8_t bt_mesh_relay_retransmit_get(void)
371 {
372 	if (!IS_ENABLED(CONFIG_BT_MESH_RELAY)) {
373 		return 0;
374 	}
375 
376 	return bt_mesh.relay_xmit;
377 }
378 
bt_mesh_fixed_group_match(uint16_t addr)379 bool bt_mesh_fixed_group_match(uint16_t addr)
380 {
381 	/* Check for fixed group addresses */
382 	switch (addr) {
383 	case BT_MESH_ADDR_ALL_NODES:
384 		return true;
385 	case BT_MESH_ADDR_PROXIES:
386 		return (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED);
387 	case BT_MESH_ADDR_FRIENDS:
388 		return (bt_mesh_friend_get() == BT_MESH_FEATURE_ENABLED);
389 	case BT_MESH_ADDR_RELAYS:
390 		return (bt_mesh_relay_get() == BT_MESH_FEATURE_ENABLED);
391 	default:
392 		return false;
393 	}
394 }
395 
bt_mesh_cfg_default_set(void)396 void bt_mesh_cfg_default_set(void)
397 {
398 	bt_mesh.default_ttl = CONFIG_BT_MESH_DEFAULT_TTL;
399 	bt_mesh.net_xmit =
400 		BT_MESH_TRANSMIT(CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT,
401 				 CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL);
402 
403 #if defined(CONFIG_BT_MESH_RELAY)
404 	bt_mesh.relay_xmit =
405 		BT_MESH_TRANSMIT(CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT,
406 				 CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL);
407 #endif
408 
409 	if (IS_ENABLED(CONFIG_BT_MESH_RELAY_ENABLED)) {
410 		atomic_set_bit(bt_mesh.flags, BT_MESH_RELAY);
411 	}
412 
413 	if (IS_ENABLED(CONFIG_BT_MESH_BEACON_ENABLED)) {
414 		atomic_set_bit(bt_mesh.flags, BT_MESH_BEACON);
415 	}
416 
417 	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY_ENABLED)) {
418 		atomic_set_bit(bt_mesh.flags, BT_MESH_GATT_PROXY);
419 	}
420 
421 	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND_ENABLED)) {
422 		atomic_set_bit(bt_mesh.flags, BT_MESH_FRIEND);
423 	}
424 }
425 
cfg_set(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)426 static int cfg_set(const char *name, size_t len_rd,
427 		   settings_read_cb read_cb, void *cb_arg)
428 {
429 	struct cfg_val cfg;
430 	int err;
431 
432 	if (len_rd == 0) {
433 		LOG_DBG("Cleared configuration state");
434 		return 0;
435 	}
436 
437 	err = bt_mesh_settings_set(read_cb, cb_arg, &cfg, sizeof(cfg));
438 	if (err) {
439 		LOG_ERR("Failed to set \'cfg\'");
440 		return err;
441 	}
442 
443 	bt_mesh_net_transmit_set(cfg.net_transmit);
444 	bt_mesh_relay_set(cfg.relay, cfg.relay_retransmit);
445 	bt_mesh_beacon_set(cfg.beacon);
446 	bt_mesh_gatt_proxy_set(cfg.gatt_proxy);
447 	bt_mesh_friend_set(cfg.frnd);
448 	bt_mesh_default_ttl_set(cfg.default_ttl);
449 
450 	LOG_DBG("Restored configuration state");
451 
452 	return 0;
453 }
454 
455 BT_MESH_SETTINGS_DEFINE(cfg, "Cfg", cfg_set);
456 
clear_cfg(void)457 static void clear_cfg(void)
458 {
459 	int err;
460 
461 	err = settings_delete("bt/mesh/Cfg");
462 	if (err) {
463 		LOG_ERR("Failed to clear configuration (err: %d)", err);
464 	} else {
465 		LOG_DBG("Cleared configuration");
466 	}
467 }
468 
store_pending_cfg(void)469 static void store_pending_cfg(void)
470 {
471 	struct cfg_val val;
472 	int err;
473 
474 	val.net_transmit = bt_mesh_net_transmit_get();
475 	val.relay = bt_mesh_relay_get();
476 	val.relay_retransmit = bt_mesh_relay_retransmit_get();
477 	val.beacon = bt_mesh_beacon_enabled();
478 	val.gatt_proxy = bt_mesh_gatt_proxy_get();
479 	val.frnd = bt_mesh_friend_get();
480 	val.default_ttl = bt_mesh_default_ttl_get();
481 
482 	err = settings_save_one("bt/mesh/Cfg", &val, sizeof(val));
483 	if (err) {
484 		LOG_ERR("Failed to store configuration value");
485 	} else {
486 		LOG_DBG("Stored configuration value");
487 		LOG_HEXDUMP_DBG(&val, sizeof(val), "raw value");
488 	}
489 }
490 
bt_mesh_cfg_pending_store(void)491 void bt_mesh_cfg_pending_store(void)
492 {
493 	if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
494 		store_pending_cfg();
495 	} else {
496 		clear_cfg();
497 	}
498 }
499