Bluetooth: Mesh: Expose destination address in bt_mesh_msg_ctx

There are valid use cases where the model layer must know the true
destination address. So far only the fact that it was one of the
addresses that the model subscribes to (its element's unicast
included) has been knowable.

Solve the issue by moving the destination address from the internal
net_rx context to the public bt_mesh_msg_ctx struct.

Fixes #7453

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2018-05-10 16:44:10 +03:00 committed by Johan Hedberg
commit c1c5f3d9a3
6 changed files with 57 additions and 46 deletions

View file

@ -130,6 +130,9 @@ struct bt_mesh_msg_ctx {
/** Remote address. */ /** Remote address. */
u16_t addr; u16_t addr;
/** Destination address of a received message. Not used for sending. */
u16_t recv_dst;
/** Received TTL value. Not used for sending. */ /** Received TTL value. Not used for sending. */
u8_t recv_ttl:7; u8_t recv_ttl:7;

View file

@ -473,7 +473,7 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
int i; int i;
BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx, BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx,
rx->ctx.addr, rx->dst); rx->ctx.addr, rx->ctx.recv_dst);
BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len)); BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
if (get_opcode(buf, &opcode) < 0) { if (get_opcode(buf, &opcode) < 0) {
@ -486,16 +486,17 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
for (i = 0; i < dev_comp->elem_count; i++) { for (i = 0; i < dev_comp->elem_count; i++) {
struct bt_mesh_elem *elem = &dev_comp->elem[i]; struct bt_mesh_elem *elem = &dev_comp->elem[i];
if (BT_MESH_ADDR_IS_UNICAST(rx->dst)) { if (BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
if (elem->addr != rx->dst) { if (elem->addr != rx->ctx.recv_dst) {
continue; continue;
} }
} else if (BT_MESH_ADDR_IS_GROUP(rx->dst) || } else if (BT_MESH_ADDR_IS_GROUP(rx->ctx.recv_dst) ||
BT_MESH_ADDR_IS_VIRTUAL(rx->dst)) { BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) {
if (!bt_mesh_elem_find_group(elem, rx->dst)) { if (!bt_mesh_elem_find_group(elem, rx->ctx.recv_dst)) {
continue; continue;
} }
} else if (i != 0 || !bt_mesh_fixed_group_match(rx->dst)) { } else if (i != 0 ||
!bt_mesh_fixed_group_match(rx->ctx.recv_dst)) {
continue; continue;
} }

View file

@ -1102,7 +1102,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
} }
info.src = rx->ctx.addr; info.src = rx->ctx.addr;
info.dst = rx->dst; info.dst = rx->ctx.recv_dst;
if (rx->net_if == BT_MESH_NET_IF_LOCAL) { if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
info.ttl = rx->ctx.recv_ttl; info.ttl = rx->ctx.recv_ttl;
@ -1239,12 +1239,14 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
} }
BT_DBG("recv_ttl %u net_idx 0x%04x src 0x%04x dst 0x%04x", BT_DBG("recv_ttl %u net_idx 0x%04x src 0x%04x dst 0x%04x",
rx->ctx.recv_ttl, rx->sub->net_idx, rx->ctx.addr, rx->dst); rx->ctx.recv_ttl, rx->sub->net_idx, rx->ctx.addr,
rx->ctx.recv_dst);
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
if (friend_lpn_matches(frnd, rx->sub->net_idx, rx->dst)) { if (friend_lpn_matches(frnd, rx->sub->net_idx,
rx->ctx.recv_dst)) {
friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, sbuf); friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, sbuf);
} }
} }

View file

