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