Diff between 8457e6a3ad147c1167862f148cbbf281d879e874 and da429de905ed87f7d530ca29284aedfad848f227

Changed Files

File Additions Deletions Status
mesh/model.c +10 -13 modified
mesh/net.c +31 -31 modified
mesh/net.h +4 -3 modified

Full Patch

diff --git a/mesh/model.c b/mesh/model.c
index 92a0049..072972f 100644
--- a/mesh/model.c
+++ b/mesh/model.c
@@ -964,10 +964,12 @@ bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
 		/* Unicast and not addressed to us */
 		return false;
 
-	clear_text = l_malloc(size);
-	if (!clear_text)
+	/* 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;
 
 	/*
@@ -995,16 +997,6 @@ bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
 		goto done;
 	}
 
-	/* print_packet("Clr Rx (pre-cache-check)", clear_text, size - 4); */
-
-	crpl = node_get_crpl(node);
-
-	if (net_msg_in_replay_cache(net, (uint16_t) decrypt_idx, src,
-				crpl, seq, iv_index)) {
-		result = true;
-		goto done;
-	}
-
 	print_packet("Clr Rx", clear_text, size - (szmict ? 8 : 4));
 
 	forward.virt = decrypt_virt;
@@ -1073,7 +1065,7 @@ bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
 		 * Either the message has been processed internally or
 		 * has been passed on to an external model.
 		 */
-		result = forward.has_dst | forward.done;
+		result |= forward.has_dst | forward.done;
 
 		/* If the message was to unicast address, we are done */
 		if (!is_subscription && ele_idx == i)
@@ -1088,8 +1080,13 @@ 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);
+
 	return result;
 }
 
diff --git a/mesh/net.c b/mesh/net.c
index 19f3b87..ec05b6b 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -3759,9 +3759,8 @@ static bool clean_old_iv_index(void *a, void *b)
 	return false;
 }
 
-bool net_msg_in_replay_cache(struct mesh_net *net, uint16_t idx,
-				uint16_t src, uint16_t crpl, uint32_t seq,
-				uint32_t iv_index)
+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;
 
@@ -3782,49 +3781,50 @@ bool net_msg_in_replay_cache(struct mesh_net *net, uint16_t idx,
 						L_UINT_TO_PTR(src));
 
 	if (rpe) {
-		if (iv_index > rpe->iv_index) {
-			rpe->seq = seq;
-			rpe->iv_index = iv_index;
-			rpl_put_entry(net->node, src, iv_index, seq);
+		if (iv_index > rpe->iv_index)
 			return false;
-		}
-
-		if (seq < rpe->seq) {
-			l_debug("Ignoring packet with lower sequence number");
-			return true;
-		}
 
-		if (seq == rpe->seq) {
-			l_debug("Message already processed (duplicate)");
+		/* Return true if (iv_index | seq) too low */
+		if (iv_index < rpe->iv_index || seq <= rpe->seq) {
+			l_debug("Ignoring replayed packet");
 			return true;
 		}
-
-		rpe->seq = seq;
-
-		rpl_put_entry(net->node, src, iv_index, seq);
-
-		return false;
 	}
 
-	l_debug("New Entry for %4.4x", src);
-
-	/* Replay Cache is fixed sized */
-	if (l_queue_length(net->replay_cache) >= crpl) {
+	/* SRC not in Replay Cache... see if there is space for it */
+	else if (l_queue_length(net->replay_cache) >= crpl) {
 		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;
 	}
 
-	if (!rpl_put_entry(net->node, src, iv_index, seq))
-		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) {
+		l_debug("New Entry for %4.4x", src);
+		rpe = l_new(struct mesh_rpl, 1);
+		rpe->seq = src;
+	}
 
-	rpe = l_new(struct mesh_rpl, 1);
-	rpe->src = src;
 	rpe->seq = seq;
 	rpe->iv_index = iv_index;
-	l_queue_push_head(net->replay_cache, rpe);
+	rpl_put_entry(net->node, src, iv_index, seq);
 
-	return false;
+	/* Optimize so that most recent conversations stay earliest in cache */
+	l_queue_push_head(net->replay_cache, rpe);
 }
diff --git a/mesh/net.h b/mesh/net.h
index ff0a9bb..6fedd69 100644
--- a/mesh/net.h
+++ b/mesh/net.h
@@ -379,6 +379,7 @@ 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_in_replay_cache(struct mesh_net *net, uint16_t idx,
-				uint16_t src, uint16_t crpl, uint32_t seq,
-				uint32_t iv_index);
+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);