ble_mesh: fix segmented message RPL behavior
This commit is contained in:
parent
5f5f5cf305
commit
716db01a7f
1 changed files with 45 additions and 19 deletions
|
@ -555,7 +555,23 @@ int bt_mesh_trans_resend(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
|
||||||
return err;
|
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;
|
int i;
|
||||||
|
|
||||||
|
@ -564,17 +580,20 @@ static bool is_replay(struct bt_mesh_net_rx *rx)
|
||||||
return false;
|
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++) {
|
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
|
||||||
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
|
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
|
||||||
|
|
||||||
/* Empty slot */
|
/* Empty slot */
|
||||||
if (!rpl->src) {
|
if (!rpl->src) {
|
||||||
rpl->src = rx->ctx.addr;
|
if (match) {
|
||||||
rpl->seq = rx->seq;
|
*match = rpl;
|
||||||
rpl->old_iv = rx->old_iv;
|
} else {
|
||||||
|
update_rpl(rpl, rx);
|
||||||
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
|
|
||||||
bt_mesh_store_rpl(rpl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -597,11 +616,10 @@ static bool is_replay(struct bt_mesh_net_rx *rx)
|
||||||
if ((!rx->old_iv && rpl->old_iv) ||
|
if ((!rx->old_iv && rpl->old_iv) ||
|
||||||
(rpl->seq < rx->seq) || (rpl->seq > rx->seq + 10)) {
|
(rpl->seq < rx->seq) || (rpl->seq > rx->seq + 10)) {
|
||||||
#endif /* #if !CONFIG_BLE_MESH_PATCH_FOR_SLAB_APP_1_1_0 */
|
#endif /* #if !CONFIG_BLE_MESH_PATCH_FOR_SLAB_APP_1_1_0 */
|
||||||
rpl->seq = rx->seq;
|
if (match) {
|
||||||
rpl->old_iv = rx->old_iv;
|
*match = rpl;
|
||||||
|
} else {
|
||||||
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
|
update_rpl(rpl, rx);
|
||||||
bt_mesh_store_rpl(rpl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -950,7 +968,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx,
|
||||||
return -EINVAL;
|
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",
|
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
|
||||||
rx->ctx.addr, rx->ctx.recv_dst, rx->seq);
|
rx->ctx.addr, rx->ctx.recv_dst, rx->seq);
|
||||||
return -EINVAL;
|
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,
|
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)
|
enum bt_mesh_friend_pdu_type *pdu_type, u64_t *seq_auth)
|
||||||
{
|
{
|
||||||
|
struct bt_mesh_rpl *rpl = NULL;
|
||||||
struct seg_rx *rx;
|
struct seg_rx *rx;
|
||||||
u8_t *hdr = buf->data;
|
u8_t *hdr = buf->data;
|
||||||
u16_t seq_zero;
|
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;
|
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));
|
BT_DBG("ASZMIC %u AKF %u AID 0x%02x", ASZMIC(hdr), AKF(hdr), AID(hdr));
|
||||||
|
|
||||||
net_buf_simple_pull(buf, 1);
|
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,
|
send_ack(net_rx->sub, net_rx->ctx.recv_dst,
|
||||||
net_rx->ctx.addr, net_rx->ctx.send_ttl,
|
net_rx->ctx.addr, net_rx->ctx.send_ttl,
|
||||||
seq_auth, rx->block, rx->obo);
|
seq_auth, rx->block, rx->obo);
|
||||||
|
|
||||||
|
if (rpl) {
|
||||||
|
update_rpl(rpl, net_rx);
|
||||||
|
}
|
||||||
|
|
||||||
return -EALREADY;
|
return -EALREADY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1387,12 +1417,8 @@ found_rx:
|
||||||
|
|
||||||
BT_DBG("Complete SDU");
|
BT_DBG("Complete SDU");
|
||||||
|
|
||||||
if (net_rx->local_match && is_replay(net_rx)) {
|
if (rpl) {
|
||||||
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
|
update_rpl(rpl, net_rx);
|
||||||
net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq);
|
|
||||||
/* Clear the segment's bit */
|
|
||||||
rx->block &= ~BIT(seg_o);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*pdu_type = BLE_MESH_FRIEND_PDU_COMPLETE;
|
*pdu_type = BLE_MESH_FRIEND_PDU_COMPLETE;
|
||||||
|
|
Loading…
Reference in a new issue