Commit 81dbc697 authored by Pavel Vasilyev's avatar Pavel Vasilyev Committed by Carles Cufi
Browse files

bluetooth: mesh: rpl: fix rpl for subnet bridge

The initial implementation of RPL check for Subnet Bridge wasn't fully
correct. It decides whether to relay or not a PDU based on RPL of only
received messages. However, the spec section 3.9.8 says:

```
In addition, a Subnet Bridge node shall implement replay protection for
all Access and Transport Control messages that are sent to bridged
subnets.

A Subnet Bridge node shall maintain the most recent IVISeq value for
each source address authorized to send messages to bridged subnets.
Messages received by the Subnet Bridge node with the IVISeq value less
than or equal to the last stored value from that source address shall
be discarded immediately upon reception. When a message is retransmitted
to a bridged subnet, the stored IVISeq value shall be updated. In this
way, bridged subnets are protected against replay attacks from other
subnets.
```

This was noticed with MESH/NODE/SBR/NET/BV-02-C test. It passes when
PTS misses the message at step 3 and 4, and fails when PTS manages to
receive the message.

This commit fixes the wrong behavior by removing argument for
`bt_mesh_rpl_check` function making store a new message and bypassing
`local_match` check in case of Subnet Bridge node.

Signed-off-by: default avatarPavel Vasilyev <pavel.vasilyev@nordicsemi.no>
parent dfdce2c1
Loading
Loading
Loading
Loading
+1 −3
Changes for subsys/bluetooth/mesh/net.c: 1 added line, 3 removed lines.
Original line number Diff line number Diff line
@@ -927,9 +927,7 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi,
		return;
	}

	struct bt_mesh_rpl *rpl = NULL;

	if (bt_mesh_rpl_check(&rx, &rpl)) {
	if (bt_mesh_rpl_check(&rx, NULL, true)) {
		return;
	}

+1 −1
Changes for subsys/bluetooth/mesh/proxy_srv.c: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -277,7 +277,7 @@ static void proxy_cfg(struct bt_mesh_proxy_role *role)

	rx.local_match = 1U;

	if (bt_mesh_rpl_check(&rx, NULL)) {
	if (bt_mesh_rpl_check(&rx, NULL, false)) {
		LOG_WRN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", rx.ctx.addr, rx.ctx.recv_dst,
			rx.seq);
		return;
+3 −3
Changes for subsys/bluetooth/mesh/rpl.c: 3 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
 * by upper logic (access, transport commands) and for receiving the segmented messages.
 * If a NULL match is given the RPL is immediately updated (used for proxy configuration).
 */
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match, bool bridge)
{
	struct bt_mesh_rpl *rpl;
	int i;
@@ -117,8 +117,8 @@ bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
		return false;
	}

	/* The RPL is used only for the local node */
	if (!rx->local_match) {
	/* The RPL is used only for the local node or Subnet Bridge. */
	if (!rx->local_match && !bridge) {
		return false;
	}

+1 −2
Changes for subsys/bluetooth/mesh/rpl.h: 1 added line, 2 removed lines.
Original line number Diff line number Diff line
@@ -22,8 +22,7 @@ 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);
bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match, bool bridge);
void bt_mesh_rpl_clear(void);
void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
			struct bt_mesh_net_rx *rx);
+2 −2
Changes for subsys/bluetooth/mesh/transport.c: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -1036,7 +1036,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx,
		return -EBADMSG;
	}

	if (bt_mesh_rpl_check(rx, &rpl)) {
	if (bt_mesh_rpl_check(rx, &rpl, false)) {
		LOG_WRN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", rx->ctx.addr, rx->ctx.recv_dst,
			rx->seq);
		return -EINVAL;
@@ -1350,7 +1350,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
		return -EBADMSG;
	}

	if (bt_mesh_rpl_check(net_rx, &rpl)) {
	if (bt_mesh_rpl_check(net_rx, &rpl, false)) {
		LOG_WRN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", net_rx->ctx.addr,
			net_rx->ctx.recv_dst, net_rx->seq);
		return -EINVAL;
Loading