Bluetooth: Mesh: Move Replay Protect to seperate module

Move RPL to seperate module, and remove it in `bt_mesh`
structure.

Signed-off-by: Lingao Meng <mengabc1086@gmail.com>
This commit is contained in:
Lingao Meng 2020-09-09 16:59:43 +08:00 committed by Johan Hedberg
commit f16c653be9
16 changed files with 249 additions and 186 deletions

View file

@ -12,6 +12,7 @@
#if defined(CONFIG_BT_MESH)
#include "mesh/net.h"
#include "mesh/lpn.h"
#include "mesh/rpl.h"
#include "mesh/transport.h"
#endif /* CONFIG_BT_MESH */

View file

@ -9,6 +9,7 @@ zephyr_library_sources_ifdef(CONFIG_BT_MESH
beacon.c
net.c
transport.c
rpl.c
crypto.c
access.c
cfg_srv.c

View file

@ -589,6 +589,12 @@ config BT_MESH_DEBUG_NET
Use this option to enable Network layer debug logs for the
Bluetooth Mesh functionality.
config BT_MESH_DEBUG_RPL
bool "Replay protection list debug"
help
Use this option to enable Replay protection list debug logs
for the Bluetooth Mesh functionality.
config BT_MESH_DEBUG_TRANS
bool "Transport layer debug"
help

View file

@ -15,6 +15,7 @@
#include "mesh.h"
#include "net.h"
#include "rpl.h"
#include "settings.h"
struct bt_mesh_cdb bt_mesh_cdb = {

View file

@ -27,6 +27,7 @@
#include "mesh.h"
#include "adv.h"
#include "net.h"
#include "rpl.h"
#include "lpn.h"
#include "transport.h"
#include "crypto.h"

View file

@ -24,6 +24,7 @@
#include "adv.h"
#include "prov.h"
#include "net.h"
#include "rpl.h"
#include "beacon.h"
#include "lpn.h"
#include "friend.h"

View file

@ -27,6 +27,7 @@
#include "adv.h"
#include "mesh.h"
#include "net.h"
#include "rpl.h"
#include "lpn.h"
#include "friend.h"
#include "proxy.h"
@ -559,30 +560,6 @@ bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, uint8_t new_kr, bool new_key)
return false;
}
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(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_BT_SETTINGS)) {
bt_mesh_store_rpl(rpl);
}
}
}
}
#if defined(CONFIG_BT_MESH_IV_UPDATE_TEST)
void bt_mesh_iv_update_test(bool enable)
{
@ -658,7 +635,7 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update)
if (iv_index > bt_mesh.iv_index + 1) {
BT_WARN("Performing IV Index Recovery");
(void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
bt_mesh_rpl_clear();
bt_mesh.iv_index = iv_index;
bt_mesh.seq = 0U;
goto do_update;

View file

@ -74,15 +74,6 @@ struct bt_mesh_subnet {
} keys[2];
};
struct bt_mesh_rpl {
uint16_t src;
bool old_iv;
#if defined(CONFIG_BT_SETTINGS)
bool store;
#endif
uint32_t seq;
};
#if defined(CONFIG_BT_MESH_FRIEND)
#define FRIEND_SEG_RX CONFIG_BT_MESH_FRIEND_SEG_RX
#define FRIEND_SUB_LIST_SIZE CONFIG_BT_MESH_FRIEND_SUB_LIST_SIZE
@ -257,8 +248,6 @@ struct bt_mesh_net {
struct bt_mesh_app_key app_keys[CONFIG_BT_MESH_APP_KEY_COUNT];
struct bt_mesh_subnet sub[CONFIG_BT_MESH_SUBNET_COUNT];
struct bt_mesh_rpl rpl[CONFIG_BT_MESH_CRPL];
};
/* Network interface */
@ -318,8 +307,6 @@ void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub);
int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub);
void bt_mesh_rpl_reset(void);
bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update);
void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub);

View file

@ -29,6 +29,7 @@
#include "adv.h"
#include "mesh.h"
#include "net.h"
#include "rpl.h"
#include "beacon.h"
#include "access.h"
#include "foundation.h"

View file

@ -22,6 +22,7 @@
#include "mesh.h"
#include "adv.h"
#include "net.h"
#include "rpl.h"
#include "transport.h"
#include "prov.h"
#include "beacon.h"

175
subsys/bluetooth/mesh/rpl.c Normal file
View file

@ -0,0 +1,175 @@
/* Bluetooth Mesh */
/*
* Copyright (c) 2017 Intel Corporation
* Copyright (c) 2020 Lingao Meng
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <sys/atomic.h>
#include <sys/util.h>
#include <sys/byteorder.h>
#include <net/buf.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/mesh.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_RPL)
#define LOG_MODULE_NAME bt_mesh_rpl
#include "common/log.h"
#include "mesh.h"
#include "adv.h"
#include "net.h"
#include "rpl.h"
#include "settings.h"
static struct bt_mesh_rpl replay_list[CONFIG_BT_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);
}
}
}
}

View file

@ -0,0 +1,30 @@
/* Bluetooth Mesh */
/*
* Copyright (c) 2017 Intel Corporation
* Copyright (c) 2020 Lingao Meng
*
* SPDX-License-Identifier: Apache-2.0
*/
struct bt_mesh_rpl {
uint16_t src;
bool old_iv;
#if defined(CONFIG_BT_SETTINGS)
bool store;
#endif
uint32_t seq;
};
typedef void (*bt_mesh_rpl_func_t)(struct bt_mesh_rpl *rpl,
void *user_data);
void bt_mesh_rpl_reset(void);
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
struct bt_mesh_rpl **match);
void bt_mesh_rpl_clear(void);
struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src);
struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src);
void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data);
void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
struct bt_mesh_net_rx *rx);

