diff mbox series

[BlueZ,2/2] mesh: Move RPL check from model to net layer

Message ID 20200828200427.18753-3-inga.stotland@intel.com (mailing list archive)
State Accepted
Headers show
Series Mesh replay protection clean up | expand

Commit Message

Stotland, Inga Aug. 28, 2020, 8:04 p.m. UTC
Check whether an incoming message has an RPL entry prior to
handing it over to model layer for processing. If present in RPL
or the RPL queue is full, ignore the incoming message.

If the incoming message is processed successfully, add the message
as a new RPL entry.
---
 mesh/model.c |  18 ++---
 mesh/model.h |   6 +-
 mesh/net.c   | 184 +++++++++++++++++++++++++++------------------------
 mesh/net.h   |   4 --
 4 files changed, 106 insertions(+), 106 deletions(-)
diff mbox series

Patch

diff --git a/mesh/model.c b/mesh/model.c
index 7bbc9cca7..ed2a75215 100644
--- a/mesh/model.c
+++ b/mesh/model.c
@@ -862,9 +862,9 @@  static void send_msg_rcvd(struct mesh_node *node, uint8_t ele_idx,
 }
 
 bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
-			uint32_t seq, uint32_t iv_index,
-			uint16_t net_idx, uint16_t src, uint16_t dst,
-			uint8_t key_aid, const uint8_t *data, uint16_t size)
+			uint32_t iv_index, uint16_t net_idx, uint16_t src,
+			uint16_t dst, uint8_t key_aid, const uint8_t *data,
+								uint16_t size)
 {
 	uint8_t *clear_text;
 	struct mod_forward forward = {
@@ -877,7 +877,7 @@  bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
 	struct mesh_net *net = node_get_net(node);
 	uint8_t num_ele;
 	int decrypt_idx, i, ele_idx;
-	uint16_t addr, crpl;
+	uint16_t addr;
 	struct mesh_virtual *decrypt_virt = NULL;
 	bool result = false;
 	bool is_subscription;
@@ -892,12 +892,6 @@  bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
 		/* Unicast and not addressed to us */
 		return false;
 
-	/* Don't process if already in RPL */
-	crpl = node_get_crpl(node);
-
-	if (net_msg_check_replay_cache(net, src, crpl, seq, iv_index))
-		return false;
-
 	clear_text = l_malloc(size);
 	forward.data = clear_text;
 
@@ -988,10 +982,6 @@  bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
 			break;
 	}
 
-	/* If message has been handled by us, add to RPL */
-	if (result)
-		net_msg_add_replay_cache(net, src, seq, iv_index);
-
 done:
 	l_free(clear_text);
 
diff --git a/mesh/model.h b/mesh/model.h
index fe0648d04..2eec761a0 100644
--- a/mesh/model.h
+++ b/mesh/model.h
@@ -117,9 +117,9 @@  bool mesh_model_send(struct mesh_node *node, uint16_t src, uint16_t dst,
 int mesh_model_publish(struct mesh_node *node, uint32_t id, uint16_t src,
 			bool segmented, uint16_t len, const void *data);
 bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
-			uint32_t seq, uint32_t iv_index, uint16_t net_idx,
-			uint16_t src, uint16_t dst, uint8_t key_aid,
-			const uint8_t *data, uint16_t size);
+			uint32_t iv_index, uint16_t net_idx, uint16_t src,
+			uint16_t dst, uint8_t key_aid, const uint8_t *data,
+								uint16_t size);
 void mesh_model_app_key_delete(struct mesh_node *node, uint16_t ele_idx,
 				struct l_queue *models, uint16_t app_idx);
 uint16_t mesh_model_opcode_set(uint32_t opcode, uint8_t *buf);
diff --git a/mesh/net.c b/mesh/net.c
index 83647d6ad..6c7311732 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -1621,6 +1621,91 @@  static void outseg_to(struct l_timeout *seg_timeout, void *user_data)
 					sar->seqZero, sar->last_nak);
 }
 
