esp-idf/components/bt/esp_ble_mesh/core/rpl.c

142 wiersze
3.5 KiB
C

/* Bluetooth Mesh */
/*
* SPDX-FileCopyrightText: 2017 Intel Corporation
* SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "mesh/config.h"
#include "mesh/trace.h"
#include "mesh.h"
#include "settings.h"
void bt_mesh_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 rpl_check_and_store(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
{
for (size_t i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
/* Empty slot */
if (rpl->src == BLE_MESH_ADDR_UNASSIGNED) {
if (match) {
*match = rpl;
} else {
bt_mesh_update_rpl(rpl, rx);
}
return false;
}
/* Existing slot for given address */
if (rpl->src == rx->ctx.addr) {
if (rx->old_iv && !rpl->old_iv) {
return true;
}
if ((!rx->old_iv && rpl->old_iv) ||
rpl->seq < rx->seq) {
if (match) {
*match = rpl;
} else {
bt_mesh_update_rpl(rpl, rx);
}
return false;
}
return true;
}
}
BT_ERR("RPL is full!");
return true;
}
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
{
/* Don't bother checking messages from ourselves */
if (rx->net_if == BLE_MESH_NET_IF_LOCAL) {
return false;
}
/* The RPL is used only for the local node */
if (!rx->local_match) {
return false;
}
return rpl_check_and_store(rx, match);
}
bool bt_mesh_bridge_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
{
return rpl_check_and_store(rx, match);
}
void bt_mesh_rpl_update(void)
{
/* Discard "old old" IV Index entries from RPL and flag
* any other ones (which are valid) as old.
*/
for (size_t i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
if (rpl->src) {
if (rpl->old_iv) {
(void)memset(rpl, 0, sizeof(*rpl));
} else {
rpl->old_iv = true;
}
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) {
bt_mesh_store_rpl(rpl);
}
}
}
}
void bt_mesh_rpl_reset_single(uint16_t src, bool erase)
{
if (!BLE_MESH_ADDR_IS_UNICAST(src)) {
return;
}
for (size_t i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
if (src == bt_mesh.rpl[i].src) {
memset(&bt_mesh.rpl[i], 0, sizeof(struct bt_mesh_rpl));
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS) && erase) {
bt_mesh_clear_rpl_single(src);
}
}
}
}
void bt_mesh_rpl_reset(bool erase)
{
(void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS) && erase) {
bt_mesh_clear_rpl();
}
}