@@ -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);
@@ -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);
@@ -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;
@@ -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);