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