xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/mesh/src/friend.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*  Bluetooth Mesh */
2 
3 /*
4  * Copyright (c) 2017 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 
10 #include "syscfg/syscfg.h"
11 #if MYNEWT_VAL(BLE_MESH_FRIEND) == 1
12 
13 #include <stdint.h>
14 #include <errno.h>
15 #include <assert.h>
16 
17 #define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_FRIEND))
18 #include "host/ble_hs_log.h"
19 
20 #include "mesh/mesh.h"
21 #include "mesh/slist.h"
22 #include "mesh_priv.h"
23 #include "crypto.h"
24 #include "adv.h"
25 #include "net.h"
26 #include "transport.h"
27 #include "access.h"
28 #include "foundation.h"
29 #include "friend.h"
30 
31 /* We reserve one extra buffer for each friendship, since we need to be able
32  * to resend the last sent PDU, which sits separately outside of the queue.
33  */
34 #define FRIEND_BUF_COUNT ((MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE) + 1) * MYNEWT_VAL(BLE_MESH_FRIEND_LPN_COUNT))
35 
36 static os_membuf_t friend_buf_mem[OS_MEMPOOL_SIZE(
37 		FRIEND_BUF_COUNT,
38 		BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)];
39 
40 struct os_mbuf_pool friend_os_mbuf_pool;
41 static struct os_mempool friend_buf_mempool;
42 
43 
44 #define FRIEND_ADV(buf)     CONTAINER_OF(BT_MESH_ADV(buf), \
45 					 struct friend_adv, adv)
46 
47 /* PDUs from Friend to the LPN should only be transmitted once with the
48  * smallest possible interval (20ms).
49  */
50 #define FRIEND_XMIT         BT_MESH_TRANSMIT(0, 20)
51 
52 struct friend_pdu_info {
53 	u16_t  src;
54 	u16_t  dst;
55 
56 	u8_t   seq[3];
57 
58 	u8_t   ttl:7,
59 	       ctl:1;
60 
61 	u32_t  iv_index;
62 };
63 
64 static struct friend_adv {
65 	struct bt_mesh_adv adv;
66 	u64_t seq_auth;
67 } adv_pool[FRIEND_BUF_COUNT];
68 
adv_alloc(int id)69 static struct bt_mesh_adv *adv_alloc(int id)
70 {
71 	return &adv_pool[id].adv;
72 }
73 
discard_buffer(void)74 static void discard_buffer(void)
75 {
76 	struct bt_mesh_friend *frnd = &bt_mesh.frnd[0];
77 	struct os_mbuf *buf;
78 	int i;
79 
80 	/* Find the Friend context with the most queued buffers */
81 	for (i = 1; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
82 		if (bt_mesh.frnd[i].queue_size > frnd->queue_size) {
83 			frnd = &bt_mesh.frnd[i];
84 		}
85 	}
86 
87 	buf = net_buf_slist_get(&frnd->queue);
88 	__ASSERT_NO_MSG(buf != NULL);
89 	BT_WARN("Discarding buffer %p for LPN 0x%04x", buf, frnd->lpn);
90 	net_buf_unref(buf);
91 }
92 
friend_buf_alloc(u16_t src)93 static struct os_mbuf *friend_buf_alloc(u16_t src)
94 {
95 	struct os_mbuf *buf;
96 
97 	do {
98 		buf = bt_mesh_adv_create_from_pool(&friend_os_mbuf_pool, adv_alloc,
99 						   BT_MESH_ADV_DATA,
100 						   FRIEND_XMIT, K_NO_WAIT);
101 		if (!buf) {
102 			discard_buffer();
103 		}
104 	} while (!buf);
105 
106 	BT_MESH_ADV(buf)->addr = src;
107 	FRIEND_ADV(buf)->seq_auth = TRANS_SEQ_AUTH_NVAL;
108 
109 	BT_DBG("allocated buf %p", buf);
110 
111 	return buf;
112 }
113 
bt_mesh_friend_find(u16_t net_idx,u16_t lpn_addr,bool valid,bool established)114 struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
115 					   bool valid, bool established)
116 {
117 	int i;
118 
119 	BT_DBG("net_idx 0x%04x lpn_addr 0x%04x", net_idx, lpn_addr);
120 
121 	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
122 		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
123 
124 		if (valid && !frnd->valid) {
125 			continue;
126 		}
127 
128 		if (established && !frnd->established) {
129 			continue;
130 		}
131 
132 		if (net_idx != BT_MESH_KEY_ANY && frnd->net_idx != net_idx) {
133 			continue;
134 		}
135 
136 		if (frnd->lpn == lpn_addr) {
137 			return frnd;
138 		}
139 	}
140 
141 	return NULL;
142 }
143 
144 /* Intentionally start a little bit late into the ReceiveWindow when
145  * it's large enough. This may improve reliability with some platforms,
146  * like the PTS, where the receiver might not have sufficiently compensated
147  * for internal latencies required to start scanning.
148  */
recv_delay(struct bt_mesh_friend * frnd)149 static s32_t recv_delay(struct bt_mesh_friend *frnd)
150 {
151 #if CONFIG_BT_MESH_FRIEND_RECV_WIN > 50
152 	return (s32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5);
153 #else
154 	return frnd->recv_delay;
155 #endif
156 }
157 
friend_clear(struct bt_mesh_friend * frnd)158 static void friend_clear(struct bt_mesh_friend *frnd)
159 {
160 	int i;
161 
162 	BT_DBG("LPN 0x%04x", frnd->lpn);
163 
164 	k_delayed_work_cancel(&frnd->timer);
165 
166 	friend_cred_del(frnd->net_idx, frnd->lpn);
167 
168 	if (frnd->last) {
169 		/* Cancel the sending if necessary */
170 		if (frnd->pending_buf) {
171 			BT_MESH_ADV(frnd->last)->busy = 0;
172 		}
173 
174 		net_buf_unref(frnd->last);
175 		frnd->last = NULL;
176 	}
177 
178 	while (!net_buf_slist_is_empty(&frnd->queue)) {
179 		net_buf_unref(net_buf_slist_get(&frnd->queue));
180 	}
181 
182 	for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
183 		struct bt_mesh_friend_seg *seg = &frnd->seg[i];
184 
185 		while (!net_buf_slist_is_empty(&seg->queue)) {
186 			net_buf_unref(net_buf_slist_get(&seg->queue));
187 		}
188 	}
189 
190 	frnd->valid = 0;
191 	frnd->established = 0;
192 	frnd->pending_buf = 0;
193 	frnd->fsn = 0;
194 	frnd->queue_size = 0;
195 	frnd->pending_req = 0;
196 	memset(frnd->sub_list, 0, sizeof(frnd->sub_list));
197 }
198 
bt_mesh_friend_clear_net_idx(u16_t net_idx)199 void bt_mesh_friend_clear_net_idx(u16_t net_idx)
200 {
201 	int i;
202 
203 	BT_DBG("net_idx 0x%04x", net_idx);
204 
205 	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
206 		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
207 
208 		if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
209 			continue;
210 		}
211 
212 		if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
213 			friend_clear(frnd);
214 		}
215 	}
216 }
217 
bt_mesh_friend_sec_update(u16_t net_idx)218 void bt_mesh_friend_sec_update(u16_t net_idx)
219 {
220 	int i;
221 
222 	BT_DBG("net_idx 0x%04x", net_idx);
223 
224 	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
225 		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
226 
227 		if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
228 			continue;
229 		}
230 
231 		if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
232 			frnd->sec_update = 1;
233 		}
234 	}
235 }
236 
bt_mesh_friend_clear(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)237 int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
238 {
239 	struct bt_mesh_ctl_friend_clear *msg = (void *)buf->om_data;
240 	struct bt_mesh_friend *frnd;
241 	u16_t lpn_addr, lpn_counter;
242 	struct bt_mesh_net_tx tx = {
243 		.sub  = rx->sub,
244 		.ctx  = &rx->ctx,
245 		.src  = bt_mesh_primary_addr(),
246 		.xmit = bt_mesh_net_transmit_get(),
247 	};
248 	struct bt_mesh_ctl_friend_clear_confirm cfm;
249 
250 	if (buf->om_len < sizeof(*msg)) {
251 		BT_WARN("Too short Friend Clear");
252 		return -EINVAL;
253 	}
254 
255 	lpn_addr = sys_be16_to_cpu(msg->lpn_addr);
256 	lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
257 
258 	BT_DBG("LPN addr 0x%04x counter 0x%04x", lpn_addr, lpn_counter);
259 
260 	frnd = bt_mesh_friend_find(rx->sub->net_idx, lpn_addr, false, false);
261 	if (!frnd) {
262 		BT_WARN("No matching LPN addr 0x%04x", lpn_addr);
263 		return 0;
264 	}
265 
266 	/* A Friend Clear message is considered valid if the result of the
267 	 * subtraction of the value of the LPNCounter field of the Friend
268 	 * Request message (the one that initiated the friendship) from the
269 	 * value of the LPNCounter field of the Friend Clear message, modulo
270 	 * 65536, is in the range 0 to 255 inclusive.
271 	 */
272 	if (lpn_counter - frnd->lpn_counter > 255) {
273 		BT_WARN("LPN Counter out of range (old %u new %u)",
274 			frnd->lpn_counter, lpn_counter);
275 		return 0;
276 	}
277 
278 	tx.ctx->send_ttl = BT_MESH_TTL_MAX;
279 
280 	cfm.lpn_addr    = msg->lpn_addr;
281 	cfm.lpn_counter = msg->lpn_counter;
282 
283 	bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm,
284 			 sizeof(cfm), NULL, NULL, NULL);
285 
286 	friend_clear(frnd);
287 
288 	return 0;
289 }
290 
friend_sub_add(struct bt_mesh_friend * frnd,u16_t addr)291 static void friend_sub_add(struct bt_mesh_friend *frnd, u16_t addr)
292 {
293 	int i;
294 
295 	for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
296 		if (frnd->sub_list[i] == BT_MESH_ADDR_UNASSIGNED) {
297 			frnd->sub_list[i] = addr;
298 			return;
299 		}
300 	}
301 
302 	BT_WARN("No space in friend subscription list");
303 }
304 
friend_sub_rem(struct bt_mesh_friend * frnd,u16_t addr)305 static void friend_sub_rem(struct bt_mesh_friend *frnd, u16_t addr)
306 {
307 	int i;
308 
309 	for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
310 		if (frnd->sub_list[i] == addr) {
311 			frnd->sub_list[i] = BT_MESH_ADDR_UNASSIGNED;
312 			return;
313 		}
314 	}
315 }
316 
create_friend_pdu(struct bt_mesh_friend * frnd,struct friend_pdu_info * info,struct os_mbuf * sdu)317 static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd,
318 					 struct friend_pdu_info *info,
319 					 struct os_mbuf *sdu)
320 {
321 	struct bt_mesh_subnet *sub;
322 	const u8_t *enc, *priv;
323 	struct os_mbuf *buf;
324 	u8_t nid;
325 
326 	sub = bt_mesh_subnet_get(frnd->net_idx);
327 	__ASSERT_NO_MSG(sub != NULL);
328 
329 	buf = friend_buf_alloc(info->src);
330 
331 	/* Friend Offer needs master security credentials */
332 	if (info->ctl && TRANS_CTL_OP(sdu->om_data) == TRANS_CTL_OP_FRIEND_OFFER) {
333 		enc = sub->keys[sub->kr_flag].enc;
334 		priv = sub->keys[sub->kr_flag].privacy;
335 		nid = sub->keys[sub->kr_flag].nid;
336 	} else {
337 		if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
338 			BT_ERR("friend_cred_get failed");
339 			goto failed;
340 		}
341 	}
342 
343 	net_buf_add_u8(buf, (nid | (info->iv_index & 1) << 7));
344 
345 	if (info->ctl) {
346 		net_buf_add_u8(buf, info->ttl | 0x80);
347 	} else {
348 		net_buf_add_u8(buf, info->ttl);
349 	}
350 
351 	net_buf_add_mem(buf, info->seq, sizeof(info->seq));
352 
353 	net_buf_add_be16(buf, info->src);
354 	net_buf_add_be16(buf, info->dst);
355 
356 	net_buf_add_mem(buf, sdu->om_data, sdu->om_len);
357 
358 	/* We re-encrypt and obfuscate using the received IVI rather than
359 	 * the normal TX IVI (which may be different) since the transport
360 	 * layer nonce includes the IVI.
361 	 */
362 	if (bt_mesh_net_encrypt(enc, buf, info->iv_index, false)) {
363 		BT_ERR("Re-encrypting failed");
364 		goto failed;
365 	}
366 
367 	if (bt_mesh_net_obfuscate(buf->om_data, info->iv_index, priv)) {
368 		BT_ERR("Re-obfuscating failed");
369 		goto failed;
370 	}
371 
372 	return buf;
373 
374 failed:
375 	net_buf_unref(buf);
376 	return NULL;
377 }
378 
encode_friend_ctl(struct bt_mesh_friend * frnd,u8_t ctl_op,struct os_mbuf * sdu)379 static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
380 					 u8_t ctl_op,
381 					 struct os_mbuf *sdu)
382 {
383 	struct friend_pdu_info info;
384 	u32_t seq;
385 
386 	BT_DBG("LPN 0x%04x", frnd->lpn);
387 
388 	net_buf_simple_push_u8(sdu, TRANS_CTL_HDR(ctl_op, 0));
389 
390 	info.src = bt_mesh_primary_addr();
391 	info.dst = frnd->lpn;
392 
393 	info.ctl = 1;
394 	info.ttl = 0;
395 
396 	seq = bt_mesh_next_seq();
397 	info.seq[0] = seq >> 16;
398 	info.seq[1] = seq >> 8;
399 	info.seq[2] = seq;
400 
401 	info.iv_index = BT_MESH_NET_IVI_TX;
402 
403 	return create_friend_pdu(frnd, &info, sdu);
404 }
405 
encode_update(struct bt_mesh_friend * frnd,u8_t md)406 static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, u8_t md)
407 {
408 	struct bt_mesh_ctl_friend_update *upd;
409 	struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*upd));
410 	struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
411 	struct os_mbuf *buf;
412 
413 	__ASSERT_NO_MSG(sub != NULL);
414 
415 	BT_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md);
416 
417 	net_buf_simple_init(sdu, 1);
418 
419 	upd = net_buf_simple_add(sdu, sizeof(*upd));
420 	upd->flags = bt_mesh_net_flags(sub);
421 	upd->iv_index = sys_cpu_to_be32(bt_mesh.iv_index);
422 	upd->md = md;
423 
424 	buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_UPDATE, sdu);
425 
426 	os_mbuf_free_chain(sdu);
427 	return buf;
428 }
429 
enqueue_sub_cfm(struct bt_mesh_friend * frnd,u8_t xact)430 static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, u8_t xact)
431 {
432 	struct bt_mesh_ctl_friend_sub_confirm *cfm;
433 	struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*cfm));
434 	struct os_mbuf *buf;
435 
436 	BT_DBG("lpn 0x%04x xact 0x%02x", frnd->lpn, xact);
437 
438 	net_buf_simple_init(sdu, 1);
439 
440 	cfm = net_buf_simple_add(sdu, sizeof(*cfm));
441 	cfm->xact = xact;
442 
443 	buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_SUB_CFM, sdu);
444 	if (!buf) {
445 		BT_ERR("Unable to encode Subscription List Confirmation");
446 		goto done;
447 	}
448 
449 	if (frnd->last) {
450 		BT_DBG("Discarding last PDU");
451 		net_buf_unref(frnd->last);
452 	}
453 
454 	frnd->last = buf;
455 	frnd->send_last = 1;
456 
457 done:
458 	os_mbuf_free_chain(sdu);
459 }
460 
friend_recv_delay(struct bt_mesh_friend * frnd)461 static void friend_recv_delay(struct bt_mesh_friend *frnd)
462 {
463 	frnd->pending_req = 1;
464 	k_delayed_work_submit(&frnd->timer, recv_delay(frnd));
465 	BT_DBG("Waiting RecvDelay of %d ms", recv_delay(frnd));
466 }
467 
bt_mesh_friend_sub_add(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)468 int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
469 			   struct os_mbuf *buf)
470 {
471 	struct bt_mesh_friend *frnd;
472 	u8_t xact;
473 
474 	if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) {
475 		BT_WARN("Too short Friend Subscription Add");
476 		return -EINVAL;
477 	}
478 
479 	frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true);
480 	if (!frnd) {
481 		BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
482 		return 0;
483 	}
484 
485 	if (frnd->pending_buf) {
486 		BT_WARN("Previous buffer not yet sent!");
487 		return 0;
488 	}
489 
490 	friend_recv_delay(frnd);
491 
492 	xact = net_buf_simple_pull_u8(buf);
493 
494 	while (buf->om_len >= 2) {
495 		friend_sub_add(frnd, net_buf_simple_pull_be16(buf));
496 	}
497 
498 	enqueue_sub_cfm(frnd, xact);
499 
500 	return 0;
501 }
502 
bt_mesh_friend_sub_rem(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)503 int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
504 			   struct os_mbuf *buf)
505 {
506 	struct bt_mesh_friend *frnd;
507 	u8_t xact;
508 
509 	if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) {
510 		BT_WARN("Too short Friend Subscription Remove");
511 		return -EINVAL;
512 	}
513 
514 	frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true);
515 	if (!frnd) {
516 		BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
517 		return 0;
518 	}
519 
520 	if (frnd->pending_buf) {
521 		BT_WARN("Previous buffer not yet sent!");
522 		return 0;
523 	}
524 
525 	friend_recv_delay(frnd);
526 
527 	xact = net_buf_simple_pull_u8(buf);
528 
529 	while (buf->om_len >= 2) {
530 		friend_sub_rem(frnd, net_buf_simple_pull_be16(buf));
531 	}
532 
533 	enqueue_sub_cfm(frnd, xact);
534 
535 	return 0;
536 }
537 
enqueue_buf(struct bt_mesh_friend * frnd,struct os_mbuf * buf)538 static void enqueue_buf(struct bt_mesh_friend *frnd, struct os_mbuf *buf)
539 {
540 	net_buf_slist_put(&frnd->queue, buf);
541 	frnd->queue_size++;
542 }
543 
enqueue_update(struct bt_mesh_friend * frnd,u8_t md)544 static void enqueue_update(struct bt_mesh_friend *frnd, u8_t md)
545 {
546 	struct os_mbuf *buf;
547 
548 	buf = encode_update(frnd, md);
549 	if (!buf) {
550 		BT_ERR("Unable to encode Friend Update");
551 		return;
552 	}
553 
554 	frnd->sec_update = 0;
555 	enqueue_buf(frnd, buf);
556 }
557 
bt_mesh_friend_poll(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)558 int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
559 {
560 	struct bt_mesh_ctl_friend_poll *msg = (void *)buf->om_data;
561 	struct bt_mesh_friend *frnd;
562 
563 	if (buf->om_len < sizeof(*msg)) {
564 		BT_WARN("Too short Friend Poll");
565 		return -EINVAL;
566 	}
567 
568 	frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false);
569 	if (!frnd) {
570 		BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
571 		return 0;
572 	}
573 
574 	if (msg->fsn & ~1) {
575 		BT_WARN("Prohibited (non-zero) padding bits");
576 		return -EINVAL;
577 	}
578 
579 	if (frnd->pending_buf) {
580 		BT_WARN("Previous buffer not yet sent");
581 		return 0;
582 	}
583 
584 	BT_DBG("msg->fsn %u frnd->fsn %u", (msg->fsn & 1), frnd->fsn);
585 
586 	friend_recv_delay(frnd);
587 
588 	if (!frnd->established) {
589 		BT_DBG("Friendship established with 0x%04x", frnd->lpn);
590 		frnd->established = 1;
591 	}
592 
593 	if (msg->fsn == frnd->fsn && frnd->last) {
594 		BT_DBG("Re-sending last PDU");
595 		frnd->send_last = 1;
596 	} else {
597 		if (frnd->last) {
598 			net_buf_unref(frnd->last);
599 			frnd->last = NULL;
600 		}
601 
602 		frnd->fsn = msg->fsn;
603 
604 		if (net_buf_slist_is_empty(&frnd->queue)) {
605 			enqueue_update(frnd, 0);
606 			BT_DBG("Enqueued Friend Update to empty queue");
607 		}
608 	}
609 
610 	return 0;
611 }
612 
find_clear(u16_t prev_friend)613 static struct bt_mesh_friend *find_clear(u16_t prev_friend)
614 {
615 	int i;
616 
617 	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
618 		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
619 
620 		if (frnd->clear.frnd == prev_friend) {
621 			return frnd;
622 		}
623 	}
624 
625 	return NULL;
626 }
627 
friend_clear_sent(int err,void * user_data)628 static void friend_clear_sent(int err, void *user_data)
629 {
630 	struct bt_mesh_friend *frnd = user_data;
631 
632 	k_delayed_work_submit(&frnd->clear.timer,
633 			      K_SECONDS(frnd->clear.repeat_sec));
634 	frnd->clear.repeat_sec *= 2;
635 }
636 
637 static const struct bt_mesh_send_cb clear_sent_cb = {
638 	.end = friend_clear_sent,
639 };
640 
send_friend_clear(struct bt_mesh_friend * frnd)641 static void send_friend_clear(struct bt_mesh_friend *frnd)
642 {
643 	struct bt_mesh_msg_ctx ctx = {
644 		.net_idx  = frnd->net_idx,
645 		.app_idx  = BT_MESH_KEY_UNUSED,
646 		.addr     = frnd->clear.frnd,
647 		.send_ttl = BT_MESH_TTL_MAX,
648 	};
649 	struct bt_mesh_net_tx tx = {
650 		.sub  = &bt_mesh.sub[0],
651 		.ctx  = &ctx,
652 		.src  = bt_mesh_primary_addr(),
653 		.xmit = bt_mesh_net_transmit_get(),
654 	};
655 	struct bt_mesh_ctl_friend_clear req = {
656 		.lpn_addr    = sys_cpu_to_be16(frnd->lpn),
657 		.lpn_counter = sys_cpu_to_be16(frnd->lpn_counter),
658 	};
659 
660 	BT_DBG("");
661 
662 	bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
663 			 sizeof(req), NULL, &clear_sent_cb, frnd);
664 }
665 
clear_timeout(struct ble_npl_event * work)666 static void clear_timeout(struct ble_npl_event *work)
667 {
668 	struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work);
669 	u32_t duration;
670 
671 	BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
672 
673 	duration = k_uptime_get_32() - frnd->clear.start;
674 	if (duration > 2 * frnd->poll_to) {
675 		BT_DBG("Clear Procedure timer expired");
676 		frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED;
677 		return;
678 	}
679 
680 	send_friend_clear(frnd);
681 }
682 
clear_procedure_start(struct bt_mesh_friend * frnd)683 static void clear_procedure_start(struct bt_mesh_friend *frnd)
684 {
685 	BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
686 
687 	frnd->clear.start = k_uptime_get_32() + (2 * frnd->poll_to);
688 	frnd->clear.repeat_sec = 1;
689 
690 	send_friend_clear(frnd);
691 }
692 
bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)693 int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
694 			     struct os_mbuf *buf)
695 {
696 	struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data;
697 	struct bt_mesh_friend *frnd;
698 	u16_t lpn_addr, lpn_counter;
699 
700 	BT_DBG("");
701 
702 	if (buf->om_len < sizeof(*msg)) {
703 		BT_WARN("Too short Friend Clear Confirm");
704 		return -EINVAL;
705 	}
706 
707 	frnd = find_clear(rx->ctx.addr);
708 	if (!frnd) {
709 		BT_WARN("No pending clear procedure for 0x%02x", rx->ctx.addr);
710 		return 0;
711 	}
712 
713 	lpn_addr = sys_be16_to_cpu(msg->lpn_addr);
714 	if (lpn_addr != frnd->lpn) {
715 		BT_WARN("LPN address mismatch (0x%04x != 0x%04x)",
716 			lpn_addr, frnd->lpn);
717 		return 0;
718 	}
719 
720 	lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
721 	if (lpn_counter != frnd->lpn_counter) {
722 		BT_WARN("LPN counter mismatch (0x%04x != 0x%04x)",
723 			lpn_counter, frnd->lpn_counter);
724 		return 0;
725 	}
726 
727 	k_delayed_work_cancel(&frnd->clear.timer);
728 	frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED;
729 
730 	return 0;
731 }
732 
enqueue_offer(struct bt_mesh_friend * frnd,s8_t rssi)733 static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
734 {
735 	struct bt_mesh_ctl_friend_offer *off;
736 	struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*off));
737 	struct os_mbuf *buf;
738 
739 	BT_DBG("");
740 
741 	net_buf_simple_init(sdu, 1);
742 
743 	off = net_buf_simple_add(sdu, sizeof(*off));
744 
745 	off->recv_win = CONFIG_BT_MESH_FRIEND_RECV_WIN,
746 	off->queue_size = CONFIG_BT_MESH_FRIEND_QUEUE_SIZE,
747 	off->sub_list_size = ARRAY_SIZE(frnd->sub_list),
748 	off->rssi = rssi,
749 	off->frnd_counter = sys_cpu_to_be16(frnd->counter);
750 
751 	buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_OFFER, sdu);
752 	if (!buf) {
753 		BT_ERR("Unable to encode Friend Offer");
754 		goto done;
755 	}
756 
757 	frnd->counter++;
758 
759 	if (frnd->last) {
760 		net_buf_unref(frnd->last);
761 	}
762 
763 	frnd->last = buf;
764 	frnd->send_last = 1;
765 
766 done:
767 	os_mbuf_free_chain(sdu);
768 }
769 
770 #define RECV_WIN                  CONFIG_BT_MESH_FRIEND_RECV_WIN
771 #define RSSI_FACT(crit)           (((crit) >> 5) & (u8_t)BIT_MASK(2))
772 #define RECV_WIN_FACT(crit)       (((crit) >> 3) & (u8_t)BIT_MASK(2))
773 #define MIN_QUEUE_SIZE_LOG(crit)  ((crit) & (u8_t)BIT_MASK(3))
774 #define MIN_QUEUE_SIZE(crit)      ((u32_t)BIT(MIN_QUEUE_SIZE_LOG(crit)))
775 
offer_delay(struct bt_mesh_friend * frnd,s8_t rssi,u8_t crit)776 static s32_t offer_delay(struct bt_mesh_friend *frnd, s8_t rssi, u8_t crit)
777 {
778 	/* Scaling factors. The actual values are 1, 1.5, 2 & 2.5, but we
779 	 * want to avoid floating-point arithmetic.
780 	 */
781 	static const u8_t fact[] = { 10, 15, 20, 25 };
782 	s32_t delay;
783 
784 	BT_DBG("ReceiveWindowFactor %u ReceiveWindow %u RSSIFactor %u RSSI %d",
785 	       fact[RECV_WIN_FACT(crit)], RECV_WIN,
786 	       fact[RSSI_FACT(crit)], rssi);
787 
788 	/* Delay = ReceiveWindowFactor * ReceiveWindow - RSSIFactor * RSSI */
789 	delay = (s32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN;
790 	delay -= (s32_t)fact[RSSI_FACT(crit)] * rssi;
791 	delay /= 10;
792 
793 	BT_DBG("Local Delay calculated as %d ms", delay);
794 
795 	if (delay < 100) {
796 		return K_MSEC(100);
797 	}
798 
799 	return K_MSEC(delay);
800 }
801 
bt_mesh_friend_req(struct bt_mesh_net_rx * rx,struct os_mbuf * buf)802 int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
803 {
804 	struct bt_mesh_ctl_friend_req *msg = (void *)buf->om_data;
805 	struct bt_mesh_friend *frnd = NULL;
806 	u16_t old_friend;
807 	u32_t poll_to;
808 	int i;
809 
810 	if (buf->om_len < sizeof(*msg)) {
811 		BT_WARN("Too short Friend Request");
812 		return -EINVAL;
813 	}
814 
815 	if (msg->recv_delay <= 0x09) {
816 		BT_WARN("Prohibited ReceiveDelay (0x%02x)", msg->recv_delay);
817 		return -EINVAL;
818 	}
819 
820 	poll_to = (((u32_t)msg->poll_to[0] << 16) |
821 		   ((u32_t)msg->poll_to[1] << 8) |
822 		   ((u32_t)msg->poll_to[2]));
823 
824 	if (poll_to <= 0x000009 || poll_to >= 0x34bc00) {
825 		BT_WARN("Prohibited PollTimeout (0x%06x)", poll_to);
826 		return -EINVAL;
827 	}
828 
829 	if (msg->num_elem == 0x00) {
830 		BT_WARN("Prohibited NumElements value (0x00)");
831 		return -EINVAL;
832 	}
833 
834 	if (!MIN_QUEUE_SIZE_LOG(msg->criteria)) {
835 		BT_WARN("Prohibited Minimum Queue Size in Friend Request");
836 		return -EINVAL;
837 	}
838 
839 	if (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE < MIN_QUEUE_SIZE(msg->criteria)) {
840 		BT_WARN("We have a too small Friend Queue size (%u < %u)",
841 			CONFIG_BT_MESH_FRIEND_QUEUE_SIZE,
842 			MIN_QUEUE_SIZE(msg->criteria));
843 		return 0;
844 	}
845 
846 	old_friend = sys_be16_to_cpu(msg->prev_addr);
847 	if (BT_MESH_ADDR_IS_UNICAST(old_friend)) {
848 		frnd = bt_mesh_friend_find(rx->sub->net_idx, old_friend,
849 					   true, false);
850 	} else {
851 		frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr,
852 					   true, false);
853 	}
854 
855 	if (frnd) {
856 		BT_WARN("Existing LPN re-requesting Friendship");
857 		friend_clear(frnd);
858 		goto init_friend;
859 	}
860 
861 	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
862 		if (!bt_mesh.frnd[i].valid) {
863 			frnd = &bt_mesh.frnd[i];
864 			frnd->valid = 1;
865 			break;
866 		}
867 	}
868 
869 	if (!frnd) {
870 		BT_WARN("No free Friend contexts for new LPN");
871 		return -ENOMEM;
872 	}
873 
874 init_friend:
875 	frnd->lpn = rx->ctx.addr;
876 	frnd->net_idx = rx->sub->net_idx;
877 	frnd->recv_delay = msg->recv_delay;
878 	frnd->poll_to = poll_to * 100;
879 	frnd->lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
880 	frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr);
881 
882 	BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums",
883 	       frnd->lpn, rx->rssi, frnd->recv_delay, frnd->poll_to);
884 
885 	if (BT_MESH_ADDR_IS_UNICAST(old_friend) &&
886 	    !bt_mesh_elem_find(old_friend)) {
887 		clear_procedure_start(frnd);
888 	}
889 
890 	k_delayed_work_submit(&frnd->timer,
891 			      offer_delay(frnd, rx->rssi, msg->criteria));
892 
893 	friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter,
894 			   frnd->counter);
895 
896 	enqueue_offer(frnd, rx->rssi);
897 
898 	return 0;
899 }
900 
get_seg(struct bt_mesh_friend * frnd,u16_t src,u64_t * seq_auth)901 static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
902 					  u16_t src, u64_t *seq_auth)
903 {
904 	struct bt_mesh_friend_seg *unassigned = NULL;
905 	int i;
906 
907 	for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
908 		struct bt_mesh_friend_seg *seg = &frnd->seg[i];
909 		struct os_mbuf *buf = (void *)net_buf_slist_peek_head(&seg->queue);
910 
911 		if (buf && BT_MESH_ADV(buf)->addr == src &&
912 		    FRIEND_ADV(buf)->seq_auth == *seq_auth) {
913 			return seg;
914 		}
915 
916 		if (!unassigned && !buf) {
917 			unassigned = seg;
918 		}
919 	}
920 
921 	return unassigned;
922 }
923 
enqueue_friend_pdu(struct bt_mesh_friend * frnd,enum bt_mesh_friend_pdu_type type,struct os_mbuf * buf)924 static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
925 			       enum bt_mesh_friend_pdu_type type,
926 			       struct os_mbuf *buf)
927 {
928 	struct bt_mesh_friend_seg *seg;
929 	struct friend_adv *adv;
930 
931 	BT_DBG("type %u", type);
932 
933 	if (type == BT_MESH_FRIEND_PDU_SINGLE) {
934 		if (frnd->sec_update) {
935 			enqueue_update(frnd, 1);
936 		}
937 
938 		enqueue_buf(frnd, buf);
939 		return;
940 	}
941 
942 	adv = FRIEND_ADV(buf);
943 	seg = get_seg(frnd, BT_MESH_ADV(buf)->addr, &adv->seq_auth);
944 	if (!seg) {
945 		BT_ERR("No free friend segment RX contexts for 0x%04x",
946 		       BT_MESH_ADV(buf)->addr);
947 		net_buf_unref(buf);
948 		return;
949 	}
950 
951 	net_buf_slist_put(&seg->queue, buf);
952 
953 	if (type == BT_MESH_FRIEND_PDU_COMPLETE) {
954 		if (frnd->sec_update) {
955 			enqueue_update(frnd, 1);
956 		}
957 
958 		/* Only acks should have a valid SeqAuth in the Friend queue
959 		 * (otherwise we can't easily detect them there), so clear
960 		 * the SeqAuth information from the segments before merging.
961 		 */
962 		struct os_mbuf *m;
963 		struct os_mbuf_pkthdr *pkthdr;
964 		NET_BUF_SLIST_FOR_EACH_NODE(&seg->queue, pkthdr) {
965 			m = OS_MBUF_PKTHDR_TO_MBUF(pkthdr);
966 			FRIEND_ADV(m)->seq_auth = TRANS_SEQ_AUTH_NVAL;
967 			frnd->queue_size++;
968 		}
969 
970 		net_buf_slist_merge_slist(&frnd->queue, &seg->queue);
971 	}
972 }
973 
buf_send_start(u16_t duration,int err,void * user_data)974 static void buf_send_start(u16_t duration, int err, void *user_data)
975 {
976 	struct bt_mesh_friend *frnd = user_data;
977 
978 	BT_DBG("err %d", err);
979 
980 	frnd->pending_buf = 0;
981 
982 	/* Friend Offer doesn't follow the re-sending semantics */
983 	if (!frnd->established) {
984 		net_buf_unref(frnd->last);
985 		frnd->last = NULL;
986 	}
987 }
988 
buf_send_end(int err,void * user_data)989 static void buf_send_end(int err, void *user_data)
990 {
991 	struct bt_mesh_friend *frnd = user_data;
992 
993 	BT_DBG("err %d", err);
994 
995 	if (frnd->pending_req) {
996 		BT_WARN("Another request before previous completed sending");
997 		return;
998 	}
999 
1000 	if (frnd->established) {
1001 		k_delayed_work_submit(&frnd->timer, frnd->poll_to);
1002 		BT_DBG("Waiting %u ms for next poll", frnd->poll_to);
1003 	} else {
1004 		/* Friend offer timeout is 1 second */
1005 		k_delayed_work_submit(&frnd->timer, K_SECONDS(1));
1006 		BT_DBG("Waiting for first poll");
1007 	}
1008 }
1009 
friend_timeout(struct ble_npl_event * work)1010 static void friend_timeout(struct ble_npl_event *work)
1011 {
1012 	struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work);
1013 	static const struct bt_mesh_send_cb buf_sent_cb = {
1014 		.start = buf_send_start,
1015 		.end = buf_send_end,
1016 	};
1017 
1018 	__ASSERT_NO_MSG(frnd->pending_buf == 0);
1019 
1020 	BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn,
1021 	       frnd->send_last, frnd->last);
1022 
1023 	if (frnd->send_last && frnd->last) {
1024 		BT_DBG("Sending frnd->last %p", frnd->last);
1025 		frnd->send_last = 0;
1026 		goto send_last;
1027 	}
1028 
1029 	if (frnd->established && !frnd->pending_req) {
1030 		BT_WARN("Friendship lost with 0x%04x", frnd->lpn);
1031 		friend_clear(frnd);
1032 		return;
1033 	}
1034 
1035 	frnd->last = net_buf_slist_get(&frnd->queue);
1036 	if (!frnd->last) {
1037 		BT_WARN("Friendship not established with 0x%04x", frnd->lpn);
1038 		friend_clear(frnd);
1039 		return;
1040 	}
1041 
1042 	BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x",
1043 	       frnd->last, frnd->lpn);
1044 	frnd->queue_size--;
1045 
1046 send_last:
1047 	frnd->pending_req = 0;
1048 	frnd->pending_buf = 1;
1049 	bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd);
1050 }
1051 
bt_mesh_friend_init(void)1052 int bt_mesh_friend_init(void)
1053 {
1054 	int rc;
1055 	int i;
1056 
1057 	rc = os_mempool_init(&friend_buf_mempool, FRIEND_BUF_COUNT,
1058 			BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE,
1059 			friend_buf_mem, "friend_buf_pool");
1060 	assert(rc == 0);
1061 
1062 	rc = os_mbuf_pool_init(&friend_os_mbuf_pool, &friend_buf_mempool,
1063 			BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE,
1064 			FRIEND_BUF_COUNT);
1065 	assert(rc == 0);
1066 
1067 	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1068 		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1069 		int j;
1070 
1071 		frnd->net_idx = BT_MESH_KEY_UNUSED;
1072 
1073 		net_buf_slist_init(&frnd->queue);
1074 
1075 		k_delayed_work_init(&frnd->timer, friend_timeout);
1076 		k_delayed_work_add_arg(&frnd->timer, frnd);
1077 		k_delayed_work_init(&frnd->clear.timer, clear_timeout);
1078 		k_delayed_work_add_arg(&frnd->clear.timer, frnd);
1079 
1080 		for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) {
1081 			net_buf_slist_init(&frnd->seg[j].queue);
1082 		}
1083 	}
1084 
1085 	return 0;
1086 }
1087 
friend_purge_old_ack(struct bt_mesh_friend * frnd,u64_t * seq_auth,u16_t src)1088 static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
1089 				 u16_t src)
1090 {
1091 	struct os_mbuf *cur, *prev = NULL;
1092 
1093 	BT_DBG("SeqAuth %llx src 0x%04x", *seq_auth, src);
1094 
1095 	for (cur = net_buf_slist_peek_head(&frnd->queue);
1096 	     cur != NULL; prev = cur, cur = net_buf_slist_peek_next(cur)) {
1097 		struct os_mbuf *buf = (void *)cur;
1098 
1099 		if (BT_MESH_ADV(buf)->addr == src &&
1100 		    FRIEND_ADV(buf)->seq_auth == *seq_auth) {
1101 			BT_DBG("Removing old ack from Friend Queue");
1102 
1103 			net_buf_slist_remove(&frnd->queue, prev, cur);
1104 			frnd->queue_size--;
1105 
1106 			net_buf_unref(buf);
1107 			break;
1108 		}
1109 	}
1110 }
1111 
friend_lpn_enqueue_rx(struct bt_mesh_friend * frnd,struct bt_mesh_net_rx * rx,enum bt_mesh_friend_pdu_type type,u64_t * seq_auth,struct os_mbuf * sbuf)1112 static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
1113 				  struct bt_mesh_net_rx *rx,
1114 				  enum bt_mesh_friend_pdu_type type,
1115 				  u64_t *seq_auth, struct os_mbuf *sbuf)
1116 {
1117 	struct friend_pdu_info info;
1118 	struct os_mbuf *buf;
1119 
1120 	BT_DBG("LPN 0x%04x queue_size %u", frnd->lpn, frnd->queue_size);
1121 
1122 	if (type == BT_MESH_FRIEND_PDU_SINGLE && seq_auth) {
1123 		friend_purge_old_ack(frnd, seq_auth, rx->ctx.addr);
1124 	}
1125 
1126 	info.src = rx->ctx.addr;
1127 	info.dst = rx->ctx.recv_dst;
1128 
1129 	if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
1130 		info.ttl = rx->ctx.recv_ttl;
1131 	} else {
1132 		info.ttl = rx->ctx.recv_ttl - 1;
1133 	}
1134 
1135 	info.ctl = rx->ctl;
1136 
1137 	info.seq[0] = (rx->seq >> 16);
1138 	info.seq[1] = (rx->seq >> 8);
1139 	info.seq[2] = rx->seq;
1140 
1141 	info.iv_index = BT_MESH_NET_IVI_RX(rx);
1142 
1143 	buf = create_friend_pdu(frnd, &info, sbuf);
1144 	if (!buf) {
1145 		BT_ERR("Failed to encode Friend buffer");
1146 		return;
1147 	}
1148 
1149 	if (seq_auth) {
1150 		FRIEND_ADV(buf)->seq_auth = *seq_auth;
1151 	}
1152 
1153 	enqueue_friend_pdu(frnd, type, buf);
1154 
1155 	BT_DBG("Queued message for LPN 0x%04x, queue_size %u",
1156 	       frnd->lpn, frnd->queue_size);
1157 }
1158 
friend_lpn_enqueue_tx(struct bt_mesh_friend * frnd,struct bt_mesh_net_tx * tx,enum bt_mesh_friend_pdu_type type,u64_t * seq_auth,struct os_mbuf * sbuf)1159 static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
1160 				  struct bt_mesh_net_tx *tx,
1161 				  enum bt_mesh_friend_pdu_type type,
1162 				  u64_t *seq_auth, struct os_mbuf *sbuf)
1163 {
1164 	struct friend_pdu_info info;
1165 	struct os_mbuf *buf;
1166 	u32_t seq;
1167 
1168 	BT_DBG("LPN 0x%04x", frnd->lpn);
1169 
1170 	if (type == BT_MESH_FRIEND_PDU_SINGLE && seq_auth) {
1171 		friend_purge_old_ack(frnd, seq_auth, tx->src);
1172 	}
1173 
1174 	info.src = tx->src;
1175 	info.dst = tx->ctx->addr;
1176 
1177 	info.ttl = tx->ctx->send_ttl;
1178 	info.ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
1179 
1180 	seq = bt_mesh_next_seq();
1181 	info.seq[0] = seq >> 16;
1182 	info.seq[1] = seq >> 8;
1183 	info.seq[2] = seq;
1184 
1185 	info.iv_index = BT_MESH_NET_IVI_TX;
1186 
1187 	buf = create_friend_pdu(frnd, &info, sbuf);
1188 	if (!buf) {
1189 		BT_ERR("Failed to encode Friend buffer");
1190 		return;
1191 	}
1192 
1193 	if (seq_auth) {
1194 		FRIEND_ADV(buf)->seq_auth = *seq_auth;
1195 	}
1196 
1197 	enqueue_friend_pdu(frnd, type, buf);
1198 
1199 	BT_DBG("Queued message for LPN 0x%04x", frnd->lpn);
1200 }
1201 
friend_lpn_matches(struct bt_mesh_friend * frnd,u16_t net_idx,u16_t addr)1202 static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
1203 			       u16_t addr)
1204 {
1205 	int i;
1206 
1207 	if (!frnd->established) {
1208 		return false;
1209 	}
1210 
1211 	if (net_idx != frnd->net_idx) {
1212 		return false;
1213 	}
1214 
1215 	if (BT_MESH_ADDR_IS_UNICAST(addr)) {
1216 		if (addr == frnd->lpn) {
1217 			return true;
1218 		}
1219 
1220 		return false;
1221 	}
1222 
1223 	for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
1224 		if (frnd->sub_list[i] == addr) {
1225 			return true;
1226 		}
1227 	}
1228 
1229 	return false;
1230 }
1231 
bt_mesh_friend_match(u16_t net_idx,u16_t addr)1232 bool bt_mesh_friend_match(u16_t net_idx, u16_t addr)
1233 {
1234 	int i;
1235 
1236 	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1237 		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1238 
1239 		if (friend_lpn_matches(frnd, net_idx, addr)) {
1240 			BT_DBG("LPN 0x%04x matched address 0x%04x",
1241 			       frnd->lpn, addr);
1242 			return true;
1243 		}
1244 	}
1245 
1246 	BT_DBG("No matching LPN for address 0x%04x", addr);
1247 
1248 	return false;
1249 }
1250 
bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx * rx,enum bt_mesh_friend_pdu_type type,u64_t * seq_auth,struct os_mbuf * sbuf)1251 void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
1252 			       enum bt_mesh_friend_pdu_type type,
1253 			       u64_t *seq_auth, struct os_mbuf *sbuf)
1254 {
1255 	int i;
1256 
1257 	if (!rx->friend_match ||
1258 	    (rx->ctx.recv_ttl <= 1 && rx->net_if != BT_MESH_NET_IF_LOCAL) ||
1259 	    bt_mesh_friend_get() != BT_MESH_FRIEND_ENABLED) {
1260 		return;
1261 	}
1262 
1263 	BT_DBG("recv_ttl %u net_idx 0x%04x src 0x%04x dst 0x%04x",
1264 	       rx->ctx.recv_ttl, rx->sub->net_idx, rx->ctx.addr,
1265 	       rx->ctx.recv_dst);
1266 
1267 	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1268 		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1269 
1270 		if (friend_lpn_matches(frnd, rx->sub->net_idx,
1271 				       rx->ctx.recv_dst)) {
1272 			friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, sbuf);
1273 		}
1274 	}
1275 }
1276 
bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx * tx,enum bt_mesh_friend_pdu_type type,u64_t * seq_auth,struct os_mbuf * sbuf)1277 bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
1278 			       enum bt_mesh_friend_pdu_type type,
1279 			       u64_t *seq_auth, struct os_mbuf *sbuf)
1280 {
1281 	bool matched = false;
1282 	int i;
1283 
1284 	if (!bt_mesh_friend_match(tx->sub->net_idx, tx->ctx->addr) ||
1285 	    bt_mesh_friend_get() != BT_MESH_FRIEND_ENABLED) {
1286 		return matched;
1287 	}
1288 
1289 	BT_DBG("net_idx 0x%04x dst 0x%04x src 0x%04x", tx->sub->net_idx,
1290 	       tx->ctx->addr, tx->src);
1291 
1292 	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1293 		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1294 
1295 		if (friend_lpn_matches(frnd, tx->sub->net_idx, tx->ctx->addr)) {
1296 			friend_lpn_enqueue_tx(frnd, tx, type, seq_auth, sbuf);
1297 			matched = true;
1298 		}
1299 	}
1300 
1301 	return matched;
1302 }
1303 
bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet * sub,u16_t src,u16_t dst,u64_t * seq_auth)1304 void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
1305 				     u16_t dst, u64_t *seq_auth)
1306 {
1307 	int i;
1308 
1309 	BT_DBG("");
1310 
1311 	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
1312 		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
1313 		int j;
1314 
1315 		if (!friend_lpn_matches(frnd, sub->net_idx, dst)) {
1316 			continue;
1317 		}
1318 
1319 		for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) {
1320 			struct bt_mesh_friend_seg *seg = &frnd->seg[j];
1321 			struct os_mbuf *buf;
1322 
1323 			buf = (void *)net_buf_slist_peek_head(&seg->queue);
1324 			if (!buf) {
1325 				continue;
1326 			}
1327 
1328 			if (BT_MESH_ADV(buf)->addr != src) {
1329 				continue;
1330 			}
1331 
1332 			if (FRIEND_ADV(buf)->seq_auth != *seq_auth) {
1333 				continue;
1334 			}
1335 
1336 			BT_WARN("Clearing incomplete segments for 0x%04x", src);
1337 
1338 			while (!net_buf_slist_is_empty(&seg->queue)) {
1339 				net_buf_unref(net_buf_slist_get(&seg->queue));
1340 			}
1341 		}
1342 	}
1343 }
1344 
1345 #endif //MYNEWT_VAL(BLE_MESH_FRIEND)
1346