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