+static bool match_replay_cache(const void *a, const void *b)
+{
+	const struct mesh_rpl *rpe = a;
+	uint16_t src = L_PTR_TO_UINT(b);
+
+	return src == rpe->src;
+}
+
+static bool clean_old_iv_index(void *a, void *b)
+{
+	struct mesh_rpl *rpe = a;
+	uint32_t iv_index = L_PTR_TO_UINT(b);
+
+	if (iv_index < 2)
+		return false;
+
+	if (rpe->iv_index < iv_index - 1) {
+		l_free(rpe);
+		return true;
+	}
+
+	return false;
+}
+
+static bool msg_check_replay_cache(struct mesh_net *net, uint16_t src,
+				uint16_t crpl, uint32_t seq, uint32_t iv_index)
+{
+	struct mesh_rpl *rpe;
+
+	/* If anything missing reject this message by returning true */
+	if (!net || !net->node)
+		return true;
+
+	rpe = l_queue_find(net->replay_cache, match_replay_cache,
+						L_UINT_TO_PTR(src));
+
+	if (rpe) {
+		if (iv_index > rpe->iv_index)
+			return false;
+
+		/* Return true if (iv_index | seq) too low */
+		if (iv_index < rpe->iv_index || seq <= rpe->seq) {
+			l_debug("Ignoring replayed packet");
+			return true;
+		}
+	} else if (l_queue_length(net->replay_cache) >= crpl) {
+		/* SRC not in Replay Cache... see if there is space for it */
+
+		int ret = l_queue_foreach_remove(net->replay_cache,
+				clean_old_iv_index, L_UINT_TO_PTR(iv_index));
+
+		/* Return true if no space could be freed */
+		if (!ret) {
+			l_debug("Replay cache full");
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static void msg_add_replay_cache(struct mesh_net *net, uint16_t src,
+						uint32_t seq, uint32_t iv_index)
+{
+	struct mesh_rpl *rpe;
+
+	if (!net || !net->replay_cache)
+		return;
+
+	rpe = l_queue_remove_if(net->replay_cache, match_replay_cache,
+						L_UINT_TO_PTR(src));
+
+	if (!rpe) {
+		rpe = l_new(struct mesh_rpl, 1);
+		rpe->src = src;
+	}
+
+	rpe->seq = seq;
+	rpe->iv_index = iv_index;
+	rpl_put_entry(net->node, src, iv_index, seq);
+
+	/* Optimize so that most recent conversations stay earliest in cache */
+	l_queue_push_head(net->replay_cache, rpe);
+}
+
 static bool msg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index,
 					uint8_t ttl, uint32_t seq,
 					uint16_t net_idx,
@@ -1630,6 +1715,7 @@  static bool msg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index,
 					const uint8_t *data, uint16_t size)
 {
 	uint32_t seqAuth = seq_auth(seq, seqZero);
+	uint16_t crpl;
 
 	/* Sanity check seqAuth */
 	if (seqAuth > seq)
@@ -1671,8 +1757,19 @@  not_for_friend:
 	if (dst == PROXIES_ADDRESS && !net->proxy_enable)
 		return false;
 
-	return mesh_model_rx(net->node, szmic, seqAuth, seq, iv_index, net_idx,
-						src, dst, key_aid, data, size);
+	/* Don't process if already in RPL */
+	crpl = node_get_crpl(net->node);
+
+	if (msg_check_replay_cache(net, src, crpl, seq, iv_index))
+		return false;
+
+	if (!mesh_model_rx(net->node, szmic, seqAuth, iv_index, net_idx, src,
+						dst, key_aid, data, size))
+		return false;
+
+	/* If message has been handled by us, add to RPL */
+	msg_add_replay_cache(net, src, seq, iv_index);
+	return true;
 }
 
 static uint16_t key_id_to_net_idx(struct mesh_net *net, uint32_t key_id)
@@ -3448,89 +3545,6 @@  uint32_t mesh_net_get_instant(struct mesh_net *net)
 	return net->instant;
 }
 
-static bool match_replay_cache(const void *a, const void *b)
-{
-	const struct mesh_rpl *rpe = a;
-	uint16_t src = L_PTR_TO_UINT(b);
-
-	return src == rpe->src;
-}
-
-static bool clean_old_iv_index(void *a, void *b)
-{
-	struct mesh_rpl *rpe = a;
-	uint32_t iv_index = L_PTR_TO_UINT(b);
-
-	if (iv_index < 2)
-		return false;
-
-	if (rpe->iv_index < iv_index - 1) {
-		l_free(rpe);
-		return true;
-	}
-
-	return false;
-}
-
-bool net_msg_check_replay_cache(struct mesh_net *net, uint16_t src,
-				uint16_t crpl, uint32_t seq, uint32_t iv_index)
-{
-	struct mesh_rpl *rpe;
-
-	/* If anything missing reject this message by returning true */
-	if (!net || !net->node)
-		return true;
-
-	rpe = l_queue_find(net->replay_cache, match_replay_cache,
-						L_UINT_TO_PTR(src));
-
-	if (rpe) {
-		if (iv_index > rpe->iv_index)
-			return false;
-
-		/* Return true if (iv_index | seq) too low */
-		if (iv_index < rpe->iv_index || seq <= rpe->seq) {
-			l_debug("Ignoring replayed packet");
-			return true;
-		}
-	} else if (l_queue_length(net->replay_cache) >= crpl) {
-		/* SRC not in Replay Cache... see if there is space for it */
-
-		int ret = l_queue_foreach_remove(net->replay_cache,
-				clean_old_iv_index, L_UINT_TO_PTR(iv_index));
-
-		/* Return true if no space could be freed */
-		if (!ret)
-			return true;
-	}
-
-	return false;
-}
-
-void net_msg_add_replay_cache(struct mesh_net *net, uint16_t src, uint32_t seq,
-							uint32_t iv_index)
-{
-	struct mesh_rpl *rpe;
-
-	if (!net || !net->replay_cache)
-		return;
-
-	rpe = l_queue_remove_if(net->replay_cache, match_replay_cache,
-						L_UINT_TO_PTR(src));
-
-	if (!rpe) {
-		rpe = l_new(struct mesh_rpl, 1);
-		rpe->src = src;
-	}
-
-	rpe->seq = seq;
-	rpe->iv_index = iv_index;
-	rpl_put_entry(net->node, src, iv_index, seq);
-
-	/* Optimize so that most recent conversations stay earliest in cache */
-	l_queue_push_head(net->replay_cache, rpe);
-}
-
 static void hb_sub_timeout_func(struct l_timeout *timeout, void *user_data)
 {
 	struct mesh_net *net = user_data;
diff --git a/mesh/net.h b/mesh/net.h
index 725054ce6..7bec6d0fc 100644
--- a/mesh/net.h
+++ b/mesh/net.h
@@ -354,8 +354,4 @@  void mesh_net_set_prov(struct mesh_net *net, struct mesh_prov *prov);
 uint32_t mesh_net_get_instant(struct mesh_net *net);
 struct l_queue *mesh_net_get_friends(struct mesh_net *net);
 struct l_queue *mesh_net_get_negotiations(struct mesh_net *net);
-bool net_msg_check_replay_cache(struct mesh_net *net, uint16_t src,
-				uint16_t crpl, uint32_t seq, uint32_t iv_index);
-void net_msg_add_replay_cache(struct mesh_net *net, uint16_t src, uint32_t seq,
-							uint32_t iv_index);
 bool mesh_net_load_rpl(struct mesh_net *net);