1 /*
2 * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include <errno.h>
9
10 #include "mesh.h"
11 #include "access.h"
12 #include "beacon.h"
13 #include "transport.h"
14 #include "mesh_common.h"
15 #include "foundation.h"
16 #include "proxy_client.h"
17 #include "provisioner_prov.h"
18 #include "provisioner_main.h"
19 #include "mesh_bearer_adapt.h"
20
21 #define PDU_TYPE(data) (data[0] & BIT_MASK(6))
22 #define PDU_SAR(data) (data[0] >> 6)
23
24 #define PROXY_SAR_TIMEOUT K_SECONDS(20)
25
26 #define SAR_COMPLETE 0x00
27 #define SAR_FIRST 0x01
28 #define SAR_CONT 0x02
29 #define SAR_LAST 0x03
30
31 #define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6)))
32
33 #define SERVER_BUF_SIZE 68
34
35 #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
36 CONFIG_BLE_MESH_GATT_PROXY_CLIENT
37
38 static struct bt_mesh_proxy_server {
39 struct bt_mesh_conn *conn;
40 enum __packed {
41 NONE,
42 PROV,
43 PROXY,
44 } conn_type;
45 #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
46 uint16_t net_idx;
47 #endif
48 uint8_t msg_type;
49 struct k_delayed_work sar_timer;
50 struct net_buf_simple buf;
51 } servers[BLE_MESH_MAX_CONN];
52
53 static uint8_t server_buf_data[SERVER_BUF_SIZE * BLE_MESH_MAX_CONN];
54
find_server(struct bt_mesh_conn * conn)55 static struct bt_mesh_proxy_server *find_server(struct bt_mesh_conn *conn)
56 {
57 int i;
58
59 for (i = 0; i < ARRAY_SIZE(servers); i++) {
60 if (servers[i].conn == conn) {
61 return &servers[i];
62 }
63 }
64
65 return NULL;
66 }
67
proxy_sar_timeout(struct k_work * work)68 static void proxy_sar_timeout(struct k_work *work)
69 {
70 struct bt_mesh_proxy_server *server = NULL;
71
72 BT_WARN("%s", __func__);
73
74 server = CONTAINER_OF(work, struct bt_mesh_proxy_server, sar_timer.work);
75 if (!server || !server->conn) {
76 BT_ERR("Invalid proxy server parameter");
77 return;
78 }
79
80 net_buf_simple_reset(&server->buf);
81 bt_mesh_gattc_disconnect(server->conn);
82 }
83
84 #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
85 /**
86 * The following callbacks are used to notify proper information
87 * to the application layer.
88 */
89 static proxy_client_recv_adv_cb_t proxy_client_adv_recv_cb;
90 static proxy_client_connect_cb_t proxy_client_connect_cb;
91 static proxy_client_disconnect_cb_t proxy_client_disconnect_cb;
92 static proxy_client_recv_filter_status_cb_t proxy_client_filter_status_recv_cb;
93
bt_mesh_proxy_client_set_adv_recv_cb(proxy_client_recv_adv_cb_t cb)94 void bt_mesh_proxy_client_set_adv_recv_cb(proxy_client_recv_adv_cb_t cb)
95 {
96 proxy_client_adv_recv_cb = cb;
97 }
98
bt_mesh_proxy_client_set_conn_cb(proxy_client_connect_cb_t cb)99 void bt_mesh_proxy_client_set_conn_cb(proxy_client_connect_cb_t cb)
100 {
101 proxy_client_connect_cb = cb;
102 }
103
bt_mesh_proxy_client_set_disconn_cb(proxy_client_disconnect_cb_t cb)104 void bt_mesh_proxy_client_set_disconn_cb(proxy_client_disconnect_cb_t cb)
105 {
106 proxy_client_disconnect_cb = cb;
107 }
108
bt_mesh_proxy_client_set_filter_status_cb(proxy_client_recv_filter_status_cb_t cb)109 void bt_mesh_proxy_client_set_filter_status_cb(proxy_client_recv_filter_status_cb_t cb)
110 {
111 proxy_client_filter_status_recv_cb = cb;
112 }
113
filter_status(struct bt_mesh_proxy_server * server,struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)114 static void filter_status(struct bt_mesh_proxy_server *server,
115 struct bt_mesh_net_rx *rx,
116 struct net_buf_simple *buf)
117 {
118 uint8_t filter_type = 0U;
119 uint16_t list_size = 0U;
120
121 if (buf->len != 3) {
122 BT_ERR("Invalid Proxy Filter Status length %d", buf->len);
123 return;
124 }
125
126 filter_type = net_buf_simple_pull_u8(buf);
127 if (filter_type > 0x01) {
128 BT_ERR("Invalid proxy filter type 0x%02x", filter_type);
129 return;
130 }
131
132 list_size = net_buf_simple_pull_be16(buf);
133
134 BT_INFO("filter_type 0x%02x, list_size %d", filter_type, list_size);
135
136 if (proxy_client_filter_status_recv_cb) {
137 proxy_client_filter_status_recv_cb(server - servers, rx->ctx.addr, server->net_idx, filter_type, list_size);
138 }
139
140 return;
141 }
142
proxy_cfg(struct bt_mesh_proxy_server * server)143 static void proxy_cfg(struct bt_mesh_proxy_server *server)
144 {
145 NET_BUF_SIMPLE_DEFINE(buf, 29);
146 struct bt_mesh_net_rx rx = {0};
147 uint8_t opcode = 0U;
148 int err = 0;
149
150 if (server->buf.len > 29) {
151 BT_ERR("Too large proxy cfg pdu (len %d)", server->buf.len);
152 return;
153 }
154
155 err = bt_mesh_net_decode(&server->buf, BLE_MESH_NET_IF_PROXY_CFG,
156 &rx, &buf);
157 if (err) {
158 BT_ERR("Failed to decode Proxy Configuration (err %d)", err);
159 return;
160 }
161
162 if (!BLE_MESH_ADDR_IS_UNICAST(rx.ctx.addr)) {
163 BT_ERR("Proxy Configuration from non-unicast addr 0x%04x", rx.ctx.addr);
164 return;
165 }
166
167 rx.local_match = 1U;
168
169 if (bt_mesh_rpl_check(&rx, NULL)) {
170 BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
171 rx.ctx.addr, rx.ctx.recv_dst, rx.seq);
172 return;
173 }
174
175 /* Remove network headers */
176 net_buf_simple_pull(&buf, BLE_MESH_NET_HDR_LEN);
177
178 BT_DBG("%u bytes: %s", buf.len, bt_hex(buf.data, buf.len));
179
180 if (buf.len < 3) {
181 BT_WARN("Too short proxy configuration PDU");
182 return;
183 }
184
185 opcode = net_buf_simple_pull_u8(&buf);
186
187 switch (opcode) {
188 case BLE_MESH_PROXY_CFG_FILTER_STATUS:
189 filter_status(server, &rx, &buf);
190 break;
191 default:
192 BT_WARN("Unknown Proxy Configuration OpCode 0x%02x", opcode);
193 break;
194 }
195 }
196 #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
197
proxy_complete_pdu(struct bt_mesh_proxy_server * server)198 static void proxy_complete_pdu(struct bt_mesh_proxy_server *server)
199 {
200 switch (server->msg_type) {
201 #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
202 case BLE_MESH_PROXY_NET_PDU:
203 BT_DBG("Mesh Network PDU");
204 bt_mesh_net_recv(&server->buf, 0, BLE_MESH_NET_IF_PROXY);
205 break;
206 case BLE_MESH_PROXY_BEACON:
207 BT_DBG("Mesh Beacon PDU");
208 bt_mesh_beacon_recv(&server->buf, 0);
209 break;
210 case BLE_MESH_PROXY_CONFIG:
211 BT_DBG("Mesh Configuration PDU");
212 proxy_cfg(server);
213 break;
214 #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
215 #if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT
216 case BLE_MESH_PROXY_PROV:
217 BT_DBG("Mesh Provisioning PDU");
218 bt_mesh_provisioner_pb_gatt_recv(server->conn, &server->buf);
219 break;
220 #endif
221 default:
222 BT_WARN("Unhandled Message Type 0x%02x", server->msg_type);
223 break;
224 }
225
226 net_buf_simple_reset(&server->buf);
227 }
228
229 #define ATTR_IS_PROV(uuid) (uuid == BLE_MESH_UUID_MESH_PROV_VAL)
230
proxy_recv(struct bt_mesh_conn * conn,const struct bt_mesh_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)231 static ssize_t proxy_recv(struct bt_mesh_conn *conn,
232 const struct bt_mesh_gatt_attr *attr, const void *buf,
233 uint16_t len, uint16_t offset, uint8_t flags)
234 {
235 struct bt_mesh_proxy_server *server = find_server(conn);
236 const uint8_t *data = buf;
237 uint16_t srvc_uuid = 0U;
238
239 if (!server) {
240 BT_ERR("No Proxy Server object found");
241 return -ENOTCONN;
242 }
243
244 if (len < 1) {
245 BT_WARN("Too small Proxy PDU");
246 return -EINVAL;
247 }
248
249 srvc_uuid = bt_mesh_gattc_get_service_uuid(conn);
250 if (!srvc_uuid) {
251 BT_ERR("No service uuid found");
252 return -ENOTCONN;
253 }
254
255 if (ATTR_IS_PROV(srvc_uuid) != (PDU_TYPE(data) == BLE_MESH_PROXY_PROV)) {
256 BT_WARN("Proxy PDU type doesn't match GATT service uuid");
257 return -EINVAL;
258 }
259
260 if (len - 1 > net_buf_simple_tailroom(&server->buf)) {
261 BT_WARN("Too big proxy PDU");
262 return -EINVAL;
263 }
264
265 switch (PDU_SAR(data)) {
266 case SAR_COMPLETE:
267 if (server->buf.len) {
268 BT_WARN("Complete PDU while a pending incomplete one");
269 return -EINVAL;
270 }
271
272 server->msg_type = PDU_TYPE(data);
273 net_buf_simple_add_mem(&server->buf, data + 1, len - 1);
274 proxy_complete_pdu(server);
275 break;
276
277 case SAR_FIRST:
278 if (server->buf.len) {
279 BT_WARN("First PDU while a pending incomplete one");
280 return -EINVAL;
281 }
282
283 k_delayed_work_submit(&server->sar_timer, PROXY_SAR_TIMEOUT);
284 server->msg_type = PDU_TYPE(data);
285 net_buf_simple_add_mem(&server->buf, data + 1, len - 1);
286 break;
287
288 case SAR_CONT:
289 if (!server->buf.len) {
290 BT_WARN("Continuation with no prior data");
291 return -EINVAL;
292 }
293
294 if (server->msg_type != PDU_TYPE(data)) {
295 BT_WARN("Unexpected message type in continuation");
296 return -EINVAL;
297 }
298
299 k_delayed_work_submit(&server->sar_timer, PROXY_SAR_TIMEOUT);
300 net_buf_simple_add_mem(&server->buf, data + 1, len - 1);
301 break;
302
303 case SAR_LAST:
304 if (!server->buf.len) {
305 BT_WARN("Last SAR PDU with no prior data");
306 return -EINVAL;
307 }
308
309 if (server->msg_type != PDU_TYPE(data)) {
310 BT_WARN("Unexpected message type in last SAR PDU");
311 return -EINVAL;
312 }
313
314 k_delayed_work_cancel(&server->sar_timer);
315 net_buf_simple_add_mem(&server->buf, data + 1, len - 1);
316 proxy_complete_pdu(server);
317 break;
318 }
319
320 return len;
321 }
322
323
proxy_send(struct bt_mesh_conn * conn,const void * data,uint16_t len)324 static int proxy_send(struct bt_mesh_conn *conn, const void *data, uint16_t len)
325 {
326 BT_DBG("%u bytes: %s", len, bt_hex(data, len));
327
328 return bt_mesh_gattc_write_no_rsp(conn, NULL, data, len);
329 }
330
proxy_segment_and_send(struct bt_mesh_conn * conn,uint8_t type,struct net_buf_simple * msg)331 static int proxy_segment_and_send(struct bt_mesh_conn *conn, uint8_t type,
332 struct net_buf_simple *msg)
333 {
334 uint16_t mtu = 0U;
335 int err = 0;
336
337 if (conn == NULL) {
338 BT_ERR("%s, Invalid parameter", __func__);
339 return -EINVAL;
340 }
341
342 BT_DBG("conn %p type 0x%02x len %u: %s", conn, type, msg->len,
343 bt_hex(msg->data, msg->len));
344
345 mtu = bt_mesh_gattc_get_mtu_info(conn);
346 if (!mtu) {
347 BT_ERR("Conn %p used to get mtu not exists", conn);
348 return -ENOTCONN;
349 }
350
351 /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */
352 mtu -= 3;
353 if (mtu > msg->len) {
354 net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type));
355 return proxy_send(conn, msg->data, msg->len);
356 }
357
358 net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
359 err = proxy_send(conn, msg->data, mtu);
360 net_buf_simple_pull(msg, mtu);
361
362 while (msg->len) {
363 if (msg->len + 1 < mtu) {
364 net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type));
365 err = proxy_send(conn, msg->data, msg->len);
366 break;
367 }
368
369 net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
370 err = proxy_send(conn, msg->data, mtu);
371 net_buf_simple_pull(msg, mtu);
372 }
373
374 return err;
375 }
376
bt_mesh_proxy_client_send(struct bt_mesh_conn * conn,uint8_t type,struct net_buf_simple * msg)377 int bt_mesh_proxy_client_send(struct bt_mesh_conn *conn, uint8_t type,
378 struct net_buf_simple *msg)
379 {
380 struct bt_mesh_proxy_server *server = find_server(conn);
381
382 if (!server) {
383 BT_ERR("No Proxy Server object found");
384 return -ENOTCONN;
385 }
386
387 if ((server->conn_type == PROV) != (type == BLE_MESH_PROXY_PROV)) {
388 BT_ERR("Invalid PDU type for Proxy Server");
389 return -EINVAL;
390 }
391
392 return proxy_segment_and_send(conn, type, msg);
393 }
394
proxy_connected(bt_mesh_addr_t * addr,struct bt_mesh_conn * conn,int id)395 static void proxy_connected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, int id)
396 {
397 struct bt_mesh_proxy_server *server = NULL;
398
399 if (!servers[id].conn) {
400 server = &servers[id];
401 }
402
403 if (!server) {
404 BT_ERR("No free Proxy Server objects");
405 /** Disconnect current connection, clear part of prov_link
406 * information, like uuid, dev_addr, linking flag, etc.
407 */
408 bt_mesh_gattc_disconnect(conn);
409 return;
410 }
411
412 server->conn = bt_mesh_conn_ref(conn);
413 server->conn_type = NONE;
414 net_buf_simple_reset(&server->buf);
415
416 bt_mesh_gattc_exchange_mtu(id);
417 return;
418 }
419
proxy_disconnected(bt_mesh_addr_t * addr,struct bt_mesh_conn * conn,uint8_t reason)420 static void proxy_disconnected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, uint8_t reason)
421 {
422 struct bt_mesh_proxy_server *server = find_server(conn);
423
424 BT_DBG("conn %p, handle is %d, reason 0x%02x", conn, conn->handle, reason);
425
426 if (!server) {
427 BT_ERR("No Proxy Server object found");
428 return;
429 }
430
431 #if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT
432 if (server->conn_type == PROV) {
433 bt_mesh_provisioner_pb_gatt_close(conn, reason);
434 }
435 #endif
436
437 #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
438 if (server->conn_type == PROXY) {
439 if (proxy_client_disconnect_cb) {
440 proxy_client_disconnect_cb(addr, server - servers, server->net_idx, reason);
441 }
442 }
443 #endif
444
445 k_delayed_work_cancel(&server->sar_timer);
446 server->conn = NULL;
447 server->conn_type = NONE;
448 #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
449 server->net_idx = BLE_MESH_KEY_UNUSED;
450 #endif
451
452 return;
453 }
454
455 #if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT
prov_write_ccc(bt_mesh_addr_t * addr,struct bt_mesh_conn * conn)456 static ssize_t prov_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn)
457 {
458 struct bt_mesh_proxy_server *server = find_server(conn);
459
460 if (!server) {
461 BT_ERR("No Proxy Server object found");
462 return -ENOTCONN;
463 }
464
465 if (server->conn_type == NONE) {
466 server->conn_type = PROV;
467
468 if (bt_mesh_provisioner_set_prov_conn(addr->val, server->conn)) {
469 bt_mesh_gattc_disconnect(server->conn);
470 return -EIO;
471 }
472 return bt_mesh_provisioner_pb_gatt_open(conn, addr->val);
473 }
474
475 return -ENOMEM;
476 }
477
prov_recv_ntf(struct bt_mesh_conn * conn,uint8_t * data,uint16_t len)478 static ssize_t prov_recv_ntf(struct bt_mesh_conn *conn, uint8_t *data, uint16_t len)
479 {
480 struct bt_mesh_proxy_server *server = find_server(conn);
481
482 if (!server) {
483 BT_ERR("No Proxy Server object found");
484 return -ENOTCONN;
485 }
486
487 if (server->conn_type == PROV) {
488 return proxy_recv(conn, NULL, data, len, 0, 0);
489 }
490
491 return -EINVAL;
492 }
493
bt_mesh_proxy_client_prov_enable(void)494 int bt_mesh_proxy_client_prov_enable(void)
495 {
496 int i;
497
498 BT_DBG("%s", __func__);
499
500 for (i = 0; i < ARRAY_SIZE(servers); i++) {
501 if (servers[i].conn) {
502 servers[i].conn_type = PROV;
503 }
504 }
505
506 return 0;
507 }
508
bt_mesh_proxy_client_prov_disable(void)509 int bt_mesh_proxy_client_prov_disable(void)
510 {
511 int i;
512
513 BT_DBG("%s", __func__);
514
515 for (i = 0; i < ARRAY_SIZE(servers); i++) {
516 struct bt_mesh_proxy_server *server = &servers[i];
517
518 if (server->conn && server->conn_type == PROV) {
519 bt_mesh_gattc_disconnect(server->conn);
520 server->conn_type = NONE;
521 }
522 }
523
524 return 0;
525 }
526 #endif /* CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT */
527
528 #if defined(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)
proxy_write_ccc(bt_mesh_addr_t * addr,struct bt_mesh_conn * conn)529 static ssize_t proxy_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn)
530 {
531 struct bt_mesh_proxy_server *server = find_server(conn);
532
533 if (!server) {
534 BT_ERR("No Proxy Server object found");
535 return -ENOTCONN;
536 }
537
538 if (server->conn_type == NONE) {
539 server->conn_type = PROXY;
540
541 if (proxy_client_connect_cb) {
542 proxy_client_connect_cb(addr, server - servers, server->net_idx);
543 }
544 return 0;
545 }
546
547 return -EINVAL;
548 }
549
proxy_recv_ntf(struct bt_mesh_conn * conn,uint8_t * data,uint16_t len)550 static ssize_t proxy_recv_ntf(struct bt_mesh_conn *conn, uint8_t *data, uint16_t len)
551 {
552 struct bt_mesh_proxy_server *server = find_server(conn);
553
554 if (!server) {
555 BT_ERR("No Proxy Server object found");
556 return -ENOTCONN;
557 }
558
559 if (server->conn_type == PROXY) {
560 return proxy_recv(conn, NULL, data, len, 0, 0);
561 }
562
563 return -EINVAL;
564 }
565
566 /**
567 * Currently proxy client doesn't need bt_mesh_proxy_client_gatt_enable()
568 * and bt_mesh_proxy_client_gatt_disable() functions, and once they are
569 * used, proxy client can be enabled to parse node_id_adv and net_id_adv
570 * in order to support proxy client role.
571 * And if gatt proxy is disabled, proxy client can stop handling these
572 * two kinds of connectable advertising packets.
573 */
bt_mesh_proxy_client_gatt_enable(void)574 int bt_mesh_proxy_client_gatt_enable(void)
575 {
576 int i;
577
578 BT_DBG("%s", __func__);
579
580 for (i = 0; i < ARRAY_SIZE(servers); i++) {
581 if (servers[i].conn) {
582 servers[i].conn_type = PROXY;
583 }
584 }
585
586 /**
587 * TODO:
588 * Once at least one device has been provisioned, proxy client can be
589 * set to allow receiving and parsing node_id & net_id adv packets,
590 * and we may use a global flag to indicate this.
591 */
592
593 return 0;
594 }
595
bt_mesh_proxy_client_gatt_disable(void)596 int bt_mesh_proxy_client_gatt_disable(void)
597 {
598 int i;
599
600 BT_DBG("%s", __func__);
601
602 /**
603 * TODO:
604 * Once this function is invoked, proxy client shall stop handling
605 * node_id & net_id adv packets, and if proxy connection exists,
606 * it should be disconnected.
607 */
608
609 for (i = 0; i < ARRAY_SIZE(servers); i++) {
610 struct bt_mesh_proxy_server *server = &servers[i];
611
612 if (server->conn && server->conn_type == PROXY) {
613 bt_mesh_gattc_disconnect(server->conn);
614 server->conn_type = NONE;
615 }
616 }
617
618 return 0;
619 }
620 #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
621
622 static struct bt_mesh_prov_conn_cb conn_callbacks = {
623 .connected = proxy_connected,
624 .disconnected = proxy_disconnected,
625 #if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT
626 .prov_write_descr = prov_write_ccc,
627 .prov_notify = prov_recv_ntf,
628 #endif /* CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT */
629 #if defined(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)
630 .proxy_write_descr = proxy_write_ccc,
631 .proxy_notify = proxy_recv_ntf,
632 #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
633 };
634
635 #if defined(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)
bt_mesh_is_net_id_exist(const uint8_t net_id[8])636 static struct bt_mesh_subnet *bt_mesh_is_net_id_exist(const uint8_t net_id[8])
637 {
638 struct bt_mesh_subnet *sub = NULL;
639 size_t size = 0U, i = 0U;
640
641 size = bt_mesh_rx_netkey_size();
642
643 for (i = 0U; i < size; i++) {
644 sub = bt_mesh_rx_netkey_get(i);
645 if (sub && !memcmp(sub->keys[sub->kr_flag].net_id, net_id, 8)) {
646 return sub;
647 }
648 }
649
650 return NULL;
651 }
652
bt_mesh_proxy_client_gatt_adv_recv(struct net_buf_simple * buf,const bt_mesh_addr_t * addr,int8_t rssi)653 void bt_mesh_proxy_client_gatt_adv_recv(struct net_buf_simple *buf,
654 const bt_mesh_addr_t *addr, int8_t rssi)
655 {
656 bt_mesh_proxy_adv_ctx_t ctx = {0};
657 uint8_t type = 0U;
658
659 /* Check if connection reaches the maximum limitation */
660 if (bt_mesh_gattc_get_free_conn_count() == 0) {
661 BT_INFO("BLE connections for mesh reach max limit");
662 return;
663 }
664
665 type = net_buf_simple_pull_u8(buf);
666
667 switch (type) {
668 case BLE_MESH_PROXY_ADV_NET_ID: {
669 if (buf->len != sizeof(ctx.net_id.net_id)) {
670 BT_WARN("Malformed Network ID");
671 return;
672 }
673
674 struct bt_mesh_subnet *sub = NULL;
675 sub = bt_mesh_is_net_id_exist(buf->data);
676 if (!sub) {
677 return;
678 }
679
680 memcpy(ctx.net_id.net_id, buf->data, buf->len);
681 ctx.net_id.net_idx = sub->net_idx;
682 break;
683 }
684 case BLE_MESH_PROXY_ADV_NODE_ID:
685 /* Gets node identity information.
686 * hash = aes-ecb(identity key, 16 octets(padding + random + src)) mod 2^64,
687 * If Proxy Client wants to get src, it may encrypts multiple times and compare
688 * the hash value (8 octets) with the received one.
689 */
690 return;
691 default:
692 BT_DBG("Unknown Mesh Proxy adv type 0x%02x", type);
693 return;
694 }
695
696 if (proxy_client_adv_recv_cb) {
697 proxy_client_adv_recv_cb(addr, type, &ctx, rssi);
698 }
699 }
700
bt_mesh_proxy_client_connect(const uint8_t addr[6],uint8_t addr_type,uint16_t net_idx)701 int bt_mesh_proxy_client_connect(const uint8_t addr[6], uint8_t addr_type, uint16_t net_idx)
702 {
703 bt_mesh_addr_t remote_addr = {0};
704 int result = 0;
705
706 if (!addr || addr_type > BLE_MESH_ADDR_RANDOM) {
707 BT_ERR("%s, Invalid parameter", __func__);
708 return -EINVAL;
709 }
710
711 memcpy(remote_addr.val, addr, BLE_MESH_ADDR_LEN);
712 remote_addr.type = addr_type;
713
714 result = bt_mesh_gattc_conn_create(&remote_addr, BLE_MESH_UUID_MESH_PROXY_VAL);
715 if (result < 0) {
716 return result;
717 }
718
719 /* Store corresponding net_idx which can be used for sending Proxy Configuration */
720 servers[result].net_idx = net_idx;
721 return 0;
722 }
723
bt_mesh_proxy_client_disconnect(uint8_t conn_handle)724 int bt_mesh_proxy_client_disconnect(uint8_t conn_handle)
725 {
726 struct bt_mesh_conn *conn = NULL;
727
728 if (conn_handle >= BLE_MESH_MAX_CONN) {
729 BT_ERR("%s, Invalid parameter", __func__);
730 return -EINVAL;
731 }
732
733 BT_DBG("conn_handle %d", conn_handle);
734
735 conn = servers[conn_handle].conn;
736 if (!conn) {
737 BT_ERR("Not connected, conn handle %d", conn_handle);
738 return -ENOTCONN;
739 }
740
741 bt_mesh_gattc_disconnect(conn);
742 return 0;
743 }
744
bt_mesh_proxy_client_relay(struct net_buf_simple * buf,uint16_t dst)745 bool bt_mesh_proxy_client_relay(struct net_buf_simple *buf, uint16_t dst)
746 {
747 bool send = false;
748 int err = 0;
749 int i;
750
751 for (i = 0; i < ARRAY_SIZE(servers); i++) {
752 struct bt_mesh_proxy_server *server = &servers[i];
753 NET_BUF_SIMPLE_DEFINE(msg, 32);
754
755 if (!server->conn || server->conn_type != PROXY) {
756 continue;
757 }
758
759 /* Proxy PDU sending modifies the original buffer,
760 * so we need to make a copy.
761 */
762 net_buf_simple_init(&msg, 1);
763 net_buf_simple_add_mem(&msg, buf->data, buf->len);
764
765 err = bt_mesh_proxy_client_send(server->conn, BLE_MESH_PROXY_NET_PDU, &msg);
766 if (err) {
767 BT_ERR("Failed to send proxy network message (err %d)", err);
768 } else {
769 BT_INFO("%u bytes to dst 0x%04x", buf->len, dst);
770 send = true;
771 }
772 }
773
774 return send;
775 }
776
beacon_send(struct bt_mesh_conn * conn,struct bt_mesh_subnet * sub)777 static int beacon_send(struct bt_mesh_conn *conn, struct bt_mesh_subnet *sub)
778 {
779 NET_BUF_SIMPLE_DEFINE(buf, 23);
780
781 net_buf_simple_init(&buf, 1);
782 bt_mesh_beacon_create(sub, &buf);
783
784 return bt_mesh_proxy_client_send(conn, BLE_MESH_PROXY_BEACON, &buf);
785 }
786
bt_mesh_proxy_client_beacon_send(struct bt_mesh_subnet * sub)787 bool bt_mesh_proxy_client_beacon_send(struct bt_mesh_subnet *sub)
788 {
789 bool send = false;
790 int err = 0;
791 int i;
792
793 /* NULL means we send Secure Network Beacon on all subnets */
794 if (!sub) {
795 #if CONFIG_BLE_MESH_NODE
796 if (bt_mesh_is_provisioned()) {
797 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
798 if (bt_mesh.sub[i].net_idx != BLE_MESH_KEY_UNUSED) {
799 send = bt_mesh_proxy_client_beacon_send(&bt_mesh.sub[i]);
800 }
801 }
802 return send;
803 }
804 #endif /* CONFIG_BLE_MESH_NODE */
805 #if CONFIG_BLE_MESH_PROVISIONER
806 if (bt_mesh_is_provisioner_en()) {
807 for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) {
808 if (bt_mesh.p_sub[i] && bt_mesh.p_sub[i]->net_idx != BLE_MESH_KEY_UNUSED) {
809 send = bt_mesh_proxy_client_beacon_send(bt_mesh.p_sub[i]);
810 }
811 }
812 return send;
813 }
814 #endif /* CONFIG_BLE_MESH_PROVISIONER */
815 return send;
816 }
817
818 for (i = 0; i < ARRAY_SIZE(servers); i++) {
819 if (servers[i].conn && servers[i].conn_type == PROXY) {
820 err = beacon_send(servers[i].conn, sub);
821 if (err) {
822 BT_ERR("Failed to send proxy beacon message (err %d)", err);
823 } else {
824 send = true;
825 }
826 }
827 }
828
829 return send;
830 }
831
send_proxy_cfg(struct bt_mesh_conn * conn,uint16_t net_idx,struct bt_mesh_proxy_cfg_pdu * cfg)832 static int send_proxy_cfg(struct bt_mesh_conn *conn, uint16_t net_idx, struct bt_mesh_proxy_cfg_pdu *cfg)
833 {
834 struct bt_mesh_msg_ctx ctx = {
835 .net_idx = net_idx,
836 .app_idx = BLE_MESH_KEY_UNUSED, /* CTL shall be set to 1 */
837 .addr = BLE_MESH_ADDR_UNASSIGNED, /* DST shall be set to the unassigned address */
838 .send_ttl = 0U, /* TTL shall be set to 0 */
839 };
840 struct bt_mesh_net_tx tx = {
841 .ctx = &ctx,
842 .src = bt_mesh_primary_addr(),
843 };
844 struct net_buf_simple *buf = NULL;
845 uint16_t alloc_len = 0U;
846 int err = 0;
847
848 if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
849 tx.sub = bt_mesh_subnet_get(net_idx);
850 } else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) {
851 tx.sub = bt_mesh_provisioner_subnet_get(net_idx);
852 }
853 if (!tx.sub) {
854 BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx);
855 return -EIO;
856 }
857
858 switch (cfg->opcode) {
859 case BLE_MESH_PROXY_CFG_FILTER_SET:
860 if (cfg->set.filter_type > 0x01) {
861 BT_ERR("Invalid proxy filter type 0x%02x", cfg->set.filter_type);
862 return -EINVAL;
863 }
864
865 alloc_len = sizeof(cfg->opcode) + sizeof(cfg->set.filter_type);
866 break;
867 case BLE_MESH_PROXY_CFG_FILTER_ADD:
868 if (cfg->add.addr == NULL || cfg->add.addr_num == 0) {
869 BT_ERR("Empty proxy addr list to add");
870 return -EINVAL;
871 }
872
873 alloc_len = sizeof(cfg->opcode) + (cfg->add.addr_num << 1);
874 break;
875 case BLE_MESH_PROXY_CFG_FILTER_REMOVE:
876 if (cfg->remove.addr == NULL || cfg->remove.addr_num == 0) {
877 BT_ERR("Empty proxy addr list to remove");
878 return -EINVAL;
879 }
880
881 alloc_len = sizeof(cfg->opcode) + (cfg->remove.addr_num << 1);
882 break;
883 default:
884 BT_ERR("Unknown Proxy Configuration opcode 0x%02x", cfg->opcode);
885 return -EINVAL;
886 }
887
888 /**
889 * For Proxy Configuration PDU:
890 * 1 octet Proxy PDU type + 9 octets network pdu header + Tranport PDU + 8 octets NetMIC
891 */
892 buf = bt_mesh_alloc_buf(1 + BLE_MESH_NET_HDR_LEN + alloc_len + 8);
893 if (!buf) {
894 return -ENOMEM;
895 }
896
897 net_buf_simple_reset(buf);
898 net_buf_simple_reserve(buf, 10);
899
900 net_buf_simple_add_u8(buf, cfg->opcode);
901 switch (cfg->opcode) {
902 case BLE_MESH_PROXY_CFG_FILTER_SET:
903 net_buf_simple_add_u8(buf, cfg->set.filter_type);
904 break;
905 case BLE_MESH_PROXY_CFG_FILTER_ADD:
906 for (uint16_t i = 0U; i < cfg->add.addr_num; i++) {
907 net_buf_simple_add_le16(buf, cfg->add.addr[i]);
908 }
909 break;
910 case BLE_MESH_PROXY_CFG_FILTER_REMOVE:
911 for (uint16_t i = 0U; i < cfg->remove.addr_num; i++) {
912 net_buf_simple_add_le16(buf, cfg->remove.addr[i]);
913 }
914 break;
915 }
916
917 BT_DBG("len %u bytes: %s", buf->len, bt_hex(buf->data, buf->len));
918
919 err = bt_mesh_net_encode(&tx, buf, true);
920 if (err) {
921 BT_ERR("Encoding proxy message failed (err %d)", err);
922 bt_mesh_free_buf(buf);
923 return err;
924 }
925
926 err = bt_mesh_proxy_client_send(conn, BLE_MESH_PROXY_CONFIG, buf);
927 if (err) {
928 BT_ERR("Failed to send proxy cfg message (err %d)", err);
929 }
930
931 bt_mesh_free_buf(buf);
932 return err;
933 }
934
bt_mesh_proxy_client_cfg_send(uint8_t conn_handle,uint16_t net_idx,struct bt_mesh_proxy_cfg_pdu * pdu)935 int bt_mesh_proxy_client_cfg_send(uint8_t conn_handle, uint16_t net_idx,
936 struct bt_mesh_proxy_cfg_pdu *pdu)
937 {
938 struct bt_mesh_conn *conn = NULL;
939
940 if (conn_handle >= BLE_MESH_MAX_CONN || !pdu || pdu->opcode > BLE_MESH_PROXY_CFG_FILTER_REMOVE) {
941 BT_ERR("%s, Invalid parameter", __func__);
942 return -EINVAL;
943 }
944
945 BT_DBG("conn_handle %d, net_idx 0x%04x", conn_handle, net_idx);
946
947 conn = servers[conn_handle].conn;
948 if (!conn) {
949 BT_ERR("Not connected, conn handle %d", conn_handle);
950 return -ENOTCONN;
951 }
952
953 /**
954 * Check if net_idx used to encrypt Proxy Configuration are the same
955 * with the one added when creating proxy connection.
956 */
957 if (servers[conn_handle].net_idx != net_idx) {
958 BT_ERR("NetKeyIndex 0x%04x mismatch, expect 0x%04x",
959 net_idx, servers[conn_handle].net_idx);
960 return -EIO;
961 }
962
963 return send_proxy_cfg(conn, net_idx, pdu);
964 }
965 #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
966
bt_mesh_proxy_client_init(void)967 int bt_mesh_proxy_client_init(void)
968 {
969 int i;
970
971 /* Initialize the server receive buffers */
972 for (i = 0; i < ARRAY_SIZE(servers); i++) {
973 struct bt_mesh_proxy_server *server = &servers[i];
974
975 k_delayed_work_init(&server->sar_timer, proxy_sar_timeout);
976 server->buf.size = SERVER_BUF_SIZE;
977 server->buf.__buf = server_buf_data + (i * SERVER_BUF_SIZE);
978 #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
979 server->net_idx = BLE_MESH_KEY_UNUSED;
980 #endif
981 }
982
983 bt_mesh_gattc_conn_cb_register(&conn_callbacks);
984
985 #if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN && CONFIG_BLE_MESH_GATT_PROXY_CLIENT
986 bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_ADD,
987 BLE_MESH_EXCEP_INFO_MESH_PROXY_ADV, NULL);
988 #endif
989
990 return 0;
991 }
992
993 #if CONFIG_BLE_MESH_DEINIT
bt_mesh_proxy_client_deinit(void)994 int bt_mesh_proxy_client_deinit(void)
995 {
996 int i;
997
998 /* Initialize the server receive buffers */
999 for (i = 0; i < ARRAY_SIZE(servers); i++) {
1000 struct bt_mesh_proxy_server *server = &servers[i];
1001 k_delayed_work_free(&server->sar_timer);
1002 memset(server, 0, sizeof(struct bt_mesh_proxy_server));
1003 }
1004
1005 memset(server_buf_data, 0, sizeof(server_buf_data));
1006
1007 bt_mesh_gattc_conn_cb_deregister();
1008
1009 return 0;
1010 }
1011 #endif /* CONFIG_BLE_MESH_DEINIT */
1012
1013 #endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
1014