diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 561f5b287..18cb3c1f0 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -111,6 +111,15 @@ static struct os_mbuf *friend_buf_alloc(u16_t src) return buf; } +static bool is_lpn_unicast(struct bt_mesh_friend *frnd, u16_t addr) +{ + if (frnd->lpn == BT_MESH_ADDR_UNASSIGNED) { + return false; + } + + return (addr >= frnd->lpn && addr < (frnd->lpn + frnd->num_elem)); +} + struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr, bool valid, bool established) { @@ -133,7 +142,7 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr, continue; } - if (frnd->lpn == lpn_addr) { + if (is_lpn_unicast(frnd, lpn_addr)) { return frnd; } } @@ -831,6 +840,11 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) return -EINVAL; } + if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr + msg->num_elem - 1)) { + BT_WARN("LPN elements stretch outside of unicast range"); + return -EINVAL; + } + if (!MIN_QUEUE_SIZE_LOG(msg->criteria)) { BT_WARN("Prohibited Minimum Queue Size in Friend Request"); return -EINVAL; @@ -873,6 +887,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) init_friend: frnd->lpn = rx->ctx.addr; + frnd->num_elem = msg->num_elem; frnd->net_idx = rx->sub->net_idx; frnd->recv_delay = msg->recv_delay; frnd->poll_to = poll_to * 100; @@ -1216,11 +1231,7 @@ static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx, } if (BT_MESH_ADDR_IS_UNICAST(addr)) { - if (addr == frnd->lpn) { - return true; - } - - return false; + return is_lpn_unicast(frnd, addr); } for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { diff --git a/nimble/host/mesh/src/net.h b/nimble/host/mesh/src/net.h index 8b1557ab6..fc309594c 100644 --- a/nimble/host/mesh/src/net.h +++ b/nimble/host/mesh/src/net.h @@ -103,6 +103,7 @@ struct bt_mesh_friend { valid:1, established:1; s32_t poll_to; + u8_t num_elem; u16_t lpn_counter; u16_t counter;