@ -1179,7 +1179,8 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
return; return;
} }
BT_DBG("TTL %u CTL %u dst 0x%04x", rx->ctx.recv_ttl, rx->ctl, rx->dst); BT_DBG("TTL %u CTL %u dst 0x%04x", rx->ctx.recv_ttl, rx->ctl,
rx->ctx.recv_dst);
/* The Relay Retransmit state is only applied to adv-adv relaying. /* The Relay Retransmit state is only applied to adv-adv relaying.
* Anything else (like GATT to adv, or locally originated packets) * Anything else (like GATT to adv, or locally originated packets)
@ -1240,8 +1241,8 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
(bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED || (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED ||
rx->net_if == BT_MESH_NET_IF_LOCAL)) { rx->net_if == BT_MESH_NET_IF_LOCAL)) {
if (bt_mesh_proxy_relay(&buf->b, rx->dst) && if (bt_mesh_proxy_relay(&buf->b, rx->ctx.recv_dst) &&
BT_MESH_ADDR_IS_UNICAST(rx->dst)) { BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
goto done; goto done;
} }
} }
@ -1290,17 +1291,17 @@ int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if,
rx->ctl = CTL(buf->data); rx->ctl = CTL(buf->data);
rx->seq = SEQ(buf->data); rx->seq = SEQ(buf->data);
rx->dst = DST(buf->data); rx->ctx.recv_dst = DST(buf->data);
BT_DBG("Decryption successful. Payload len %u", buf->len); BT_DBG("Decryption successful. Payload len %u", buf->len);
if (net_if != BT_MESH_NET_IF_PROXY_CFG && if (net_if != BT_MESH_NET_IF_PROXY_CFG &&
rx->dst == BT_MESH_ADDR_UNASSIGNED) { rx->ctx.recv_dst == BT_MESH_ADDR_UNASSIGNED) {
BT_ERR("Destination address is unassigned; dropping packet"); BT_ERR("Destination address is unassigned; dropping packet");
return -EBADMSG; return -EBADMSG;
} }
if (BT_MESH_ADDR_IS_RFU(rx->dst)) { if (BT_MESH_ADDR_IS_RFU(rx->ctx.recv_dst)) {
BT_ERR("Destination address is RFU; dropping packet"); BT_ERR("Destination address is RFU; dropping packet");
return -EBADMSG; return -EBADMSG;
} }
@ -1310,7 +1311,7 @@ int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if,
return -EBADMSG; return -EBADMSG;
} }
BT_DBG("src 0x%04x dst 0x%04x ttl %u", rx->ctx.addr, rx->dst, BT_DBG("src 0x%04x dst 0x%04x ttl %u", rx->ctx.addr, rx->ctx.recv_dst,
rx->ctx.recv_ttl); rx->ctx.recv_ttl);
BT_DBG("PDU: %s", bt_hex(buf->data, buf->len)); BT_DBG("PDU: %s", bt_hex(buf->data, buf->len));
@ -1342,15 +1343,15 @@ void bt_mesh_net_recv(struct net_buf_simple *data, s8_t rssi,
bt_mesh_proxy_addr_add(data, rx.ctx.addr); bt_mesh_proxy_addr_add(data, rx.ctx.addr);
} }
rx.local_match = (bt_mesh_fixed_group_match(rx.dst) || rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) ||
bt_mesh_elem_find(rx.dst)); bt_mesh_elem_find(rx.ctx.recv_dst));
bt_mesh_trans_recv(&buf, &rx); bt_mesh_trans_recv(&buf, &rx);
/* Relay if this was a group/virtual address, or if the destination /* Relay if this was a group/virtual address, or if the destination
* was neither a local element nor an LPN we're Friends for. * was neither a local element nor an LPN we're Friends for.
*/ */
if (!BT_MESH_ADDR_IS_UNICAST(rx.dst) || if (!BT_MESH_ADDR_IS_UNICAST(rx.ctx.recv_dst) ||
(!rx.local_match && !rx.friend_match)) { (!rx.local_match && !rx.friend_match)) {
net_buf_simple_restore(&buf, &state); net_buf_simple_restore(&buf, &state);
bt_mesh_net_relay(&buf, &rx); bt_mesh_net_relay(&buf, &rx);

View file

@ -246,7 +246,6 @@ struct bt_mesh_net_rx {
struct bt_mesh_subnet *sub; struct bt_mesh_subnet *sub;
struct bt_mesh_msg_ctx ctx; struct bt_mesh_msg_ctx ctx;
u32_t seq; /* Sequence Number */ u32_t seq; /* Sequence Number */
u16_t dst; /* Destination address */
u8_t old_iv:1, /* iv_index - 1 was used */ u8_t old_iv:1, /* iv_index - 1 was used */
new_key:1, /* Data was encrypted with updated key */ new_key:1, /* Data was encrypted with updated key */
friend_cred:1, /* Data was encrypted with friend cred */ friend_cred:1, /* Data was encrypted with friend cred */

View file

@ -590,12 +590,13 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
} }
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !rx->local_match) { if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !rx->local_match) {
BT_DBG("Ignoring PDU for LPN 0x%04x of this Friend", rx->dst); BT_DBG("Ignoring PDU for LPN 0x%04x of this Friend",
rx->ctx.recv_dst);
return 0; return 0;
} }
if (BT_MESH_ADDR_IS_VIRTUAL(rx->dst)) { if (BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) {
ad = bt_mesh_label_uuid_get(rx->dst); ad = bt_mesh_label_uuid_get(rx->ctx.recv_dst);
} else { } else {
ad = NULL; ad = NULL;
} }
@ -605,8 +606,9 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
if (!AKF(&hdr)) { if (!AKF(&hdr)) {
err = bt_mesh_app_decrypt(bt_mesh.dev_key, true, aszmic, buf, err = bt_mesh_app_decrypt(bt_mesh.dev_key, true, aszmic, buf,
&sdu, ad, rx->ctx.addr, rx->dst, &sdu, ad, rx->ctx.addr,
seq, BT_MESH_NET_IVI_RX(rx)); rx->ctx.recv_dst, seq,
BT_MESH_NET_IVI_RX(rx));
if (err) { if (err) {
BT_ERR("Unable to decrypt with DevKey"); BT_ERR("Unable to decrypt with DevKey");
return -EINVAL; return -EINVAL;
@ -639,8 +641,9 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
net_buf_simple_reset(&sdu); net_buf_simple_reset(&sdu);
err = bt_mesh_app_decrypt(keys->val, false, aszmic, buf, err = bt_mesh_app_decrypt(keys->val, false, aszmic, buf,
&sdu, ad, rx->ctx.addr, rx->dst, &sdu, ad, rx->ctx.addr,
seq, BT_MESH_NET_IVI_RX(rx)); rx->ctx.recv_dst, seq,
BT_MESH_NET_IVI_RX(rx));
if (err) { if (err) {
BT_WARN("Unable to decrypt with AppKey %u", i); BT_WARN("Unable to decrypt with AppKey %u", i);
continue; continue;
@ -707,7 +710,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
seq_zero = (seq_zero >> 2) & 0x1fff; seq_zero = (seq_zero >> 2) & 0x1fff;
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->friend_match) { if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->friend_match) {
BT_DBG("Ack for LPN 0x%04x of this Friend", rx->dst); BT_DBG("Ack for LPN 0x%04x of this Friend", rx->ctx.recv_dst);
/* Best effort - we don't have enough info for true SeqAuth */ /* Best effort - we don't have enough info for true SeqAuth */
*seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_RX(rx), seq_zero); *seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_RX(rx), seq_zero);
return 0; return 0;
@ -770,7 +773,7 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx,
return -EINVAL; return -EINVAL;
} }
if (rx->dst != hb_sub_dst) { if (rx->ctx.recv_dst != hb_sub_dst) {
BT_WARN("Ignoring heartbeat to non-subscribed destination"); BT_WARN("Ignoring heartbeat to non-subscribed destination");
return 0; return 0;
} }
@ -784,7 +787,7 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx,
rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops, rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
(hops == 1) ? "" : "s", feat); (hops == 1) ? "" : "s", feat);
bt_mesh_heartbeat(rx->ctx.addr, rx->dst, hops, feat); bt_mesh_heartbeat(rx->ctx.addr, rx->ctx.recv_dst, hops, feat);
return 0; return 0;
} }
@ -868,7 +871,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx,
if (rx->local_match && is_replay(rx)) { if (rx->local_match && is_replay(rx)) {
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
rx->ctx.addr, rx->dst, rx->seq); rx->ctx.addr, rx->ctx.recv_dst, rx->seq);
return -EINVAL; return -EINVAL;
} }
@ -1062,7 +1065,8 @@ static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) { for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
struct seg_rx *rx = &seg_rx[i]; struct seg_rx *rx = &seg_rx[i];
if (rx->src != net_rx->ctx.addr || rx->dst != net_rx->dst) { if (rx->src != net_rx->ctx.addr ||
rx->dst != net_rx->ctx.recv_dst) {
continue; continue;
} }
@ -1098,7 +1102,7 @@ static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx,
return false; return false;
} }
if (rx->src != net_rx->ctx.addr || rx->dst != net_rx->dst) { if (rx->src != net_rx->ctx.addr || rx->dst != net_rx->ctx.recv_dst) {
BT_ERR("Invalid source or destination for segment"); BT_ERR("Invalid source or destination for segment");
return false; return false;
} }
@ -1133,7 +1137,7 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
rx->hdr = *hdr; rx->hdr = *hdr;
rx->ttl = net_rx->ctx.send_ttl; rx->ttl = net_rx->ctx.send_ttl;
rx->src = net_rx->ctx.addr; rx->src = net_rx->ctx.addr;
rx->dst = net_rx->dst; rx->dst = net_rx->ctx.recv_dst;
rx->block = 0; rx->block = 0;
BT_DBG("New RX context. Block Complete 0x%08x", BT_DBG("New RX context. Block Complete 0x%08x",
@ -1201,9 +1205,9 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
if (rx->block == BLOCK_COMPLETE(rx->seg_n)) { if (rx->block == BLOCK_COMPLETE(rx->seg_n)) {
BT_WARN("Got segment for already complete SDU"); BT_WARN("Got segment for already complete SDU");
send_ack(net_rx->sub, net_rx->dst, net_rx->ctx.addr, send_ack(net_rx->sub, net_rx->ctx.recv_dst,
net_rx->ctx.send_ttl, seq_auth, rx->block, net_rx->ctx.addr, net_rx->ctx.send_ttl,
rx->obo); seq_auth, rx->block, rx->obo);
return -EALREADY; return -EALREADY;
} }
@ -1218,7 +1222,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
/* Bail out early if we're not ready to receive such a large SDU */ /* Bail out early if we're not ready to receive such a large SDU */
if (!sdu_len_is_ok(net_rx->ctl, seg_n)) { if (!sdu_len_is_ok(net_rx->ctl, seg_n)) {
BT_ERR("Too big incoming SDU length"); BT_ERR("Too big incoming SDU length");
send_ack(net_rx->sub, net_rx->dst, net_rx->ctx.addr, send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
net_rx->ctx.send_ttl, seq_auth, 0, net_rx->ctx.send_ttl, seq_auth, 0,
net_rx->friend_match); net_rx->friend_match);
return -EMSGSIZE; return -EMSGSIZE;
@ -1255,8 +1259,9 @@ found_rx:
if (rx->buf.len > CONFIG_BT_MESH_RX_SDU_MAX) { if (rx->buf.len > CONFIG_BT_MESH_RX_SDU_MAX) {
BT_ERR("Too large SDU len"); BT_ERR("Too large SDU len");
send_ack(net_rx->sub, net_rx->dst, net_rx->ctx.addr, send_ack(net_rx->sub, net_rx->ctx.recv_dst,
net_rx->ctx.send_ttl, seq_auth, 0, rx->obo); net_rx->ctx.addr, net_rx->ctx.send_ttl,
seq_auth, 0, rx->obo);
seg_rx_reset(rx, true); seg_rx_reset(rx, true);
return -EMSGSIZE; return -EMSGSIZE;
} }
@ -1292,7 +1297,7 @@ found_rx:
if (net_rx->local_match && is_replay(net_rx)) { if (net_rx->local_match && is_replay(net_rx)) {
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
net_rx->ctx.addr, net_rx->dst, net_rx->seq); net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq);
/* Clear the segment's bit */ /* Clear the segment's bit */
rx->block &= ~BIT(seg_o); rx->block &= ~BIT(seg_o);
return -EINVAL; return -EINVAL;
@ -1301,7 +1306,7 @@ found_rx:
*pdu_type = BT_MESH_FRIEND_PDU_COMPLETE; *pdu_type = BT_MESH_FRIEND_PDU_COMPLETE;
k_delayed_work_cancel(&rx->ack); k_delayed_work_cancel(&rx->ack);
send_ack(net_rx->sub, net_rx->dst, net_rx->ctx.addr, send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo); net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo);
if (net_rx->ctl) { if (net_rx->ctl) {
@ -1325,13 +1330,13 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
rx->friend_match = bt_mesh_friend_match(rx->sub->net_idx, rx->friend_match = bt_mesh_friend_match(rx->sub->net_idx,
rx->dst); rx->ctx.recv_dst);
} else { } else {
rx->friend_match = false; rx->friend_match = false;
} }
BT_DBG("src 0x%04x dst 0x%04x seq 0x%08x friend_match %u", BT_DBG("src 0x%04x dst 0x%04x seq 0x%08x friend_match %u",
rx->ctx.addr, rx->dst, rx->seq, rx->friend_match); rx->ctx.addr, rx->ctx.recv_dst, rx->seq, rx->friend_match);
/* Remove network headers */ /* Remove network headers */
net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN); net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN);
@ -1340,7 +1345,7 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
if (IS_ENABLED(CONFIG_BT_TESTING)) { if (IS_ENABLED(CONFIG_BT_TESTING)) {
bt_test_mesh_net_recv(rx->ctx.recv_ttl, rx->ctl, rx->ctx.addr, bt_test_mesh_net_recv(rx->ctx.recv_ttl, rx->ctl, rx->ctx.addr,
rx->dst, buf->data, buf->len); rx->ctx.recv_dst, buf->data, buf->len);
} }
/* If LPN mode is enabled messages are only accepted when we've /* If LPN mode is enabled messages are only accepted when we've