1 /*
2 * Copyright (c) 2017 Intel Corporation
3 * Copyright (c) 2021 Lingao Meng
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/byteorder.h>
10 #include <zephyr/sys/iterable_sections.h>
11 #include <zephyr/net_buf.h>
12 #include <zephyr/bluetooth/bluetooth.h>
13 #include <zephyr/bluetooth/conn.h>
14 #include <zephyr/bluetooth/gatt.h>
15 #include <zephyr/bluetooth/mesh.h>
16 #include <zephyr/sys/util.h>
17
18 #include <zephyr/bluetooth/hci.h>
19
20 #include "common/bt_str.h"
21
22 #include "mesh.h"
23 #include "net.h"
24 #include "rpl.h"
25 #include "transport.h"
26 #include "prov.h"
27 #include "beacon.h"
28 #include "foundation.h"
29 #include "access.h"
30 #include "proxy.h"
31 #include "gatt.h"
32 #include "proxy_msg.h"
33 #include "crypto.h"
34
35 #define LOG_LEVEL CONFIG_BT_MESH_PROXY_LOG_LEVEL
36 #include <zephyr/logging/log.h>
37 LOG_MODULE_REGISTER(bt_mesh_gatt);
38
39 /* Interval to update random value in (10 minutes).
40 *
41 * Defined in the Bluetooth Mesh Specification v1.1, Section 7.2.2.2.4.
42 */
43 #define PROXY_RANDOM_UPDATE_INTERVAL (10 * 60 * MSEC_PER_SEC)
44
45 #define ADV_OPT_ADDR(private) (IS_ENABLED(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR) ? \
46 BT_LE_ADV_OPT_USE_IDENTITY : (private) ? BT_LE_ADV_OPT_USE_NRPA : 0)
47
48 #define ADV_OPT_PROXY(private) \
49 (BT_LE_ADV_OPT_CONN | BT_LE_ADV_OPT_SCANNABLE | ADV_OPT_ADDR(private))
50
51 static void proxy_send_beacons(struct k_work *work);
52 static int proxy_send(struct bt_conn *conn,
53 const void *data, uint16_t len,
54 bt_gatt_complete_func_t end, void *user_data);
55
56 static struct bt_mesh_proxy_client {
57 struct bt_mesh_proxy_role *cli;
58 uint16_t filter[CONFIG_BT_MESH_PROXY_FILTER_SIZE];
59 enum __packed {
60 NONE,
61 ACCEPT,
62 REJECT,
63 } filter_type;
64 struct k_work send_beacons;
65 #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
66 bool privacy;
67 #endif
68 } clients[CONFIG_BT_MAX_CONN] = {
69 [0 ... (CONFIG_BT_MAX_CONN - 1)] = {
70 .send_beacons = Z_WORK_INITIALIZER(proxy_send_beacons),
71 },
72 };
73
74 static bool service_registered;
75
find_client(struct bt_conn * conn)76 static struct bt_mesh_proxy_client *find_client(struct bt_conn *conn)
77 {
78 return &clients[bt_conn_index(conn)];
79 }
80
gatt_recv(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)81 static ssize_t gatt_recv(struct bt_conn *conn,
82 const struct bt_gatt_attr *attr, const void *buf,
83 uint16_t len, uint16_t offset, uint8_t flags)
84 {
85 const uint8_t *data = buf;
86
87 if (len < 1) {
88 LOG_WRN("Too small Proxy PDU");
89 return -EINVAL;
90 }
91
92 if (PDU_TYPE(data) == BT_MESH_PROXY_PROV) {
93 LOG_WRN("Proxy PDU type doesn't match GATT service");
94 return -EINVAL;
95 }
96
97 return bt_mesh_proxy_msg_recv(conn, buf, len);
98 }
99
100 /* Next subnet in queue to be advertised */
101 static struct bt_mesh_subnet *beacon_sub;
102
filter_set(struct bt_mesh_proxy_client * client,struct net_buf_simple * buf)103 static int filter_set(struct bt_mesh_proxy_client *client,
104 struct net_buf_simple *buf)
105 {
106 uint8_t type;
107
108 if (buf->len < 1) {
109 LOG_WRN("Too short Filter Set message");
110 return -EINVAL;
111 }
112
113 type = net_buf_simple_pull_u8(buf);
114 LOG_DBG("type 0x%02x", type);
115
116 switch (type) {
117 case 0x00:
118 (void)memset(client->filter, 0, sizeof(client->filter));
119 client->filter_type = ACCEPT;
120 break;
121 case 0x01:
122 (void)memset(client->filter, 0, sizeof(client->filter));
123 client->filter_type = REJECT;
124 break;
125 default:
126 LOG_WRN("Prohibited Filter Type 0x%02x", type);
127 return -EINVAL;
128 }
129
130 return 0;
131 }
132
filter_add(struct bt_mesh_proxy_client * client,uint16_t addr)133 static void filter_add(struct bt_mesh_proxy_client *client, uint16_t addr)
134 {
135 int i;
136
137 LOG_DBG("addr 0x%04x", addr);
138
139 if (addr == BT_MESH_ADDR_UNASSIGNED) {
140 return;
141 }
142
143 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
144 if (client->filter[i] == addr) {
145 return;
146 }
147 }
148
149 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
150 if (client->filter[i] == BT_MESH_ADDR_UNASSIGNED) {
151 client->filter[i] = addr;
152 return;
153 }
154 }
155 }
156
filter_remove(struct bt_mesh_proxy_client * client,uint16_t addr)157 static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr)
158 {
159 int i;
160
161 LOG_DBG("addr 0x%04x", addr);
162
163 if (addr == BT_MESH_ADDR_UNASSIGNED) {
164 return;
165 }
166
167 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
168 if (client->filter[i] == addr) {
169 client->filter[i] = BT_MESH_ADDR_UNASSIGNED;
170 return;
171 }
172 }
173 }
174
send_filter_status(struct bt_mesh_proxy_client * client,struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)175 static void send_filter_status(struct bt_mesh_proxy_client *client,
176 struct bt_mesh_net_rx *rx,
177 struct net_buf_simple *buf)
178 {
179 struct bt_mesh_net_tx tx = {
180 .sub = rx->sub,
181 .ctx = &rx->ctx,
182 .src = bt_mesh_primary_addr(),
183 };
184 uint16_t filter_size;
185 int i, err;
186
187 /* Configuration messages always have dst unassigned */
188 tx.ctx->addr = BT_MESH_ADDR_UNASSIGNED;
189
190 net_buf_simple_reset(buf);
191 net_buf_simple_reserve(buf, 10);
192
193 net_buf_simple_add_u8(buf, CFG_FILTER_STATUS);
194
195 if (client->filter_type == ACCEPT) {
196 net_buf_simple_add_u8(buf, 0x00);
197 } else {
198 net_buf_simple_add_u8(buf, 0x01);
199 }
200
201 for (filter_size = 0U, i = 0; i < ARRAY_SIZE(client->filter); i++) {
202 if (client->filter[i] != BT_MESH_ADDR_UNASSIGNED) {
203 filter_size++;
204 }
205 }
206
207 net_buf_simple_add_be16(buf, filter_size);
208
209 LOG_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len));
210
211 err = bt_mesh_net_encode(&tx, buf, BT_MESH_NONCE_PROXY);
212 if (err) {
213 LOG_ERR("Encoding Proxy cfg message failed (err %d)", err);
214 return;
215 }
216
217 err = bt_mesh_proxy_msg_send(client->cli->conn, BT_MESH_PROXY_CONFIG,
218 buf, NULL, NULL);
219 if (err) {
220 LOG_ERR("Failed to send proxy cfg message (err %d)", err);
221 }
222 }
223
proxy_filter_recv(struct bt_conn * conn,struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)224 static void proxy_filter_recv(struct bt_conn *conn,
225 struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
226 {
227 struct bt_mesh_proxy_client *client;
228 uint8_t opcode;
229
230 client = find_client(conn);
231
232 opcode = net_buf_simple_pull_u8(buf);
233 switch (opcode) {
234 case CFG_FILTER_SET:
235 filter_set(client, buf);
236 send_filter_status(client, rx, buf);
237 break;
238 case CFG_FILTER_ADD:
239 while (buf->len >= 2) {
240 uint16_t addr;
241
242 addr = net_buf_simple_pull_be16(buf);
243 filter_add(client, addr);
244 }
245 send_filter_status(client, rx, buf);
246 break;
247 case CFG_FILTER_REMOVE:
248 while (buf->len >= 2) {
249 uint16_t addr;
250
251 addr = net_buf_simple_pull_be16(buf);
252 filter_remove(client, addr);
253 }
254 send_filter_status(client, rx, buf);
255 break;
256 default:
257 LOG_WRN("Unhandled configuration OpCode 0x%02x", opcode);
258 break;
259 }
260 }
261
proxy_cfg(struct bt_mesh_proxy_role * role)262 static void proxy_cfg(struct bt_mesh_proxy_role *role)
263 {
264 NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_NET_MAX_PDU_LEN);
265 struct bt_mesh_net_rx rx;
266 int err;
267
268 err = bt_mesh_net_decode(&role->buf, BT_MESH_NET_IF_PROXY_CFG,
269 &rx, &buf);
270 if (err) {
271 LOG_ERR("Failed to decode Proxy Configuration (err %d)", err);
272 return;
273 }
274
275 rx.local_match = 1U;
276
277 if (bt_mesh_rpl_check(&rx, NULL, false)) {
278 LOG_WRN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", rx.ctx.addr, rx.ctx.recv_dst,
279 rx.seq);
280 return;
281 }
282
283 /* Remove network headers */
284 net_buf_simple_pull(&buf, BT_MESH_NET_HDR_LEN);
285
286 LOG_DBG("%u bytes: %s", buf.len, bt_hex(buf.data, buf.len));
287
288 if (buf.len < 1) {
289 LOG_WRN("Too short proxy configuration PDU");
290 return;
291 }
292
293 proxy_filter_recv(role->conn, &rx, &buf);
294 }
295
proxy_msg_recv(struct bt_mesh_proxy_role * role)296 static void proxy_msg_recv(struct bt_mesh_proxy_role *role)
297 {
298 switch (role->msg_type) {
299 case BT_MESH_PROXY_NET_PDU:
300 LOG_DBG("Mesh Network PDU");
301 bt_mesh_net_recv(&role->buf, 0, BT_MESH_NET_IF_PROXY);
302 break;
303 case BT_MESH_PROXY_BEACON:
304 LOG_DBG("Mesh Beacon PDU");
305 bt_mesh_beacon_recv(&role->buf);
306 break;
307 case BT_MESH_PROXY_CONFIG:
308 LOG_DBG("Mesh Configuration PDU");
309 proxy_cfg(role);
310 break;
311 default:
312 LOG_WRN("Unhandled Message Type 0x%02x", role->msg_type);
313 break;
314 }
315 }
316
beacon_send(struct bt_mesh_proxy_client * client,struct bt_mesh_subnet * sub)317 static int beacon_send(struct bt_mesh_proxy_client *client,
318 struct bt_mesh_subnet *sub)
319 {
320 int err;
321
322 NET_BUF_SIMPLE_DEFINE(buf, 28);
323
324 net_buf_simple_reserve(&buf, 1);
325
326 #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
327 err = bt_mesh_beacon_create(sub, &buf, client->privacy);
328 #else
329 err = bt_mesh_beacon_create(sub, &buf, false);
330 #endif
331 if (err) {
332 return err;
333 }
334
335 return bt_mesh_proxy_msg_send(client->cli->conn, BT_MESH_PROXY_BEACON,
336 &buf, NULL, NULL);
337 }
338
send_beacon_cb(struct bt_mesh_subnet * sub,void * cb_data)339 static bool send_beacon_cb(struct bt_mesh_subnet *sub, void *cb_data)
340 {
341 struct bt_mesh_proxy_client *client = cb_data;
342
343 return beacon_send(client, sub) != 0;
344 }
345
proxy_send_beacons(struct k_work * work)346 static void proxy_send_beacons(struct k_work *work)
347 {
348 struct bt_mesh_proxy_client *client;
349
350 client = CONTAINER_OF(work, struct bt_mesh_proxy_client, send_beacons);
351
352 (void)bt_mesh_subnet_find(send_beacon_cb, client);
353 }
354
bt_mesh_proxy_beacon_send(struct bt_mesh_subnet * sub)355 void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
356 {
357 int i;
358
359 if (!sub) {
360 /* NULL means we send on all subnets */
361 bt_mesh_subnet_foreach(bt_mesh_proxy_beacon_send);
362 return;
363 }
364
365 for (i = 0; i < ARRAY_SIZE(clients); i++) {
366 if (clients[i].cli) {
367 beacon_send(&clients[i], sub);
368 }
369 }
370 }
371
identity_enabled(struct bt_mesh_subnet * sub)372 static void identity_enabled(struct bt_mesh_subnet *sub)
373 {
374 sub->node_id = BT_MESH_NODE_IDENTITY_RUNNING;
375 sub->node_id_start = k_uptime_get_32();
376
377 STRUCT_SECTION_FOREACH(bt_mesh_proxy_cb, cb) {
378 if (cb->identity_enabled) {
379 cb->identity_enabled(sub->net_idx);
380 }
381 }
382 }
383
node_id_start(struct bt_mesh_subnet * sub)384 static void node_id_start(struct bt_mesh_subnet *sub)
385 {
386 #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
387 sub->priv_beacon_ctx.node_id = false;
388 #endif
389
390 identity_enabled(sub);
391 }
392
private_node_id_start(struct bt_mesh_subnet * sub)393 static void private_node_id_start(struct bt_mesh_subnet *sub)
394 {
395 #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
396 sub->priv_beacon_ctx.node_id = true;
397 #endif
398
399 identity_enabled(sub);
400 }
401
bt_mesh_proxy_identity_start(struct bt_mesh_subnet * sub,bool private)402 void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub, bool private)
403 {
404 if (private) {
405 private_node_id_start(sub);
406 } else {
407 node_id_start(sub);
408 }
409
410 /* Prioritize the recently enabled subnet */
411 beacon_sub = sub;
412 }
413
bt_mesh_proxy_identity_stop(struct bt_mesh_subnet * sub)414 void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
415 {
416 sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
417 sub->node_id_start = 0U;
418
419 STRUCT_SECTION_FOREACH(bt_mesh_proxy_cb, cb) {
420 if (cb->identity_disabled) {
421 cb->identity_disabled(sub->net_idx);
422 }
423 }
424 }
425
bt_mesh_proxy_identity_enable(void)426 int bt_mesh_proxy_identity_enable(void)
427 {
428 LOG_DBG("");
429
430 if (!bt_mesh_is_provisioned()) {
431 return -EAGAIN;
432 }
433
434 if (bt_mesh_subnet_foreach(node_id_start)) {
435 bt_mesh_adv_gatt_update();
436 }
437
438 return 0;
439 }
440
bt_mesh_proxy_private_identity_enable(void)441 int bt_mesh_proxy_private_identity_enable(void)
442 {
443 LOG_DBG("");
444
445 if (!IS_ENABLED(CONFIG_BT_MESH_PRIV_BEACONS)) {
446 return -ENOTSUP;
447 }
448
449 if (!bt_mesh_is_provisioned()) {
450 return -EAGAIN;
451 }
452
453 if (bt_mesh_subnet_foreach(private_node_id_start)) {
454 bt_mesh_adv_gatt_update();
455 }
456
457 return 0;
458 }
459
460 #define ENC_ID_LEN 19
461 #define NET_ID_LEN 11
462
463 #define NODE_ID_TIMEOUT (CONFIG_BT_MESH_NODE_ID_TIMEOUT * MSEC_PER_SEC)
464
465 static uint8_t proxy_svc_data[ENC_ID_LEN] = {
466 BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL),
467 };
468
469 static const struct bt_data enc_id_ad[] = {
470 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
471 BT_DATA_BYTES(BT_DATA_UUID16_ALL,
472 BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)),
473 BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, ENC_ID_LEN),
474 };
475
476 static const struct bt_data net_id_ad[] = {
477 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
478 BT_DATA_BYTES(BT_DATA_UUID16_ALL,
479 BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)),
480 BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN),
481 };
482
randomize_bt_addr(void)483 static int randomize_bt_addr(void)
484 {
485 /* TODO: There appears to be no way to force an RPA/NRPA refresh. */
486 return 0;
487 }
488
enc_id_adv(struct bt_mesh_subnet * sub,uint8_t type,uint8_t hash[16],int32_t duration)489 static int enc_id_adv(struct bt_mesh_subnet *sub, uint8_t type,
490 uint8_t hash[16], int32_t duration)
491 {
492 struct bt_le_adv_param slow_adv_param = {
493 .id = BT_ID_DEFAULT,
494 .options = ADV_OPT_PROXY(type == BT_MESH_ID_TYPE_PRIV_NET ||
495 type == BT_MESH_ID_TYPE_PRIV_NODE),
496 ADV_SLOW_INT,
497 };
498 struct bt_le_adv_param fast_adv_param = {
499 .id = BT_ID_DEFAULT,
500 .options = ADV_OPT_PROXY(type == BT_MESH_ID_TYPE_PRIV_NET ||
501 type == BT_MESH_ID_TYPE_PRIV_NODE),
502 ADV_FAST_INT,
503 };
504 struct bt_data sd[1];
505 int err;
506
507 err = bt_mesh_encrypt(&sub->keys[SUBNET_KEY_TX_IDX(sub)].identity, hash, hash);
508 if (err) {
509 return err;
510 }
511
512 /* MshPRTv1.1: 7.2.2.2.4: The AdvA field shall be regenerated whenever the Random field is
513 * regenerated.
514 */
515 err = randomize_bt_addr();
516 if (err) {
517 LOG_ERR("AdvA refresh failed: %d", err);
518 return err;
519 }
520
521 proxy_svc_data[2] = type;
522 memcpy(&proxy_svc_data[3], &hash[8], 8);
523
524 if (IS_ENABLED(CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME)) {
525 sd[0].type = BT_DATA_NAME_COMPLETE;
526 sd[0].data_len = BT_DEVICE_NAME_LEN;
527 sd[0].data = BT_DEVICE_NAME;
528 }
529
530 err = bt_mesh_adv_gatt_start(
531 type == BT_MESH_ID_TYPE_PRIV_NET ? &slow_adv_param : &fast_adv_param,
532 duration, enc_id_ad, ARRAY_SIZE(enc_id_ad),
533 IS_ENABLED(CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME) ? sd : NULL,
534 IS_ENABLED(CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME) ? ARRAY_SIZE(sd) : 0);
535 if (err) {
536 LOG_WRN("Failed to advertise using type 0x%02x (err %d)", type, err);
537 return err;
538 }
539
540 return 0;
541 }
542
node_id_adv(struct bt_mesh_subnet * sub,int32_t duration)543 static int node_id_adv(struct bt_mesh_subnet *sub, int32_t duration)
544 {
545 uint8_t *random = &proxy_svc_data[11];
546 uint8_t tmp[16];
547 int err;
548
549 LOG_DBG("0x%03x", sub->net_idx);
550
551 err = bt_rand(random, 8);
552 if (err) {
553 return err;
554 }
555
556 memset(&tmp[0], 0x00, 6);
557 memcpy(&tmp[6], random, 8);
558 sys_put_be16(bt_mesh_primary_addr(), &tmp[14]);
559
560 return enc_id_adv(sub, BT_MESH_ID_TYPE_NODE, tmp, duration);
561 }
562
priv_node_id_adv(struct bt_mesh_subnet * sub,int32_t duration)563 static int priv_node_id_adv(struct bt_mesh_subnet *sub, int32_t duration)
564 {
565 uint8_t *random = &proxy_svc_data[11];
566 uint8_t tmp[16];
567 int err;
568
569 LOG_DBG("0x%03x", sub->net_idx);
570
571 err = bt_rand(random, 8);
572 if (err) {
573 return err;
574 }
575
576 memset(&tmp[0], 0x00, 5);
577 tmp[5] = 0x03;
578 memcpy(&tmp[6], random, 8);
579 sys_put_be16(bt_mesh_primary_addr(), &tmp[14]);
580
581 return enc_id_adv(sub, BT_MESH_ID_TYPE_PRIV_NODE, tmp, duration);
582 }
583
priv_net_id_adv(struct bt_mesh_subnet * sub,int32_t duration)584 static int priv_net_id_adv(struct bt_mesh_subnet *sub, int32_t duration)
585 {
586 uint8_t *random = &proxy_svc_data[11];
587 uint8_t tmp[16];
588 int err;
589
590 LOG_DBG("0x%03x", sub->net_idx);
591
592 err = bt_rand(random, 8);
593 if (err) {
594 return err;
595 }
596
597 memcpy(&tmp[0], sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8);
598 memcpy(&tmp[8], random, 8);
599
600 return enc_id_adv(sub, BT_MESH_ID_TYPE_PRIV_NET, tmp, duration);
601 }
602
net_id_adv(struct bt_mesh_subnet * sub,int32_t duration)603 static int net_id_adv(struct bt_mesh_subnet *sub, int32_t duration)
604 {
605 struct bt_le_adv_param slow_adv_param = {
606 .id = BT_ID_DEFAULT,
607 .options = ADV_OPT_PROXY(false),
608 ADV_SLOW_INT,
609 };
610 struct bt_data sd[1];
611 int err;
612
613 proxy_svc_data[2] = BT_MESH_ID_TYPE_NET;
614
615 LOG_DBG("Advertising with NetId %s", bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8));
616
617 memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8);
618
619 if (IS_ENABLED(CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME)) {
620 sd[0].type = BT_DATA_NAME_COMPLETE;
621 sd[0].data_len = BT_DEVICE_NAME_LEN;
622 sd[0].data = BT_DEVICE_NAME;
623 }
624
625 err = bt_mesh_adv_gatt_start(&slow_adv_param, duration, net_id_ad,
626 ARRAY_SIZE(net_id_ad),
627 IS_ENABLED(CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME) ? sd : NULL,
628 IS_ENABLED(CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME) ?
629 ARRAY_SIZE(sd) : 0);
630 if (err) {
631 LOG_WRN("Failed to advertise using Network ID (err %d)", err);
632 return err;
633 }
634
635 return 0;
636 }
637
is_sub_proxy_active(struct bt_mesh_subnet * sub)638 static bool is_sub_proxy_active(struct bt_mesh_subnet *sub)
639 {
640 if (sub->net_idx == BT_MESH_KEY_UNUSED) {
641 return false;
642 }
643
644 return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING ||
645 #if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)
646 (bt_mesh_od_priv_proxy_get() > 0 && sub->solicited) ||
647 #endif
648 bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED ||
649 bt_mesh_priv_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
650 }
651
active_proxy_sub_cnt_cb(struct bt_mesh_subnet * sub,void * cb_data)652 static bool active_proxy_sub_cnt_cb(struct bt_mesh_subnet *sub, void *cb_data)
653 {
654 int *cnt = cb_data;
655
656 if (is_sub_proxy_active(sub)) {
657 (*cnt)++;
658 }
659
660 /* Don't stop until we've visited all subnets.
661 * We're only using the "find" variant of the subnet iteration to get a context parameter.
662 */
663 return false;
664 }
665
active_proxy_sub_cnt_get(void)666 static int active_proxy_sub_cnt_get(void)
667 {
668 int cnt = 0;
669
670 (void)bt_mesh_subnet_find(active_proxy_sub_cnt_cb, &cnt);
671
672 return cnt;
673 }
674
proxy_adv_timeout_eval(struct bt_mesh_subnet * sub)675 static void proxy_adv_timeout_eval(struct bt_mesh_subnet *sub)
676 {
677 int32_t time_passed;
678
679 if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) {
680 time_passed = k_uptime_get_32() - sub->node_id_start;
681 if (time_passed > (NODE_ID_TIMEOUT - MSEC_PER_SEC)) {
682 bt_mesh_proxy_identity_stop(sub);
683 LOG_DBG("Node ID stopped for subnet %d after %dms", sub->net_idx,
684 time_passed);
685 }
686 }
687
688 #if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)
689 if (bt_mesh_od_priv_proxy_get() > 0 && sub->solicited && sub->priv_net_id_sent) {
690 time_passed = k_uptime_get_32() - sub->priv_net_id_sent;
691 if (time_passed > ((MSEC_PER_SEC * bt_mesh_od_priv_proxy_get()) - MSEC_PER_SEC)) {
692 sub->priv_net_id_sent = 0;
693 sub->solicited = false;
694 LOG_DBG("Private Network ID stopped for subnet %d after %dms on "
695 "solicitation",
696 sub->net_idx, time_passed);
697 }
698 }
699 #endif
700 }
701
702 enum proxy_adv_evt {
703 NET_ID,
704 PRIV_NET_ID,
705 NODE_ID,
706 PRIV_NODE_ID,
707 OD_PRIV_NET_ID,
708 };
709
710 struct proxy_adv_request {
711 int32_t duration;
712 enum proxy_adv_evt evt;
713 };
714
proxy_adv_request_get(struct bt_mesh_subnet * sub,struct proxy_adv_request * request)715 static bool proxy_adv_request_get(struct bt_mesh_subnet *sub, struct proxy_adv_request *request)
716 {
717 if (!sub) {
718 return false;
719 }
720
721 if (sub->net_idx == BT_MESH_KEY_UNUSED) {
722 return false;
723 }
724
725 /** The priority for proxy adv is first solicitation, then Node Identity,
726 * and lastly Network ID. Network ID is prioritized last since, in many
727 * cases, another device can fulfill the same demand. Solicitation is
728 * prioritized first since legacy devices are dependent on this to
729 * connect to the network.
730 */
731
732 #if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)
733 if (bt_mesh_od_priv_proxy_get() > 0 && sub->solicited) {
734 int32_t timeout = MSEC_PER_SEC * (int32_t)bt_mesh_od_priv_proxy_get();
735
736 request->evt = OD_PRIV_NET_ID;
737 request->duration = !sub->priv_net_id_sent
738 ? timeout
739 : timeout - (k_uptime_get_32() - sub->priv_net_id_sent);
740 return true;
741 }
742 #endif
743
744 if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) {
745 request->duration = NODE_ID_TIMEOUT - (k_uptime_get_32() - sub->node_id_start);
746 request->evt =
747 #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
748 sub->priv_beacon_ctx.node_id ? PRIV_NODE_ID :
749 #endif
750 NODE_ID;
751
752 return true;
753 }
754
755 if (bt_mesh_priv_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED) {
756 request->evt = PRIV_NET_ID;
757 request->duration = PROXY_RANDOM_UPDATE_INTERVAL;
758 return true;
759 }
760
761 if (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED) {
762 request->evt = NET_ID;
763 request->duration = SYS_FOREVER_MS;
764 return true;
765 }
766
767 return false;
768 }
769
adv_sub_get_next(struct bt_mesh_subnet * sub_start,struct proxy_adv_request * request)770 static struct bt_mesh_subnet *adv_sub_get_next(struct bt_mesh_subnet *sub_start,
771 struct proxy_adv_request *request)
772 {
773 struct bt_mesh_subnet *sub_temp = bt_mesh_subnet_next(sub_start);
774
775 do {
776 if (proxy_adv_request_get(sub_temp, request)) {
777 return sub_temp;
778 }
779
780 sub_temp = bt_mesh_subnet_next(sub_temp);
781 } while (sub_temp != sub_start);
782
783 return NULL;
784 }
785
786 static struct {
787 int32_t start;
788 struct bt_mesh_subnet *sub;
789 struct proxy_adv_request request;
790 } sub_adv;
791
gatt_proxy_advertise(void)792 static int gatt_proxy_advertise(void)
793 {
794 int err;
795
796 int32_t max_adv_duration = 0;
797 int cnt;
798 struct bt_mesh_subnet *sub;
799 struct proxy_adv_request request;
800
801 LOG_DBG("");
802
803 /* Close proxy activity that has timed out on all subnets */
804 bt_mesh_subnet_foreach(proxy_adv_timeout_eval);
805
806 if (!bt_mesh_proxy_has_avail_conn()) {
807 LOG_DBG("Connectable advertising deferred (max connections)");
808 return -ENOMEM;
809 }
810
811 cnt = active_proxy_sub_cnt_get();
812 if (!cnt) {
813 LOG_DBG("No subnets to advertise proxy on");
814 return -ENOENT;
815 } else if (cnt > 1) {
816 /** There is more than one subnet that requires proxy adv,
817 * and the adv resources must be shared.
818 */
819
820 /* We use NODE_ID_TIMEOUT as a starting point since it may
821 * be less than 60 seconds. Divide this period into at least
822 * 6 slices, but make sure that a slice is more than one
823 * second long (to avoid excessive rotation).
824 */
825 max_adv_duration = NODE_ID_TIMEOUT / MAX(cnt, 6);
826 max_adv_duration = MAX(max_adv_duration, MSEC_PER_SEC + 20);
827
828 /* Check if the previous subnet finished its allocated timeslot */
829 if ((sub_adv.request.duration != SYS_FOREVER_MS) &&
830 proxy_adv_request_get(sub_adv.sub, &request) &&
831 (sub_adv.request.evt == request.evt)) {
832 int32_t time_passed = k_uptime_get_32() - sub_adv.start;
833
834 if (time_passed < sub_adv.request.duration &&
835 ((sub_adv.request.duration - time_passed) >= MSEC_PER_SEC)) {
836 sub = sub_adv.sub;
837 request.duration = sub_adv.request.duration - time_passed;
838 goto end;
839 }
840 }
841 }
842
843 sub = adv_sub_get_next(sub_adv.sub, &request);
844 if (!sub) {
845 LOG_ERR("Could not find subnet to advertise");
846 return -ENOENT;
847 }
848 end:
849 if (cnt > 1) {
850 request.duration = (request.duration == SYS_FOREVER_MS)
851 ? max_adv_duration
852 : MIN(request.duration, max_adv_duration);
853 }
854
855 /* Save current state for next iteration */
856 sub_adv.start = k_uptime_get_32();
857 sub_adv.sub = sub;
858 sub_adv.request = request;
859
860 switch (request.evt) {
861 case NET_ID:
862 err = net_id_adv(sub, request.duration);
863 break;
864 #if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)
865 case OD_PRIV_NET_ID:
866 if (!sub->priv_net_id_sent) {
867 sub->priv_net_id_sent = k_uptime_get();
868 }
869 /* Fall through */
870 #endif
871 case PRIV_NET_ID:
872 err = priv_net_id_adv(sub, request.duration);
873 break;
874 case NODE_ID:
875 err = node_id_adv(sub, request.duration);
876 break;
877 case PRIV_NODE_ID:
878 err = priv_node_id_adv(sub, request.duration);
879 break;
880 default:
881 LOG_ERR("Unexpected proxy adv evt: %d", request.evt);
882 return -ENODEV;
883 }
884
885 if (err) {
886 LOG_ERR("Advertising proxy failed (err: %d)", err);
887 return err;
888 }
889
890 LOG_DBG("Advertising %d ms for net_idx 0x%04x", request.duration, sub->net_idx);
891 return err;
892 }
893
subnet_evt(struct bt_mesh_subnet * sub,enum bt_mesh_key_evt evt)894 static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
895 {
896 if (evt == BT_MESH_KEY_DELETED) {
897 if (sub == beacon_sub) {
898 beacon_sub = NULL;
899 }
900
901 bt_mesh_proxy_identity_stop(sub);
902 } else {
903 bt_mesh_proxy_beacon_send(sub);
904 }
905
906 bt_mesh_adv_gatt_update();
907 }
908
909 BT_MESH_SUBNET_CB_DEFINE(gatt_services) = {
910 .evt_handler = subnet_evt,
911 };
912
proxy_ccc_changed(const struct bt_gatt_attr * attr,uint16_t value)913 static void proxy_ccc_changed(const struct bt_gatt_attr *attr, uint16_t value)
914 {
915 LOG_DBG("value 0x%04x", value);
916 }
917
proxy_ccc_write(struct bt_conn * conn,const struct bt_gatt_attr * attr,uint16_t value)918 static ssize_t proxy_ccc_write(struct bt_conn *conn,
919 const struct bt_gatt_attr *attr, uint16_t value)
920 {
921 struct bt_mesh_proxy_client *client;
922
923 LOG_DBG("value: 0x%04x", value);
924
925 if (value != BT_GATT_CCC_NOTIFY) {
926 LOG_WRN("Client wrote 0x%04x instead enabling notify", value);
927 return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
928 }
929
930 client = find_client(conn);
931 if (client->filter_type == NONE) {
932 client->filter_type = ACCEPT;
933 bt_mesh_wq_submit(&client->send_beacons);
934 }
935
936 return sizeof(value);
937 }
938
939 /* Mesh Proxy Service Declaration */
940 static struct bt_gatt_ccc_managed_user_data proxy_ccc =
941 BT_GATT_CCC_MANAGED_USER_DATA_INIT(proxy_ccc_changed, proxy_ccc_write, NULL);
942
943 static struct bt_gatt_attr proxy_attrs[] = {
944 BT_GATT_PRIMARY_SERVICE(BT_UUID_MESH_PROXY),
945
946 BT_GATT_CHARACTERISTIC(BT_UUID_MESH_PROXY_DATA_IN,
947 BT_GATT_CHRC_WRITE_WITHOUT_RESP,
948 BT_GATT_PERM_WRITE,
949 NULL, gatt_recv, NULL),
950
951 BT_GATT_CHARACTERISTIC(BT_UUID_MESH_PROXY_DATA_OUT,
952 BT_GATT_CHRC_NOTIFY,
953 BT_GATT_PERM_NONE,
954 NULL, NULL, NULL),
955 BT_GATT_CCC_MANAGED(&proxy_ccc,
956 BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
957 };
958
959 static struct bt_gatt_service proxy_svc = BT_GATT_SERVICE(proxy_attrs);
960
bt_mesh_proxy_gatt_enable(void)961 int bt_mesh_proxy_gatt_enable(void)
962 {
963 int err;
964
965 LOG_DBG("");
966
967 if (!bt_mesh_is_provisioned()) {
968 return -ENOTSUP;
969 }
970
971 if (service_registered) {
972 return -EBUSY;
973 }
974
975 err = bt_gatt_service_register(&proxy_svc);
976 if (err) {
977 LOG_ERR("Unable to register Mesh Proxy Service (err %d)", err);
978 return err;
979 }
980
981 service_registered = true;
982
983 for (int i = 0; i < ARRAY_SIZE(clients); i++) {
984 if (clients[i].cli) {
985 clients[i].filter_type = ACCEPT;
986 }
987 }
988
989 bt_mesh_adv_gatt_update();
990
991 return 0;
992 }
993
bt_mesh_proxy_gatt_disconnect(void)994 void bt_mesh_proxy_gatt_disconnect(void)
995 {
996 int i;
997
998 LOG_DBG("");
999
1000 for (i = 0; i < ARRAY_SIZE(clients); i++) {
1001 struct bt_mesh_proxy_client *client = &clients[i];
1002
1003 if (client->cli && (client->filter_type == ACCEPT ||
1004 client->filter_type == REJECT)) {
1005 client->filter_type = NONE;
1006 bt_conn_disconnect(client->cli->conn,
1007 BT_HCI_ERR_REMOTE_USER_TERM_CONN);
1008 }
1009 }
1010 }
1011
bt_mesh_proxy_gatt_disable(void)1012 int bt_mesh_proxy_gatt_disable(void)
1013 {
1014 LOG_DBG("");
1015
1016 if (!service_registered) {
1017 return -EALREADY;
1018 }
1019
1020 bt_mesh_proxy_gatt_disconnect();
1021
1022 bt_gatt_service_unregister(&proxy_svc);
1023 service_registered = false;
1024
1025 return 0;
1026 }
1027
bt_mesh_proxy_addr_add(struct net_buf_simple * buf,uint16_t addr)1028 void bt_mesh_proxy_addr_add(struct net_buf_simple *buf, uint16_t addr)
1029 {
1030 struct bt_mesh_proxy_client *client;
1031 struct bt_mesh_proxy_role *cli =
1032 CONTAINER_OF(buf, struct bt_mesh_proxy_role, buf);
1033
1034 client = find_client(cli->conn);
1035
1036 LOG_DBG("filter_type %u addr 0x%04x", client->filter_type, addr);
1037
1038 if (client->filter_type == ACCEPT) {
1039 filter_add(client, addr);
1040 } else if (client->filter_type == REJECT) {
1041 filter_remove(client, addr);
1042 }
1043 }
1044
client_filter_match(struct bt_mesh_proxy_client * client,uint16_t addr)1045 static bool client_filter_match(struct bt_mesh_proxy_client *client,
1046 uint16_t addr)
1047 {
1048 int i;
1049
1050 LOG_DBG("filter_type %u addr 0x%04x", client->filter_type, addr);
1051
1052 if (client->filter_type == REJECT) {
1053 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
1054 if (client->filter[i] == addr) {
1055 return false;
1056 }
1057 }
1058
1059 return true;
1060 }
1061
1062 if (addr == BT_MESH_ADDR_ALL_NODES) {
1063 return true;
1064 }
1065
1066 if (client->filter_type == ACCEPT) {
1067 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
1068 if (client->filter[i] == addr) {
1069 return true;
1070 }
1071 }
1072 }
1073
1074 return false;
1075 }
1076
bt_mesh_proxy_relay(struct bt_mesh_adv * adv,uint16_t dst)1077 bool bt_mesh_proxy_relay(struct bt_mesh_adv *adv, uint16_t dst)
1078 {
1079 bool relayed = false;
1080 int i;
1081
1082 LOG_DBG("%u bytes to dst 0x%04x", adv->b.len, dst);
1083
1084 for (i = 0; i < ARRAY_SIZE(clients); i++) {
1085 struct bt_mesh_proxy_client *client = &clients[i];
1086
1087 if (!client->cli) {
1088 continue;
1089 }
1090
1091 if (!client_filter_match(client, dst)) {
1092 continue;
1093 }
1094
1095 if (bt_mesh_proxy_relay_send(client->cli->conn, adv)) {
1096 continue;
1097 }
1098
1099 relayed = true;
1100 }
1101
1102 return relayed;
1103 }
1104
solicitation_reset(struct bt_mesh_subnet * sub)1105 static void solicitation_reset(struct bt_mesh_subnet *sub)
1106 {
1107 #if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV)
1108 sub->solicited = false;
1109 sub->priv_net_id_sent = 0;
1110 #endif
1111 }
1112
gatt_connected(struct bt_conn * conn,uint8_t conn_err)1113 static void gatt_connected(struct bt_conn *conn, uint8_t conn_err)
1114 {
1115 struct bt_mesh_proxy_client *client;
1116 struct bt_conn_info info;
1117 int err;
1118
1119 err = bt_conn_get_info(conn, &info);
1120 if (err || info.role != BT_CONN_ROLE_PERIPHERAL || !service_registered ||
1121 info.id != BT_ID_DEFAULT) {
1122 return;
1123 }
1124
1125 LOG_DBG("conn %p err 0x%02x", (void *)conn, conn_err);
1126
1127 client = find_client(conn);
1128
1129 client->filter_type = NONE;
1130 (void)memset(client->filter, 0, sizeof(client->filter));
1131 client->cli = bt_mesh_proxy_role_setup(conn, proxy_send,
1132 proxy_msg_recv);
1133
1134 #if defined(CONFIG_BT_MESH_PRIV_BEACONS)
1135 /* Binding from MshPRTv1.1: 7.2.2.2.6. */
1136 enum bt_mesh_subnets_node_id_state cur_node_id = bt_mesh_subnets_node_id_state_get();
1137
1138 if (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED ||
1139 cur_node_id == BT_MESH_SUBNETS_NODE_ID_STATE_ENABLED) {
1140 client->privacy = false;
1141 } else {
1142 client->privacy = (bt_mesh_priv_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED) ||
1143 (cur_node_id == BT_MESH_SUBNETS_NODE_ID_STATE_ENABLED_PRIVATE);
1144 }
1145
1146 LOG_DBG("privacy: %d", client->privacy);
1147 #endif
1148
1149 /* If connection was formed after Proxy Solicitation we need to stop future
1150 * Private Network ID advertisements
1151 */
1152 bt_mesh_subnet_foreach(solicitation_reset);
1153
1154 /* Try to re-enable advertising in case it's possible */
1155 if (bt_mesh_proxy_has_avail_conn()) {
1156 bt_mesh_adv_gatt_update();
1157 }
1158 }
1159
gatt_disconnected(struct bt_conn * conn,uint8_t reason)1160 static void gatt_disconnected(struct bt_conn *conn, uint8_t reason)
1161 {
1162 struct bt_conn_info info;
1163 struct bt_mesh_proxy_client *client;
1164 int err;
1165
1166 err = bt_conn_get_info(conn, &info);
1167 if (err || info.role != BT_CONN_ROLE_PERIPHERAL || info.id != BT_ID_DEFAULT) {
1168 return;
1169 }
1170
1171 if (!service_registered && bt_mesh_is_provisioned()) {
1172 (void)bt_mesh_proxy_gatt_enable();
1173 return;
1174 }
1175
1176 client = find_client(conn);
1177 if (client->cli) {
1178 bt_mesh_proxy_role_cleanup(client->cli);
1179 client->cli = NULL;
1180 }
1181 }
1182
proxy_send(struct bt_conn * conn,const void * data,uint16_t len,bt_gatt_complete_func_t end,void * user_data)1183 static int proxy_send(struct bt_conn *conn,
1184 const void *data, uint16_t len,
1185 bt_gatt_complete_func_t end, void *user_data)
1186 {
1187 LOG_DBG("%u bytes: %s", len, bt_hex(data, len));
1188
1189 struct bt_gatt_notify_params params = {
1190 .data = data,
1191 .len = len,
1192 .attr = &proxy_attrs[3],
1193 .user_data = user_data,
1194 .func = end,
1195 };
1196
1197 return bt_gatt_notify_cb(conn, ¶ms);
1198 }
1199
bt_mesh_proxy_adv_start(void)1200 int bt_mesh_proxy_adv_start(void)
1201 {
1202 LOG_DBG("");
1203
1204 if (!service_registered || !bt_mesh_is_provisioned()) {
1205 return -ENOTSUP;
1206 }
1207
1208 return gatt_proxy_advertise();
1209 }
1210
1211 BT_CONN_CB_DEFINE(conn_callbacks) = {
1212 .connected = gatt_connected,
1213 .disconnected = gatt_disconnected,
1214 };
1215
bt_mesh_proxy_srv_connected_cnt(void)1216 uint8_t bt_mesh_proxy_srv_connected_cnt(void)
1217 {
1218 uint8_t cnt = 0;
1219
1220 for (int i = 0; i < ARRAY_SIZE(clients); i++) {
1221 if (clients[i].cli) {
1222 cnt++;
1223 }
1224 }
1225
1226 return cnt;
1227 }
1228