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