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