View file

@ -27,6 +27,7 @@
#include "mesh.h"
#include "net.h"
#include "crypto.h"
#include "rpl.h"
#include "transport.h"
#include "access.h"
#include "foundation.h"
@ -280,33 +281,6 @@ static int seq_set(const char *name, size_t len_rd, settings_read_cb read_cb,
return 0;
}
static struct bt_mesh_rpl *rpl_find(uint16_t src)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
if (bt_mesh.rpl[i].src == src) {
return &bt_mesh.rpl[i];
}
}
return NULL;
}
static struct bt_mesh_rpl *rpl_alloc(uint16_t src)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
if (!bt_mesh.rpl[i].src) {
bt_mesh.rpl[i].src = src;
return &bt_mesh.rpl[i];
}
}
return NULL;
}
static int rpl_set(const char *name, size_t len_rd,
settings_read_cb read_cb, void *cb_arg)
{
@ -321,7 +295,7 @@ static int rpl_set(const char *name, size_t len_rd,
}
src = strtol(name, NULL, 16);
entry = rpl_find(src);
entry = bt_mesh_rpl_find(src);
if (len_rd == 0) {
BT_DBG("val (null)");
@ -335,7 +309,7 @@ static int rpl_set(const char *name, size_t len_rd,
}
if (!entry) {
entry = rpl_alloc(src);
entry = bt_mesh_rpl_alloc(src);
if (!entry) {
BT_ERR("Unable to allocate RPL entry for 0x%04x", src);
return -ENOMEM;
@ -1349,45 +1323,33 @@ static void store_rpl(struct bt_mesh_rpl *entry)
}
}
static void clear_rpl(void)
static void clear_rpl(struct bt_mesh_rpl *rpl, void *user_data)
{
int i, err;
int err;
char path[18];
BT_DBG("");
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
char path[18];
if (!rpl->src) {
continue;
}
snprintk(path, sizeof(path), "bt/mesh/RPL/%x", rpl->src);
err = settings_delete(path);
if (err) {
BT_ERR("Failed to clear RPL");
} else {
BT_DBG("Cleared RPL");
}
(void)memset(rpl, 0, sizeof(*rpl));
if (!rpl->src) {
return;
}
snprintk(path, sizeof(path), "bt/mesh/RPL/%x", rpl->src);
err = settings_delete(path);
if (err) {
BT_ERR("Failed to clear RPL");
} else {
BT_DBG("Cleared RPL");
}
(void)memset(rpl, 0, sizeof(*rpl));
}
static void store_pending_rpl(void)
static void store_pending_rpl(struct bt_mesh_rpl *rpl, void *user_data)
{
int i;
BT_DBG("");
for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
if (rpl->store) {
rpl->store = false;
store_rpl(rpl);
}
if (rpl->store) {
rpl->store = false;
store_rpl(rpl);
}
}
@ -1996,9 +1958,9 @@ static void store_pending(struct k_work *work)
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_RPL_PENDING)) {
if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
store_pending_rpl();
bt_mesh_rpl_foreach(store_pending_rpl, NULL);
} else {
clear_rpl();
bt_mesh_rpl_foreach(clear_rpl, NULL);
}
}

View file

@ -24,6 +24,7 @@
/* Private includes for raw Network & Transport layer access */
#include "mesh.h"
#include "net.h"
#include "rpl.h"
#include "transport.h"
#include "foundation.h"
#include "settings.h"

View file

@ -29,6 +29,7 @@
#include "mesh.h"
#include "net.h"
#include "lpn.h"
#include "rpl.h"
#include "friend.h"
#include "access.h"
#include "foundation.h"
@ -676,75 +677,6 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
return err;
}
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_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(bt_mesh.rpl); i++) {
struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
/* Empty slot */
if (!rpl->src) {
if (match) {
*match = rpl;
} else {
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 {
update_rpl(rpl, rx);
}
return false;
} else {
return true;
}
}
}
BT_ERR("RPL is full!");
return true;
}
static void seg_rx_assemble(struct seg_rx *rx, struct net_buf_simple *buf,
uint8_t aszmic)
{
@ -1587,7 +1519,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
seq_auth, rx->block, rx->obo);
if (rpl) {
update_rpl(rpl, net_rx);
bt_mesh_rpl_update(rpl, net_rx);
}
return -EALREADY;
@ -1700,7 +1632,7 @@ found_rx:
BT_DBG("Complete SDU");
if (rpl) {
update_rpl(rpl, net_rx);
bt_mesh_rpl_update(rpl, net_rx);
}
*pdu_type = BT_MESH_FRIEND_PDU_COMPLETE;
@ -1822,11 +1754,7 @@ void bt_mesh_rx_reset(void)
seg_rx_reset(&seg_rx[i], true);
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_clear_rpl();
} else {
(void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
}
bt_mesh_rpl_clear();
}
void bt_mesh_tx_reset(void)
@ -1853,12 +1781,6 @@ void bt_mesh_trans_init(void)
}
}
void bt_mesh_rpl_clear(void)
{
BT_DBG("");
(void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
}
int bt_mesh_heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data)
{
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();

View file

@ -99,10 +99,6 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx);
void bt_mesh_trans_init(void);
void bt_mesh_rpl_clear(void);
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match);
int bt_mesh_heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data);
int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx,