ble_mesh: fix segmented message RPL behavior
This commit is contained in:
parent
27bc688ed8
commit
05e4b28a74
|
@ -555,7 +555,23 @@ int bt_mesh_trans_resend(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
|
|||
return err;
|
||||
}
|
||||
|
||||
static bool is_replay(struct bt_mesh_net_rx *rx)
|
||||
static void update_rpl(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx)
|
||||
{
|
||||
rpl->src = rx->ctx.addr;
|
||||
rpl->seq = rx->seq;
|
||||
rpl->old_iv = rx->old_iv;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
|
||||
bt_mesh_store_rpl(rpl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the Replay Protection List for a replay attempt. If non-NULL match
|
||||
* parameter is given the RPL slot is returned but it is not immediately
|
||||
* updated (needed for segmented messages), whereas if a NULL match is given
|
||||
* the RPL is immediately updated (used for unsegmented messages).
|
||||
*/
|
||||
static bool is_replay(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -564,17 +580,20 @@ static bool is_replay(struct bt_mesh_net_rx *rx)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* The RPL is used only for the local node */
|
||||
if (!rx->local_match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
|
||||
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
|
||||
|
||||
/* Empty slot */
|
||||
if (!rpl->src) {
|
||||
rpl->src = rx->ctx.addr;
|
||||
rpl->seq = rx->seq;
|
||||
rpl->old_iv = rx->old_iv;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
|
||||
bt_mesh_store_rpl(rpl);
|
||||
if (match) {
|
||||
*match = rpl;
|
||||
} else {
|
||||
update_rpl(rpl, rx);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -597,11 +616,10 @@ static bool is_replay(struct bt_mesh_net_rx *rx)
|
|||
if ((!rx->old_iv && rpl->old_iv) ||
|
||||
(rpl->seq < rx->seq) || (rpl->seq > rx->seq + 10)) {
|
||||
#endif /* #if !CONFIG_BLE_MESH_PATCH_FOR_SLAB_APP_1_1_0 */
|
||||
rpl->seq = rx->seq;
|
||||
rpl->old_iv = rx->old_iv;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
|
||||
bt_mesh_store_rpl(rpl);
|
||||
if (match) {
|
||||
*match = rpl;
|
||||
} else {
|
||||
update_rpl(rpl, rx);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -950,7 +968,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rx->local_match && is_replay(rx)) {
|
||||
if (is_replay(rx, NULL)) {
|
||||
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
|
||||
rx->ctx.addr, rx->ctx.recv_dst, rx->seq);
|
||||
return -EINVAL;
|
||||
|
@ -1229,6 +1247,7 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
|
|||
static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
|
||||
enum bt_mesh_friend_pdu_type *pdu_type, u64_t *seq_auth)
|
||||
{
|
||||
struct bt_mesh_rpl *rpl = NULL;
|
||||
struct seg_rx *rx;
|
||||
u8_t *hdr = buf->data;
|
||||
u16_t seq_zero;
|
||||
|
@ -1241,6 +1260,12 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_replay(net_rx, &rpl)) {
|
||||
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
|
||||
net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BT_DBG("ASZMIC %u AKF %u AID 0x%02x", ASZMIC(hdr), AKF(hdr), AID(hdr));
|
||||
|
||||
net_buf_simple_pull(buf, 1);
|
||||
|
@ -1300,6 +1325,11 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
|
|||
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);
|
||||
|
||||
if (rpl) {
|
||||
update_rpl(rpl, net_rx);
|
||||
}
|
||||
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
|
@ -1387,12 +1417,8 @@ found_rx:
|
|||
|
||||
BT_DBG("Complete SDU");
|
||||
|
||||
if (net_rx->local_match && is_replay(net_rx)) {
|
||||
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
|
||||
net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq);
|
||||
/* Clear the segment's bit */
|
||||
rx->block &= ~BIT(seg_o);
|
||||
return -EINVAL;
|
||||
if (rpl) {
|
||||
update_rpl(rpl, net_rx);
|
||||
}
|
||||
|
||||
*pdu_type = BLE_MESH_FRIEND_PDU_COMPLETE;
|
||||
|
|
Loading…
Reference in a new issue