1 /* Bluetooth Mesh */
2
3 /*
4 * SPDX-FileCopyrightText: 2017 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <stdint.h>
10 #include <errno.h>
11 #include <string.h>
12
13 #include "crypto.h"
14 #include "adv.h"
15 #include "mesh.h"
16 #include "transport.h"
17 #include "access.h"
18 #include "friend.h"
19 #include "foundation.h"
20 #include "mesh_main.h"
21 #include "provisioner_main.h"
22
23 #ifdef CONFIG_BLE_MESH_FRIEND
24
25 /* We reserve one extra buffer for each friendship, since we need to be able
26 * to resend the last sent PDU, which sits separately outside of the queue.
27 */
28 #define FRIEND_BUF_COUNT ((CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE + 1) * \
29 CONFIG_BLE_MESH_FRIEND_LPN_COUNT)
30
31 #define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), struct friend_adv, adv)
32
33 /* PDUs from Friend to the LPN should only be transmitted once with the
34 * smallest possible interval (20ms).
35 */
36 #define FRIEND_XMIT BLE_MESH_TRANSMIT(0, 20)
37
38 struct friend_pdu_info {
39 uint16_t src;
40 uint16_t dst;
41
42 uint8_t seq[3];
43
44 uint8_t ttl:7,
45 ctl:1;
46
47 uint32_t iv_index;
48 };
49
50 NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT,
51 BLE_MESH_ADV_DATA_SIZE, NULL);
52
53 static struct friend_adv {
54 struct bt_mesh_adv adv;
55 uint16_t app_idx;
56 } adv_pool[FRIEND_BUF_COUNT];
57
58 enum {
59 BLE_MESH_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL,
60 BLE_MESH_FRIENDSHIP_TERMINATE_POLL_TIMEOUT,
61 BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_REQ,
62 BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_CLEAR,
63 BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE,
64 };
65
66 static void (*friend_cb)(bool establish, uint16_t lpn_addr, uint8_t reason);
67
68 static bool friend_init = false;
69
friend_subnet_get(uint16_t net_idx)70 static struct bt_mesh_subnet *friend_subnet_get(uint16_t net_idx)
71 {
72 struct bt_mesh_subnet *sub = NULL;
73
74 if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
75 sub = bt_mesh_subnet_get(net_idx);
76 } else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) {
77 sub = bt_mesh_provisioner_subnet_get(net_idx);
78 }
79
80 return sub;
81 }
82
adv_alloc(int id)83 static struct bt_mesh_adv *adv_alloc(int id)
84 {
85 adv_pool[id].app_idx = BLE_MESH_KEY_UNUSED;
86 return &adv_pool[id].adv;
87 }
88
is_lpn_unicast(struct bt_mesh_friend * frnd,uint16_t addr)89 static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr)
90 {
91 if (frnd->lpn == BLE_MESH_ADDR_UNASSIGNED) {
92 return false;
93 }
94
95 return (addr >= frnd->lpn && addr < (frnd->lpn + frnd->num_elem));
96 }
97
bt_mesh_friend_find(uint16_t net_idx,uint16_t lpn_addr,bool valid,bool established)98 struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr,
99 bool valid, bool established)
100 {
101 int i;
102
103 BT_DBG("net_idx 0x%04x lpn_addr 0x%04x", net_idx, lpn_addr);
104
105 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
106 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
107
108 if (valid && !frnd->valid) {
109 continue;
110 }
111
112 if (established && !frnd->established) {
113 continue;
114 }
115
116 if (net_idx != BLE_MESH_KEY_ANY && frnd->net_idx != net_idx) {
117 continue;
118 }
119
120 if (is_lpn_unicast(frnd, lpn_addr)) {
121 return frnd;
122 }
123 }
124
125 return NULL;
126 }
127
purge_buffers(sys_slist_t * list)128 static void purge_buffers(sys_slist_t *list)
129 {
130 while (!sys_slist_is_empty(list)) {
131 struct net_buf *buf = NULL;
132
133 buf = (void *)sys_slist_get_not_empty(list);
134
135 buf->frags = NULL;
136 buf->flags &= ~NET_BUF_FRAGS;
137
138 net_buf_unref(buf);
139 }
140 }
141
142 /* Intentionally start a little bit late into the ReceiveWindow when
143 * it's large enough. This may improve reliability with some platforms,
144 * like the PTS, where the receiver might not have sufficiently compensated
145 * for internal latencies required to start scanning.
146 */
recv_delay(struct bt_mesh_friend * frnd)147 static int32_t recv_delay(struct bt_mesh_friend *frnd)
148 {
149 #if CONFIG_BLE_MESH_FRIEND_RECV_WIN > 50
150 return (int32_t)frnd->recv_delay + (CONFIG_BLE_MESH_FRIEND_RECV_WIN / 5);
151 #else
152 return frnd->recv_delay;
153 #endif
154 }
155
friend_clear(struct bt_mesh_friend * frnd,uint8_t reason)156 static void friend_clear(struct bt_mesh_friend *frnd, uint8_t reason)
157 {
158 int i;
159
160 BT_DBG("LPN 0x%04x", frnd->lpn);
161
162 k_delayed_work_cancel(&frnd->timer);
163
164 if (frnd->established) {
165 if (friend_cb) {
166 friend_cb(false, frnd->lpn, reason);
167 }
168 }
169
170 friend_cred_del(frnd->net_idx, frnd->lpn);
171
172 if (frnd->last) {
173 /* Cancel the sending if necessary */
174 if (frnd->pending_buf) {
175 bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 2U, BLE_MESH_BUF_REF_EQUAL);
176 BLE_MESH_ADV(frnd->last)->busy = 0U;
177 } else {
178 bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 1U, BLE_MESH_BUF_REF_EQUAL);
179 }
180
181 net_buf_unref(frnd->last);
182 frnd->last = NULL;
183 }
184
185 purge_buffers(&frnd->queue);
186
187 for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
188 struct bt_mesh_friend_seg *seg = &frnd->seg[i];
189
190 purge_buffers(&seg->queue);
191 seg->seg_count = 0U;
192 }
193
194 frnd->valid = 0U;
195 frnd->established = 0U;
196 frnd->pending_buf = 0U;
197 frnd->fsn = 0U;
198 frnd->queue_size = 0U;
199 frnd->pending_req = 0U;
200 (void)memset(frnd->sub_list, 0, sizeof(frnd->sub_list));
201 }
202
bt_mesh_friend_clear_net_idx(uint16_t net_idx)203 void bt_mesh_friend_clear_net_idx(uint16_t net_idx)
204 {
205 int i;
206
207 BT_DBG("net_idx 0x%04x", net_idx);
208
209 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
210 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
211
212 if (frnd->net_idx == BLE_MESH_KEY_UNUSED) {
213 continue;
214 }
215
216 if (net_idx == BLE_MESH_KEY_ANY || frnd->net_idx == net_idx) {
217 friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE);
218 }
219 }
220 }
221
bt_mesh_friend_sec_update(uint16_t net_idx)222 void bt_mesh_friend_sec_update(uint16_t net_idx)
223 {
224 int i;
225
226 BT_DBG("net_idx 0x%04x", net_idx);
227
228 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
229 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
230
231 if (frnd->net_idx == BLE_MESH_KEY_UNUSED) {
232 continue;
233 }
234
235 if (net_idx == BLE_MESH_KEY_ANY || frnd->net_idx == net_idx) {
236 frnd->sec_update = 1U;
237 }
238 }
239 }
240
bt_mesh_friend_clear(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)241 int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
242 {
243 struct bt_mesh_ctl_friend_clear *msg = (void *)buf->data;
244 struct bt_mesh_friend *frnd = NULL;
245 uint16_t lpn_addr = 0U, lpn_counter = 0U;
246 struct bt_mesh_net_tx tx = {
247 .sub = rx->sub,
248 .ctx = &rx->ctx,
249 .src = bt_mesh_primary_addr(),
250 .xmit = bt_mesh_net_transmit_get(),
251 };
252 struct bt_mesh_ctl_friend_clear_confirm cfm = {0};
253
254 if (buf->len < sizeof(*msg)) {
255 BT_WARN("Too short Friend Clear (len %d)", buf->len);
256 return -EINVAL;
257 }
258
259 lpn_addr = sys_be16_to_cpu(msg->lpn_addr);
260 lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
261
262 BT_DBG("LPN addr 0x%04x counter 0x%04x", lpn_addr, lpn_counter);
263
264 frnd = bt_mesh_friend_find(rx->sub->net_idx, lpn_addr, false, false);
265 if (!frnd) {
266 BT_WARN("No matching LPN addr 0x%04x", lpn_addr);
267 return 0;
268 }
269
270 /* A Friend Clear message is considered valid if the result of the
271 * subtraction of the value of the LPNCounter field of the Friend
272 * Request message (the one that initiated the friendship) from the
273 * value of the LPNCounter field of the Friend Clear message, modulo
274 * 65536, is in the range 0 to 255 inclusive.
275 */
276 if (lpn_counter - frnd->lpn_counter > 255) {
277 BT_WARN("LPN Counter out of range (old %u new %u)",
278 frnd->lpn_counter, lpn_counter);
279 return 0;
280 }
281
282 tx.ctx->send_ttl = BLE_MESH_TTL_MAX;
283
284 cfm.lpn_addr = msg->lpn_addr;
285 cfm.lpn_counter = msg->lpn_counter;
286
287 bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm,
288 sizeof(cfm), NULL, NULL);
289
290 friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_CLEAR);
291
292 return 0;
293 }
294
friend_sub_add(struct bt_mesh_friend * frnd,uint16_t addr)295 static void friend_sub_add(struct bt_mesh_friend *frnd, uint16_t addr)
296 {
297 int i;
298
299 for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
300 if (frnd->sub_list[i] == BLE_MESH_ADDR_UNASSIGNED) {
301 frnd->sub_list[i] = addr;
302 return;
303 }
304 }
305
306 BT_WARN("No space in friend subscription list");
307 }
308
friend_sub_rem(struct bt_mesh_friend * frnd,uint16_t addr)309 static void friend_sub_rem(struct bt_mesh_friend *frnd, uint16_t addr)
310 {
311 int i;
312
313 for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
314 if (frnd->sub_list[i] == addr) {
315 frnd->sub_list[i] = BLE_MESH_ADDR_UNASSIGNED;
316 return;
317 }
318 }
319 }
320
create_friend_pdu(struct bt_mesh_friend * frnd,struct friend_pdu_info * info,struct net_buf_simple * sdu)321 static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd,
322 struct friend_pdu_info *info,
323 struct net_buf_simple *sdu)
324 {
325 struct net_buf *buf = NULL;
326
327 buf = bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_alloc,
328 BLE_MESH_ADV_DATA,
329 FRIEND_XMIT, K_NO_WAIT);
330 if (!buf) {
331 return NULL;
332 }
333
334 net_buf_add_u8(buf, (info->iv_index & 1) << 7); /* Will be reset in encryption */
335
336 if (info->ctl) {
337 net_buf_add_u8(buf, info->ttl | 0x80);
338 } else {
339 net_buf_add_u8(buf, info->ttl);
340 }
341
342 net_buf_add_mem(buf, info->seq, sizeof(info->seq));
343
344 net_buf_add_be16(buf, info->src);
345 net_buf_add_be16(buf, info->dst);
346
347 net_buf_add_mem(buf, sdu->data, sdu->len);
348
349 return buf;
350 }
351
352 struct unseg_app_sdu_meta {
353 struct bt_mesh_net_rx net;
354 const uint8_t *key;
355 struct bt_mesh_subnet *subnet;
356 bool is_dev_key;
357 uint8_t aid;
358 uint8_t *ad;
359 };
360
unseg_app_sdu_unpack(struct bt_mesh_friend * frnd,struct net_buf * buf,struct unseg_app_sdu_meta * meta)361 static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd,
362 struct net_buf *buf,
363 struct unseg_app_sdu_meta *meta)
364 {
365 uint16_t app_idx = FRIEND_ADV(buf)->app_idx;
366 uint8_t role = 0U;
367 int err = 0;
368
369 meta->subnet = friend_subnet_get(frnd->net_idx);
370 if (!meta->subnet) {
371 BT_ERR("Invalid subnet for unseg app sdu");
372 return -EINVAL;
373 }
374
375 role = (IS_ENABLED(CONFIG_BLE_MESH_NODE) &&
376 bt_mesh_is_provisioned()) ? NODE : PROVISIONER;
377
378 meta->is_dev_key = (app_idx == BLE_MESH_KEY_DEV);
379 bt_mesh_net_header_parse(&buf->b, &meta->net);
380 err = bt_mesh_app_key_get(meta->subnet, app_idx, &meta->key,
381 &meta->aid, role, meta->net.ctx.addr);
382 if (err) {
383 BT_ERR("Failed to get AppKey");
384 return err;
385 }
386
387 if (BLE_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) {
388 meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst);
389 if (!meta->ad) {
390 BT_ERR("Failed to get label uuid");
391 return -ENOENT;
392 }
393 } else {
394 meta->ad = NULL;
395 }
396
397 return 0;
398 }
399
unseg_app_sdu_decrypt(struct bt_mesh_friend * frnd,struct net_buf * buf,const struct unseg_app_sdu_meta * meta)400 static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd,
401 struct net_buf *buf,
402 const struct unseg_app_sdu_meta *meta)
403 {
404 struct net_buf_simple sdu = {0};
405
406 net_buf_simple_clone(&buf->b, &sdu);
407 net_buf_simple_pull(&sdu, 10);
408 sdu.len -= 4;
409
410 return bt_mesh_app_decrypt(meta->key, meta->is_dev_key, 0, &sdu, &sdu,
411 meta->ad, meta->net.ctx.addr,
412 meta->net.ctx.recv_dst, meta->net.seq,
413 BLE_MESH_NET_IVI_TX);
414 }
415
unseg_app_sdu_encrypt(struct bt_mesh_friend * frnd,struct net_buf * buf,const struct unseg_app_sdu_meta * meta)416 static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd,
417 struct net_buf *buf,
418 const struct unseg_app_sdu_meta *meta)
419 {
420 struct net_buf_simple sdu = {0};
421
422 net_buf_simple_clone(&buf->b, &sdu);
423 net_buf_simple_pull(&sdu, 10);
424 sdu.len -= 4;
425
426 return bt_mesh_app_encrypt(meta->key, meta->is_dev_key, 0, &sdu,
427 meta->ad, meta->net.ctx.addr,
428 meta->net.ctx.recv_dst, bt_mesh.seq,
429 BLE_MESH_NET_IVI_TX);
430 }
431
unseg_app_sdu_prepare(struct bt_mesh_friend * frnd,struct net_buf * buf)432 static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd,
433 struct net_buf *buf)
434 {
435 struct unseg_app_sdu_meta meta = {0};
436 int err = 0;
437
438 if (FRIEND_ADV(buf)->app_idx == BLE_MESH_KEY_UNUSED) {
439 return 0;
440 }
441
442 err = unseg_app_sdu_unpack(frnd, buf, &meta);
443 if (err) {
444 return err;
445 }
446
447 /* No need to re-encrypt the message if the sequence number is
448 * unchanged.
449 */
450 if (meta.net.seq == bt_mesh.seq) {
451 return 0;
452 }
453
454 err = unseg_app_sdu_decrypt(frnd, buf, &meta);
455 if (err) {
456 BT_WARN("Decryption failed! %d", err);
457 return err;
458 }
459
460 err = unseg_app_sdu_encrypt(frnd, buf, &meta);
461 if (err) {
462 BT_WARN("Re-encryption failed! %d", err);
463 }
464
465 return err;
466 }
467
encrypt_friend_pdu(struct bt_mesh_friend * frnd,struct net_buf * buf,bool master_cred)468 static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf,
469 bool master_cred)
470 {
471 struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx);
472 const uint8_t *enc = NULL, *priv = NULL;
473 uint32_t iv_index = 0U;
474 uint16_t src = 0U;
475 uint8_t nid = 0U;
476 int err = 0;
477
478 if (!sub) {
479 BT_ERR("Invalid subnet to encrypt friend pdu");
480 return -EINVAL;
481 }
482
483 if (master_cred) {
484 enc = sub->keys[sub->kr_flag].enc;
485 priv = sub->keys[sub->kr_flag].privacy;
486 nid = sub->keys[sub->kr_flag].nid;
487 } else {
488 if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
489 BT_ERR("friend_cred_get failed");
490 return -ENOENT;
491 }
492 }
493
494 src = sys_get_be16(&buf->data[5]);
495
496 if (bt_mesh_elem_find(src)) {
497 uint32_t seq;
498
499 if (FRIEND_ADV(buf)->app_idx != BLE_MESH_KEY_UNUSED) {
500 err = unseg_app_sdu_prepare(frnd, buf);
501 if (err) {
502 return err;
503 }
504 }
505
506 seq = bt_mesh_next_seq();
507 sys_put_be24(seq, &buf->data[2]);
508
509 iv_index = BLE_MESH_NET_IVI_TX;
510 FRIEND_ADV(buf)->app_idx = BLE_MESH_KEY_UNUSED;
511 } else {
512 uint8_t ivi = (buf->data[0] >> 7);
513 iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi));
514 }
515
516 buf->data[0] = (nid | (iv_index & 1) << 7);
517
518 if (bt_mesh_net_encrypt(enc, &buf->b, iv_index, false)) {
519 BT_ERR("Encrypting failed");
520 return -EINVAL;
521 }
522
523 if (bt_mesh_net_obfuscate(buf->data, iv_index, priv)) {
524 BT_ERR("Obfuscating failed");
525 return -EINVAL;
526 }
527
528 return 0;
529 }
530
encode_friend_ctl(struct bt_mesh_friend * frnd,uint8_t ctl_op,struct net_buf_simple * sdu)531 static struct net_buf *encode_friend_ctl(struct bt_mesh_friend *frnd,
532 uint8_t ctl_op,
533 struct net_buf_simple *sdu)
534 {
535 struct friend_pdu_info info = {0};
536
537 BT_DBG("LPN 0x%04x", frnd->lpn);
538
539 net_buf_simple_push_u8(sdu, TRANS_CTL_HDR(ctl_op, 0));
540
541 info.src = bt_mesh_primary_addr();
542 info.dst = frnd->lpn;
543
544 info.ctl = 1U;
545 info.ttl = 0U;
546
547 memset(info.seq, 0, sizeof(info.seq));
548
549 info.iv_index = BLE_MESH_NET_IVI_TX;
550
551 return create_friend_pdu(frnd, &info, sdu);
552 }
553
encode_update(struct bt_mesh_friend * frnd,uint8_t md)554 static struct net_buf *encode_update(struct bt_mesh_friend *frnd, uint8_t md)
555 {
556 struct bt_mesh_ctl_friend_update *upd = NULL;
557 NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*upd));
558 struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx);
559
560 if (!sub) {
561 BT_ERR("Friend subnet 0x%04x not found", frnd->net_idx);
562 return NULL;
563 }
564
565 BT_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md);
566
567 net_buf_simple_reserve(&sdu, 1);
568
569 upd = net_buf_simple_add(&sdu, sizeof(*upd));
570 upd->flags = bt_mesh_net_flags(sub);
571 upd->iv_index = sys_cpu_to_be32(bt_mesh.iv_index);
572 upd->md = md;
573
574 return encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_UPDATE, &sdu);
575 }
576
enqueue_sub_cfm(struct bt_mesh_friend * frnd,uint8_t xact)577 static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, uint8_t xact)
578 {
579 struct bt_mesh_ctl_friend_sub_confirm *cfm = NULL;
580 NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*cfm));
581 struct net_buf *buf = NULL;
582
583 BT_DBG("lpn 0x%04x xact 0x%02x", frnd->lpn, xact);
584
585 net_buf_simple_reserve(&sdu, 1);
586
587 cfm = net_buf_simple_add(&sdu, sizeof(*cfm));
588 cfm->xact = xact;
589
590 buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_SUB_CFM, &sdu);
591 if (!buf) {
592 BT_ERR("Unable to encode Subscription List Confirmation");
593 return;
594 }
595
596 if (encrypt_friend_pdu(frnd, buf, false)) {
597 return;
598 }
599
600 if (frnd->last) {
601 BT_DBG("Discarding last PDU");
602 net_buf_unref(frnd->last);
603 }
604
605 frnd->last = buf;
606 frnd->send_last = 1U;
607 }
608
friend_recv_delay(struct bt_mesh_friend * frnd)609 static void friend_recv_delay(struct bt_mesh_friend *frnd)
610 {
611 frnd->pending_req = 1U;
612 k_delayed_work_submit(&frnd->timer, recv_delay(frnd));
613 BT_INFO("Waiting RecvDelay of %d ms", recv_delay(frnd));
614 }
615
bt_mesh_friend_sub_add(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)616 int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
617 struct net_buf_simple *buf)
618 {
619 struct bt_mesh_friend *frnd = NULL;
620 uint8_t xact = 0U;
621
622 if (buf->len < BLE_MESH_FRIEND_SUB_MIN_LEN) {
623 BT_WARN("Too short Friend Subscription Add (len %d)", buf->len);
624 return -EINVAL;
625 }
626
627 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true);
628 if (!frnd) {
629 BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
630 return 0;
631 }
632
633 if (frnd->pending_buf) {
634 BT_WARN("Previous buffer not yet sent!");
635 return 0;
636 }
637
638 friend_recv_delay(frnd);
639
640 xact = net_buf_simple_pull_u8(buf);
641
642 while (buf->len >= 2U) {
643 friend_sub_add(frnd, net_buf_simple_pull_be16(buf));
644 }
645
646 enqueue_sub_cfm(frnd, xact);
647
648 return 0;
649 }
650
bt_mesh_friend_sub_rem(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)651 int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
652 struct net_buf_simple *buf)
653 {
654 struct bt_mesh_friend *frnd = NULL;
655 uint8_t xact = 0U;
656
657 if (buf->len < BLE_MESH_FRIEND_SUB_MIN_LEN) {
658 BT_WARN("Too short Friend Subscription Remove (len %d)", buf->len);
659 return -EINVAL;
660 }
661
662 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true);
663 if (!frnd) {
664 BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
665 return 0;
666 }
667
668 if (frnd->pending_buf) {
669 BT_WARN("Previous buffer not yet sent!");
670 return 0;
671 }
672
673 friend_recv_delay(frnd);
674
675 xact = net_buf_simple_pull_u8(buf);
676
677 while (buf->len >= 2U) {
678 friend_sub_rem(frnd, net_buf_simple_pull_be16(buf));
679 }
680
681 enqueue_sub_cfm(frnd, xact);
682
683 return 0;
684 }
685
enqueue_buf(struct bt_mesh_friend * frnd,struct net_buf * buf)686 static void enqueue_buf(struct bt_mesh_friend *frnd, struct net_buf *buf)
687 {
688 net_buf_slist_put(&frnd->queue, buf);
689 frnd->queue_size++;
690 }
691
enqueue_update(struct bt_mesh_friend * frnd,uint8_t md)692 static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md)
693 {
694 struct net_buf *buf = NULL;
695
696 buf = encode_update(frnd, md);
697 if (!buf) {
698 BT_ERR("Unable to encode Friend Update");
699 return;
700 }
701
702 frnd->sec_update = 0U;
703 enqueue_buf(frnd, buf);
704 }
705
bt_mesh_friend_poll(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)706 int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
707 {
708 struct bt_mesh_ctl_friend_poll *msg = (void *)buf->data;
709 struct bt_mesh_friend *frnd = NULL;
710
711 if (buf->len < sizeof(*msg)) {
712 BT_WARN("Too short Friend Poll (len %d)", buf->len);
713 return -EINVAL;
714 }
715
716 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false);
717 if (!frnd) {
718 BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
719 return 0;
720 }
721
722 if (msg->fsn & ~1) {
723 BT_WARN("Prohibited (non-zero) padding bits");
724 return -EINVAL;
725 }
726
727 if (frnd->pending_buf) {
728 BT_WARN("Previous buffer not yet sent!");
729 return 0;
730 }
731
732 BT_DBG("msg->fsn %u frnd->fsn %u", (msg->fsn & 1), frnd->fsn);
733
734 friend_recv_delay(frnd);
735
736 if (!frnd->established) {
737 BT_INFO("Friendship established with 0x%04x", frnd->lpn);
738 frnd->established = 1U;
739 if (friend_cb) {
740 friend_cb(true, frnd->lpn, 0);
741 }
742 }
743
744 if (msg->fsn == frnd->fsn && frnd->last) {
745 BT_DBG("Re-sending last PDU");
746 frnd->send_last = 1U;
747 } else {
748 if (frnd->last) {
749 net_buf_unref(frnd->last);
750 frnd->last = NULL;
751 }
752
753 frnd->fsn = msg->fsn;
754
755 if (sys_slist_is_empty(&frnd->queue)) {
756 enqueue_update(frnd, 0);
757 BT_DBG("Enqueued Friend Update to empty queue");
758 }
759 }
760
761 return 0;
762 }
763
find_clear(uint16_t prev_friend)764 static struct bt_mesh_friend *find_clear(uint16_t prev_friend)
765 {
766 int i;
767
768 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
769 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
770
771 if (frnd->clear.frnd == prev_friend) {
772 return frnd;
773 }
774 }
775
776 return NULL;
777 }
778
friend_clear_sent(int err,void * user_data)779 static void friend_clear_sent(int err, void *user_data)
780 {
781 struct bt_mesh_friend *frnd = user_data;
782
783 k_delayed_work_submit(&frnd->clear.timer,
784 K_SECONDS(frnd->clear.repeat_sec));
785 frnd->clear.repeat_sec *= 2U;
786 }
787
788 static const struct bt_mesh_send_cb clear_sent_cb = {
789 .end = friend_clear_sent,
790 };
791
send_friend_clear(struct bt_mesh_friend * frnd)792 static void send_friend_clear(struct bt_mesh_friend *frnd)
793 {
794 struct bt_mesh_msg_ctx ctx = {
795 .net_idx = frnd->net_idx,
796 .app_idx = BLE_MESH_KEY_UNUSED,
797 .addr = frnd->clear.frnd,
798 .send_ttl = BLE_MESH_TTL_MAX,
799 };
800 struct bt_mesh_net_tx tx = {
801 .sub = friend_subnet_get(frnd->net_idx),
802 .ctx = &ctx,
803 .src = bt_mesh_primary_addr(),
804 .xmit = bt_mesh_net_transmit_get(),
805 };
806 struct bt_mesh_ctl_friend_clear req = {
807 .lpn_addr = sys_cpu_to_be16(frnd->lpn),
808 .lpn_counter = sys_cpu_to_be16(frnd->lpn_counter),
809 };
810
811 BT_DBG("%s", __func__);
812
813 if (!tx.sub) {
814 BT_ERR("Invalid subnet for Friend Clear");
815 return;
816 }
817
818 bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
819 sizeof(req), &clear_sent_cb, frnd);
820 }
821
clear_timeout(struct k_work * work)822 static void clear_timeout(struct k_work *work)
823 {
824 struct bt_mesh_friend *frnd = CONTAINER_OF(work, struct bt_mesh_friend,
825 clear.timer.work);
826 uint32_t duration = 0U;
827
828 BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
829
830 duration = k_uptime_get_32() - frnd->clear.start;
831 if (duration > 2 * frnd->poll_to) {
832 BT_DBG("Clear Procedure timer expired");
833 frnd->clear.frnd = BLE_MESH_ADDR_UNASSIGNED;
834 return;
835 }
836
837 send_friend_clear(frnd);
838 }
839
clear_procedure_start(struct bt_mesh_friend * frnd)840 static void clear_procedure_start(struct bt_mesh_friend *frnd)
841 {
842 BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
843
844 frnd->clear.start = k_uptime_get_32();
845 frnd->clear.repeat_sec = 1U;
846
847 send_friend_clear(frnd);
848 }
849
bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)850 int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
851 struct net_buf_simple *buf)
852 {
853 struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->data;
854 struct bt_mesh_friend *frnd = NULL;
855 uint16_t lpn_addr = 0U, lpn_counter = 0U;
856
857 BT_DBG("%s", __func__);
858
859 if (buf->len < sizeof(*msg)) {
860 BT_WARN("Too short Friend Clear Confirm (len %d)", buf->len);
861 return -EINVAL;
862 }
863
864 frnd = find_clear(rx->ctx.addr);
865 if (!frnd) {
866 BT_WARN("No pending clear procedure for 0x%02x", rx->ctx.addr);
867 return 0;
868 }
869
870 lpn_addr = sys_be16_to_cpu(msg->lpn_addr);
871 if (lpn_addr != frnd->lpn) {
872 BT_WARN("LPN address mismatch (0x%04x != 0x%04x)",
873 lpn_addr, frnd->lpn);
874 return 0;
875 }
876
877 lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
878 if (lpn_counter != frnd->lpn_counter) {
879 BT_WARN("LPN counter mismatch (0x%04x != 0x%04x)",
880 lpn_counter, frnd->lpn_counter);
881 return 0;
882 }
883
884 k_delayed_work_cancel(&frnd->clear.timer);
885 frnd->clear.frnd = BLE_MESH_ADDR_UNASSIGNED;
886
887 return 0;
888 }
889
enqueue_offer(struct bt_mesh_friend * frnd,int8_t rssi)890 static void enqueue_offer(struct bt_mesh_friend *frnd, int8_t rssi)
891 {
892 struct bt_mesh_ctl_friend_offer *off = NULL;
893 NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*off));
894 struct net_buf *buf = NULL;
895
896 BT_DBG("%s", __func__);
897
898 net_buf_simple_reserve(&sdu, 1);
899
900 off = net_buf_simple_add(&sdu, sizeof(*off));
901
902 off->recv_win = CONFIG_BLE_MESH_FRIEND_RECV_WIN,
903 off->queue_size = CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE,
904 off->sub_list_size = ARRAY_SIZE(frnd->sub_list),
905 off->rssi = rssi,
906 off->frnd_counter = sys_cpu_to_be16(frnd->counter);
907
908 buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_OFFER, &sdu);
909 if (!buf) {
910 BT_ERR("Unable to encode Friend Offer");
911 return;
912 }
913
914 if (encrypt_friend_pdu(frnd, buf, true)) {
915 return;
916 }
917
918 frnd->counter++;
919
920 if (frnd->last) {
921 net_buf_unref(frnd->last);
922 }
923
924 frnd->last = buf;
925 frnd->send_last = 1U;
926 }
927
928 #define RECV_WIN CONFIG_BLE_MESH_FRIEND_RECV_WIN
929 #define RSSI_FACT(crit) (((crit) >> 5) & (uint8_t)BIT_MASK(2))
930 #define RECV_WIN_FACT(crit) (((crit) >> 3) & (uint8_t)BIT_MASK(2))
931 #define MIN_QUEUE_SIZE_LOG(crit) ((crit) & (uint8_t)BIT_MASK(3))
932 #define MIN_QUEUE_SIZE(crit) ((uint32_t)BIT(MIN_QUEUE_SIZE_LOG(crit)))
933
offer_delay(struct bt_mesh_friend * frnd,int8_t rssi,uint8_t crit)934 static int32_t offer_delay(struct bt_mesh_friend *frnd, int8_t rssi, uint8_t crit)
935 {
936 /* Scaling factors. The actual values are 1, 1.5, 2 & 2.5, but we
937 * want to avoid floating-point arithmetic.
938 */
939 static const uint8_t fact[] = { 10, 15, 20, 25 };
940 int32_t delay = 0;
941
942 BT_INFO("ReceiveWindowFactor %u ReceiveWindow %u RSSIFactor %u RSSI %d",
943 fact[RECV_WIN_FACT(crit)], RECV_WIN,
944 fact[RSSI_FACT(crit)], rssi);
945
946 /* Delay = ReceiveWindowFactor * ReceiveWindow - RSSIFactor * RSSI */
947 delay = (int32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN;
948 delay -= (int32_t)fact[RSSI_FACT(crit)] * rssi;
949 delay /= 10;
950
951 BT_DBG("Local Delay calculated as %d ms", delay);
952
953 if (delay < 100) {
954 return K_MSEC(100);
955 }
956
957 return K_MSEC(delay);
958 }
959
bt_mesh_friend_req(struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)960 int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
961 {
962 struct bt_mesh_ctl_friend_req *msg = (void *)buf->data;
963 struct bt_mesh_friend *frnd = NULL;
964 uint32_t poll_to = 0U;
965 int i;
966
967 if (buf->len < sizeof(*msg)) {
968 BT_WARN("Too short Friend Request (len %d)", buf->len);
969 return -EINVAL;
970 }
971
972 if (msg->recv_delay <= 0x09) {
973 BT_WARN("Prohibited ReceiveDelay (0x%02x)", msg->recv_delay);
974 return -EINVAL;
975 }
976
977 poll_to = sys_get_be24(msg->poll_to);
978
979 if (poll_to <= 0x000009 || poll_to >= 0x34bc00) {
980 BT_WARN("Prohibited PollTimeout (0x%06x)", poll_to);
981 return -EINVAL;
982 }
983
984 if (msg->num_elem == 0x00) {
985 BT_WARN("Prohibited NumElements value (0x00)");
986 return -EINVAL;
987 }
988
989 if (!BLE_MESH_ADDR_IS_UNICAST(rx->ctx.addr + msg->num_elem - 1)) {
990 BT_WARN("LPN elements stretch outside of unicast range");
991 return -EINVAL;
992 }
993
994 if (!MIN_QUEUE_SIZE_LOG(msg->criteria)) {
995 BT_WARN("Prohibited Minimum Queue Size in Friend Request");
996 return -EINVAL;
997 }
998
999 if (CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE < MIN_QUEUE_SIZE(msg->criteria)) {
1000 BT_WARN("We have a too small Friend Queue size (%u < %u)",
1001 CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE,
1002 MIN_QUEUE_SIZE(msg->criteria));
1003 return 0;
1004 }
1005
1006 frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false);
1007 if (frnd) {
1008 BT_WARN("Existing LPN re-requesting Friendship");
1009 friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_REQ);
1010 goto init_friend;
1011 }
1012
1013 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1014 if (!bt_mesh.frnd[i].valid) {
1015 frnd = &bt_mesh.frnd[i];
1016 frnd->valid = 1U;
1017 break;
1018 }
1019 }
1020
1021 if (!frnd) {
1022 BT_WARN("No free Friend contexts for new LPN");
1023 return -ENOMEM;
1024 }
1025
1026 init_friend:
1027 frnd->lpn = rx->ctx.addr;
1028 frnd->num_elem = msg->num_elem;
1029 frnd->net_idx = rx->sub->net_idx;
1030 frnd->recv_delay = msg->recv_delay;
1031 frnd->poll_to = poll_to * 100U;
1032 frnd->lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
1033 frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr);
1034
1035 BT_INFO("LPN 0x%04x rssi %d recv_delay %u poll_to %ums",
1036 frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay, frnd->poll_to);
1037
1038 /**
1039 * Spec says:
1040 * After a friendship has been established, if the PreviousAddress field
1041 * of the Friend Request message contains a valid unicast address that is
1042 * not the Friend node’s own unicast address, then the Friend node shall
1043 * begin sending Friend Clear messages to that unicast address.
1044 */
1045 if (BLE_MESH_ADDR_IS_UNICAST(frnd->clear.frnd) &&
1046 !bt_mesh_elem_find(frnd->clear.frnd)) {
1047 clear_procedure_start(frnd);
1048 }
1049
1050 k_delayed_work_submit(&frnd->timer,
1051 offer_delay(frnd, rx->ctx.recv_rssi,
1052 msg->criteria));
1053
1054 friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter,
1055 frnd->counter);
1056
1057 enqueue_offer(frnd, rx->ctx.recv_rssi);
1058
1059 return 0;
1060 }
1061
is_seg(struct bt_mesh_friend_seg * seg,uint16_t src,uint16_t seq_zero)1062 static bool is_seg(struct bt_mesh_friend_seg *seg, uint16_t src, uint16_t seq_zero)
1063 {
1064 struct net_buf *buf = (void *)sys_slist_peek_head(&seg->queue);
1065 struct net_buf_simple_state state = {0};
1066 uint16_t buf_seq_zero = 0U;
1067 uint16_t buf_src = 0U;
1068
1069 if (!buf) {
1070 return false;
1071 }
1072
1073 net_buf_simple_save(&buf->b, &state);
1074 net_buf_skip(buf, 5); /* skip IVI, NID, CTL, TTL, SEQ */
1075 buf_src = net_buf_pull_be16(buf);
1076 net_buf_skip(buf, 3); /* skip DST, OP/AID */
1077 buf_seq_zero = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK);
1078 net_buf_simple_restore(&buf->b, &state);
1079
1080 return ((src == buf_src) && (seq_zero == buf_seq_zero));
1081 }
1082
get_seg(struct bt_mesh_friend * frnd,uint16_t src,uint16_t seq_zero,uint8_t seg_count)1083 static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
1084 uint16_t src, uint16_t seq_zero,
1085 uint8_t seg_count)
1086 {
1087 struct bt_mesh_friend_seg *unassigned = NULL;
1088 int i;
1089
1090 for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
1091 struct bt_mesh_friend_seg *seg = &frnd->seg[i];
1092
1093 if (is_seg(seg, src, seq_zero)) {
1094 return seg;
1095 }
1096
1097 if (!unassigned && !sys_slist_peek_head(&seg->queue)) {
1098 unassigned = seg;
1099 }
1100 }
1101
1102 if (unassigned) {
1103 unassigned->seg_count = seg_count;
1104 }
1105
1106 return unassigned;
1107 }
1108
enqueue_friend_pdu(struct bt_mesh_friend * frnd,enum bt_mesh_friend_pdu_type type,uint16_t src,uint8_t seg_count,struct net_buf * buf)1109 static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
1110 enum bt_mesh_friend_pdu_type type,
1111 uint16_t src, uint8_t seg_count,
1112 struct net_buf *buf)
1113 {
1114 struct bt_mesh_friend_seg *seg = NULL;
1115
1116 BT_DBG("type %u", type);
1117
1118 if (type == BLE_MESH_FRIEND_PDU_SINGLE) {
1119 if (frnd->sec_update) {
1120 enqueue_update(frnd, 1);
1121 }
1122
1123 enqueue_buf(frnd, buf);
1124 return;
1125 }
1126
1127 uint16_t seq_zero = (((buf->data[10] << 8 | buf->data[11]) >> 2) & TRANS_SEQ_ZERO_MASK);
1128
1129 seg = get_seg(frnd, src, seq_zero, seg_count);
1130 if (!seg) {
1131 BT_ERR("No free friend segment RX contexts for 0x%04x", src);
1132 net_buf_unref(buf);
1133 return;
1134 }
1135
1136 net_buf_slist_put(&seg->queue, buf);
1137
1138 if (type == BLE_MESH_FRIEND_PDU_COMPLETE) {
1139 if (frnd->sec_update) {
1140 enqueue_update(frnd, 1);
1141 }
1142
1143 sys_slist_merge_slist(&frnd->queue, &seg->queue);
1144
1145 frnd->queue_size += seg->seg_count;
1146 seg->seg_count = 0U;
1147 } else {
1148 /* Mark the buffer as having more to come after it */
1149 buf->flags |= NET_BUF_FRAGS;
1150 }
1151 }
1152
buf_send_start(uint16_t duration,int err,void * user_data)1153 static void buf_send_start(uint16_t duration, int err, void *user_data)
1154 {
1155 struct bt_mesh_friend *frnd = user_data;
1156
1157 BT_DBG("err %d", err);
1158
1159 frnd->pending_buf = 0U;
1160
1161 /* Friend Offer doesn't follow the re-sending semantics */
1162 if (!frnd->established) {
1163 net_buf_unref(frnd->last);
1164 frnd->last = NULL;
1165 }
1166 }
1167
buf_send_end(int err,void * user_data)1168 static void buf_send_end(int err, void *user_data)
1169 {
1170 struct bt_mesh_friend *frnd = user_data;
1171
1172 BT_DBG("err %d", err);
1173
1174 if (frnd->pending_req) {
1175 BT_WARN("Another request before previous completed sending");
1176 return;
1177 }
1178
1179 if (frnd->established) {
1180 k_delayed_work_submit(&frnd->timer, frnd->poll_to);
1181 BT_DBG("Waiting %u ms for next poll", frnd->poll_to);
1182 } else {
1183 /* Friend offer timeout is 1 second */
1184 k_delayed_work_submit(&frnd->timer, K_SECONDS(1));
1185 BT_DBG("Waiting for first poll");
1186 }
1187 }
1188
friend_timeout(struct k_work * work)1189 static void friend_timeout(struct k_work *work)
1190 {
1191 struct bt_mesh_friend *frnd = CONTAINER_OF(work, struct bt_mesh_friend,
1192 timer.work);
1193 static const struct bt_mesh_send_cb buf_sent_cb = {
1194 .start = buf_send_start,
1195 .end = buf_send_end,
1196 };
1197
1198 if (frnd->pending_buf != 0U) {
1199 BT_ERR("Previous buffer not yet sent!");
1200 return;
1201 }
1202
1203 BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn,
1204 frnd->send_last, frnd->last);
1205
1206 if (frnd->send_last && frnd->last) {
1207 BT_DBG("Sending frnd->last %p", frnd->last);
1208 frnd->send_last = 0U;
1209 goto send_last;
1210 }
1211
1212 if (frnd->established && !frnd->pending_req) {
1213 BT_WARN("Friendship lost with 0x%04x", frnd->lpn);
1214 friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_POLL_TIMEOUT);
1215 return;
1216 }
1217
1218 frnd->last = (void *)sys_slist_get(&frnd->queue);
1219 if (!frnd->last) {
1220 BT_WARN("Friendship not established with 0x%04x", frnd->lpn);
1221 friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL);
1222 return;
1223 }
1224
1225 if (encrypt_friend_pdu(frnd, frnd->last, false)) {
1226 return;
1227 }
1228
1229 /* Clear the flag we use for segment tracking */
1230 frnd->last->flags &= ~NET_BUF_FRAGS;
1231 frnd->last->frags = NULL;
1232
1233 BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x",
1234 frnd->last, frnd->lpn);
1235 frnd->queue_size--;
1236
1237 send_last:
1238 frnd->pending_req = 0U;
1239 frnd->pending_buf = 1U;
1240 bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd);
1241 }
1242
bt_mesh_friend_set_cb(void (* cb)(bool establish,uint16_t lpn_addr,uint8_t reason))1243 void bt_mesh_friend_set_cb(void (*cb)(bool establish, uint16_t lpn_addr, uint8_t reason))
1244 {
1245 friend_cb = cb;
1246 }
1247
bt_mesh_friend_init(void)1248 int bt_mesh_friend_init(void)
1249 {
1250 int i;
1251
1252 if (friend_init == true) {
1253 BT_WARN("%s, Already", __func__);
1254 return -EALREADY;
1255 }
1256
1257 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1258 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1259 int j;
1260
1261 frnd->net_idx = BLE_MESH_KEY_UNUSED;
1262
1263 sys_slist_init(&frnd->queue);
1264
1265 k_delayed_work_init(&frnd->timer, friend_timeout);
1266 k_delayed_work_init(&frnd->clear.timer, clear_timeout);
1267
1268 for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) {
1269 sys_slist_init(&frnd->seg[j].queue);
1270 }
1271 }
1272
1273 friend_init = true;
1274
1275 return 0;
1276 }
1277
1278 #if CONFIG_BLE_MESH_DEINIT
bt_mesh_friend_deinit(void)1279 int bt_mesh_friend_deinit(void)
1280 {
1281 int i;
1282
1283 if (friend_init == false) {
1284 BT_WARN("%s, Already", __func__);
1285 return -EALREADY;
1286 }
1287
1288 bt_mesh_friend_clear_net_idx(BLE_MESH_KEY_ANY);
1289
1290 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1291 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1292
1293 frnd->net_idx = BLE_MESH_KEY_UNUSED;
1294
1295 k_delayed_work_free(&frnd->timer);
1296 k_delayed_work_free(&frnd->clear.timer);
1297 }
1298
1299 bt_mesh_unref_buf_from_pool(&friend_buf_pool);
1300 memset(adv_pool, 0, sizeof(adv_pool));
1301
1302 friend_init = false;
1303
1304 return 0;
1305 }
1306 #endif /* CONFIG_BLE_MESH_DEINIT */
1307
is_segack(struct net_buf * buf,const uint64_t * seqauth,uint16_t src)1308 static bool is_segack(struct net_buf *buf, const uint64_t *seqauth, uint16_t src)
1309 {
1310 struct net_buf_simple_state state = {0};
1311 bool found = false;
1312
1313 if (buf->len != 16) {
1314 return false;
1315 }
1316
1317 net_buf_simple_save(&buf->b, &state);
1318
1319 net_buf_skip(buf, 1); /* skip IVI, NID */
1320
1321 if (!(net_buf_pull_u8(buf) >> 7)) {
1322 goto end;
1323 }
1324
1325 net_buf_pull(buf, 3); /* skip SEQNUM */
1326
1327 if (src != net_buf_pull_be16(buf)) {
1328 goto end;
1329 }
1330
1331 net_buf_skip(buf, 2); /* skip dst */
1332
1333 if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) {
1334 goto end;
1335 }
1336
1337 found = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK) ==
1338 (*seqauth & TRANS_SEQ_ZERO_MASK);
1339 end:
1340 net_buf_simple_restore(&buf->b, &state);
1341 return found;
1342 }
1343
friend_purge_old_ack(struct bt_mesh_friend * frnd,const uint64_t * seq_auth,uint16_t src)1344 static void friend_purge_old_ack(struct bt_mesh_friend *frnd,
1345 const uint64_t *seq_auth, uint16_t src)
1346 {
1347 sys_snode_t *cur = NULL, *prev = NULL;
1348
1349 BT_DBG("SeqAuth %llx src 0x%04x", *seq_auth, src);
1350
1351 for (cur = sys_slist_peek_head(&frnd->queue);
1352 cur != NULL; prev = cur, cur = sys_slist_peek_next(cur)) {
1353 struct net_buf *buf = (void *)cur;
1354
1355 if (is_segack(buf, seq_auth, src)) {
1356 BT_DBG("Removing old ack from Friend Queue");
1357
1358 sys_slist_remove(&frnd->queue, prev, cur);
1359 frnd->queue_size--;
1360 /* Make sure old slist entry state doesn't remain */
1361 buf->frags = NULL;
1362
1363 net_buf_unref(buf);
1364 break;
1365 }
1366 }
1367 }
1368
friend_lpn_enqueue_rx(struct bt_mesh_friend * frnd,struct bt_mesh_net_rx * rx,enum bt_mesh_friend_pdu_type type,const uint64_t * seq_auth,uint8_t seg_count,struct net_buf_simple * sbuf)1369 static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
1370 struct bt_mesh_net_rx *rx,
1371 enum bt_mesh_friend_pdu_type type,
1372 const uint64_t *seq_auth, uint8_t seg_count,
1373 struct net_buf_simple *sbuf)
1374 {
1375 struct friend_pdu_info info = {0};
1376 struct net_buf *buf = NULL;
1377
1378 /* Because of network loopback, tx packets will also be passed into
1379 * this rx function. These packets have already been added to the
1380 * queue, and should be ignored.
1381 */
1382 if (bt_mesh_elem_find(rx->ctx.addr)) {
1383 return;
1384 }
1385
1386 BT_DBG("LPN 0x%04x queue_size %u", frnd->lpn, frnd->queue_size);
1387
1388 if (type == BLE_MESH_FRIEND_PDU_SINGLE && seq_auth) {
1389 friend_purge_old_ack(frnd, seq_auth, rx->ctx.addr);
1390 }
1391
1392 info.src = rx->ctx.addr;
1393 info.dst = rx->ctx.recv_dst;
1394
1395 if (rx->net_if == BLE_MESH_NET_IF_LOCAL) {
1396 info.ttl = rx->ctx.recv_ttl;
1397 } else {
1398 info.ttl = rx->ctx.recv_ttl - 1U;
1399 }
1400
1401 info.ctl = rx->ctl;
1402
1403 sys_put_be24(rx->seq, info.seq);
1404
1405 info.iv_index = BLE_MESH_NET_IVI_RX(rx);
1406
1407 buf = create_friend_pdu(frnd, &info, sbuf);
1408 if (!buf) {
1409 BT_ERR("Failed to encode Friend buffer");
1410 return;
1411 }
1412
1413 enqueue_friend_pdu(frnd, type, info.src, seg_count, buf);
1414
1415 BT_DBG("Queued message for LPN 0x%04x, queue_size %u",
1416 frnd->lpn, frnd->queue_size);
1417 }
1418
friend_lpn_enqueue_tx(struct bt_mesh_friend * frnd,struct bt_mesh_net_tx * tx,enum bt_mesh_friend_pdu_type type,const uint64_t * seq_auth,uint8_t seg_count,struct net_buf_simple * sbuf)1419 static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
1420 struct bt_mesh_net_tx *tx,
1421 enum bt_mesh_friend_pdu_type type,
1422 const uint64_t *seq_auth, uint8_t seg_count,
1423 struct net_buf_simple *sbuf)
1424 {
1425 struct friend_pdu_info info = {0};
1426 struct net_buf *buf = NULL;
1427
1428 BT_DBG("LPN 0x%04x", frnd->lpn);
1429
1430 if (type == BLE_MESH_FRIEND_PDU_SINGLE && seq_auth) {
1431 friend_purge_old_ack(frnd, seq_auth, tx->src);
1432 }
1433
1434 info.src = tx->src;
1435 info.dst = tx->ctx->addr;
1436
1437 info.ttl = tx->ctx->send_ttl;
1438 info.ctl = (tx->ctx->app_idx == BLE_MESH_KEY_UNUSED);
1439
1440 sys_put_be24(bt_mesh.seq, info.seq);
1441
1442 info.iv_index = BLE_MESH_NET_IVI_TX;
1443
1444 buf = create_friend_pdu(frnd, &info, sbuf);
1445 if (!buf) {
1446 BT_ERR("Failed to encode Friend buffer");
1447 return;
1448 }
1449
1450 if (type == BLE_MESH_FRIEND_PDU_SINGLE && !info.ctl) {
1451 /* Unsegmented application packets may be re-encrypted later,
1452 * as they depend on the the sequence number being the same
1453 * when encrypting in transport and network.
1454 */
1455 FRIEND_ADV(buf)->app_idx = tx->ctx->app_idx;
1456 }
1457
1458 enqueue_friend_pdu(frnd, type, info.src, seg_count, buf);
1459
1460 BT_DBG("Queued message for LPN 0x%04x", frnd->lpn);
1461 }
1462
friend_lpn_matches(struct bt_mesh_friend * frnd,uint16_t net_idx,uint16_t addr)1463 static bool friend_lpn_matches(struct bt_mesh_friend *frnd, uint16_t net_idx,
1464 uint16_t addr)
1465 {
1466 int i;
1467
1468 if (!frnd->established) {
1469 return false;
1470 }
1471
1472 if (net_idx != frnd->net_idx) {
1473 return false;
1474 }
1475
1476 if (BLE_MESH_ADDR_IS_UNICAST(addr)) {
1477 return is_lpn_unicast(frnd, addr);
1478 }
1479
1480 for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
1481 if (frnd->sub_list[i] == addr) {
1482 return true;
1483 }
1484 }
1485
1486 return false;
1487 }
1488
bt_mesh_friend_match(uint16_t net_idx,uint16_t addr)1489 bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr)
1490 {
1491 int i;
1492
1493 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1494 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1495
1496 if (friend_lpn_matches(frnd, net_idx, addr)) {
1497 BT_DBG("LPN 0x%04x matched address 0x%04x",
1498 frnd->lpn, addr);
1499 return true;
1500 }
1501 }
1502
1503 BT_DBG("No matching LPN for address 0x%04x", addr);
1504
1505 return false;
1506 }
1507
friend_queue_has_space(struct bt_mesh_friend * frnd,uint16_t addr,const uint64_t * seq_auth,uint8_t seg_count)1508 static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr,
1509 const uint64_t *seq_auth, uint8_t seg_count)
1510 {
1511 uint32_t total = 0U;
1512 int i;
1513
1514 if (seg_count > CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE) {
1515 return false;
1516 }
1517
1518 for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
1519 struct bt_mesh_friend_seg *seg = &frnd->seg[i];
1520
1521 if (seq_auth && is_seg(seg, addr, *seq_auth & TRANS_SEQ_ZERO_MASK)) {
1522 /* If there's a segment queue for this message then the
1523 * space verification has already happened.
1524 */
1525 return true;
1526 }
1527
1528 total += seg->seg_count;
1529 }
1530
1531 /* If currently pending segments combined with this segmented message
1532 * are more than the Friend Queue Size, then there's no space. This
1533 * is because we don't have a mechanism of aborting already pending
1534 * segmented messages to free up buffers.
1535 */
1536 return (CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE - total) > seg_count;
1537 }
1538
bt_mesh_friend_queue_has_space(uint16_t net_idx,uint16_t src,uint16_t dst,const uint64_t * seq_auth,uint8_t seg_count)1539 bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst,
1540 const uint64_t *seq_auth, uint8_t seg_count)
1541 {
1542 bool someone_has_space = false, friend_match = false;
1543 int i;
1544
1545 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1546 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1547
1548 if (!friend_lpn_matches(frnd, net_idx, dst)) {
1549 continue;
1550 }
1551
1552 friend_match = true;
1553
1554 if (friend_queue_has_space(frnd, src, seq_auth, seg_count)) {
1555 someone_has_space = true;
1556 }
1557 }
1558
1559 /* If there were no matched LPNs treat this as success, so the
1560 * transport layer can continue its work.
1561 */
1562 if (!friend_match) {
1563 return true;
1564 }
1565
1566 /* From the transport layers perspective it's good enough that at
1567 * least one Friend Queue has space. If there were multiple Friend
1568 * matches then the destination must be a group address, in which
1569 * case e.g. segment acks are not sent.
1570 */
1571 return someone_has_space;
1572 }
1573
friend_queue_prepare_space(struct bt_mesh_friend * frnd,uint16_t addr,const uint64_t * seq_auth,uint8_t seg_count)1574 static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t addr,
1575 const uint64_t *seq_auth, uint8_t seg_count)
1576 {
1577 bool pending_segments = false;
1578 uint8_t avail_space = 0U;
1579
1580 if (!friend_queue_has_space(frnd, addr, seq_auth, seg_count)) {
1581 return false;
1582 }
1583
1584 avail_space = CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE - frnd->queue_size;
1585 pending_segments = false;
1586
1587 while (pending_segments || avail_space < seg_count) {
1588 struct net_buf *buf = (void *)sys_slist_get(&frnd->queue);
1589
1590 if (!buf) {
1591 BT_ERR("Unable to free up enough buffers");
1592 return false;
1593 }
1594
1595 frnd->queue_size--;
1596 avail_space++;
1597
1598 pending_segments = (buf->flags & NET_BUF_FRAGS);
1599
1600 /* Make sure old slist entry state doesn't remain */
1601 buf->frags = NULL;
1602 buf->flags &= ~NET_BUF_FRAGS;
1603
1604 net_buf_unref(buf);
1605 }
1606
1607 return true;
1608 }
1609
bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx * rx,enum bt_mesh_friend_pdu_type type,const uint64_t * seq_auth,uint8_t seg_count,struct net_buf_simple * sbuf)1610 void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
1611 enum bt_mesh_friend_pdu_type type,
1612 const uint64_t *seq_auth, uint8_t seg_count,
1613 struct net_buf_simple *sbuf)
1614 {
1615 int i;
1616
1617 if (!rx->friend_match ||
1618 (rx->ctx.recv_ttl <= 1U && rx->net_if != BLE_MESH_NET_IF_LOCAL) ||
1619 bt_mesh_friend_get() != BLE_MESH_FRIEND_ENABLED) {
1620 return;
1621 }
1622
1623 BT_DBG("recv_ttl %u net_idx 0x%04x src 0x%04x dst 0x%04x",
1624 rx->ctx.recv_ttl, rx->sub->net_idx, rx->ctx.addr,
1625 rx->ctx.recv_dst);
1626
1627 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1628 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1629
1630 if (!friend_lpn_matches(frnd, rx->sub->net_idx,
1631 rx->ctx.recv_dst)) {
1632 continue;
1633 }
1634
1635 if (!friend_queue_prepare_space(frnd, rx->ctx.addr, seq_auth,
1636 seg_count)) {
1637 continue;
1638 }
1639
1640 friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, seg_count,
1641 sbuf);
1642 }
1643 }
1644
bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx * tx,enum bt_mesh_friend_pdu_type type,const uint64_t * seq_auth,uint8_t seg_count,struct net_buf_simple * sbuf)1645 bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
1646 enum bt_mesh_friend_pdu_type type,
1647 const uint64_t *seq_auth, uint8_t seg_count,
1648 struct net_buf_simple *sbuf)
1649 {
1650 bool matched = false;
1651 int i;
1652
1653 if (!bt_mesh_friend_match(tx->sub->net_idx, tx->ctx->addr) ||
1654 bt_mesh_friend_get() != BLE_MESH_FRIEND_ENABLED) {
1655 return matched;
1656 }
1657
1658 BT_DBG("net_idx 0x%04x dst 0x%04x src 0x%04x", tx->sub->net_idx,
1659 tx->ctx->addr, tx->src);
1660
1661 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1662 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1663
1664 if (!friend_lpn_matches(frnd, tx->sub->net_idx,
1665 tx->ctx->addr)) {
1666 continue;
1667 }
1668
1669 if (!friend_queue_prepare_space(frnd, tx->src, seq_auth,
1670 seg_count)) {
1671 continue;
1672 }
1673
1674 friend_lpn_enqueue_tx(frnd, tx, type, seq_auth, seg_count,
1675 sbuf);
1676 matched = true;
1677 }
1678
1679 return matched;
1680 }
1681
bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet * sub,uint16_t src,uint16_t dst,const uint64_t * seq_auth)1682 void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src,
1683 uint16_t dst, const uint64_t *seq_auth)
1684 {
1685 int i;
1686
1687 BT_DBG("%s", __func__);
1688
1689 for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1690 struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1691 int j;
1692
1693 if (!friend_lpn_matches(frnd, sub->net_idx, dst)) {
1694 continue;
1695 }
1696
1697 for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) {
1698 struct bt_mesh_friend_seg *seg = &frnd->seg[j];
1699
1700 if (!is_seg(seg, src, *seq_auth & TRANS_SEQ_ZERO_MASK)) {
1701 continue;
1702 }
1703
1704 BT_WARN("Clearing incomplete segments for 0x%04x", src);
1705
1706 purge_buffers(&seg->queue);
1707 seg->seg_count = 0U;
1708 break;
1709 }
1710 }
1711 }
1712
bt_mesh_friend_remove_lpn(uint16_t lpn_addr)1713 void bt_mesh_friend_remove_lpn(uint16_t lpn_addr)
1714 {
1715 struct bt_mesh_friend *frnd = NULL;
1716
1717 frnd = bt_mesh_friend_find(BLE_MESH_KEY_ANY, lpn_addr, false, false);
1718 if (frnd) {
1719 friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE);
1720 }
1721 }
1722
1723 #endif /* CONFIG_BLE_MESH_FRIEND */
1724