diff --git a/mesh/model.c b/mesh/model.c
index 92a0049..072972f 100644
--- a/mesh/model.c
+++ b/mesh/model.c
/* 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;
/*
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;
* 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)
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
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;
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
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);