diff options
Diffstat (limited to 'src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c')
-rw-r--r-- | src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c new file mode 100644 index 00000000..93c2e1a8 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c @@ -0,0 +1,162 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2020 Lingao Meng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define MESH_LOG_MODULE BLE_MESH_RPL_LOG + +#include "log/log.h" + +#include "mesh_priv.h" +#include "adv.h" +#include "net.h" +#include "rpl.h" +#include "settings.h" + +static struct bt_mesh_rpl replay_list[MYNEWT_VAL(BLE_MESH_CRPL)]; + +void bt_mesh_rpl_update(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_BT_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). + */ +bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, + struct bt_mesh_rpl **match) +{ + int i; + + /* Don't bother checking messages from ourselves */ + if (rx->net_if == BT_MESH_NET_IF_LOCAL) { + return false; + } + + /* The RPL is used only for the local node */ + if (!rx->local_match) { + return false; + } + + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + struct bt_mesh_rpl *rpl = &replay_list[i]; + + /* Empty slot */ + if (!rpl->src) { + if (match) { + *match = rpl; + } else { + bt_mesh_rpl_update(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_rpl_update(rpl, rx); + } + + return false; + } else { + return true; + } + } + } + + BT_ERR("RPL is full!"); + return true; +} + +void bt_mesh_rpl_clear(void) +{ + BT_DBG(""); + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_clear_rpl(); + } else { + (void)memset(replay_list, 0, sizeof(replay_list)); + } +} + +struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + if (replay_list[i].src == src) { + return &replay_list[i]; + } + } + + return NULL; +} + +struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + if (!replay_list[i].src) { + replay_list[i].src = src; + return &replay_list[i]; + } + } + + return NULL; +} + +void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + func(&replay_list[i], user_data); + } +} + +void bt_mesh_rpl_reset(void) +{ + int i; + + /* Discard "old old" IV Index entries from RPL and flag + * any other ones (which are valid) as old. + */ + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + struct bt_mesh_rpl *rpl = &replay_list[i]; + + if (rpl->src) { + if (rpl->old_iv) { + (void)memset(rpl, 0, sizeof(*rpl)); + } else { + rpl->old_iv = true; + } + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_rpl(rpl); + } + } + } +}
\ No newline at end of file |