Diff between 3f3a7b8e192f210b7119b30e8c840e13993134a9 and c89e9c4b22b4f32c5b4dee396caf5fc54b434da2

Changed Files

File Additions Deletions Status
mesh/net.c +36 -11 modified

Full Patch

diff --git a/mesh/net.c b/mesh/net.c
index 577121f..a1b586a 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -1763,7 +1763,8 @@ not_for_friend:
 	return true;
 }
 
-static uint16_t key_id_to_net_idx(struct mesh_net *net, uint32_t net_key_id)
+static uint16_t key_id_to_net_idx(struct mesh_net *net,
+				uint32_t net_key_id, bool *frnd)
 {
 	struct mesh_subnet *subnet;
 	struct mesh_friend *friend;
@@ -1771,6 +1772,9 @@ static uint16_t key_id_to_net_idx(struct mesh_net *net, uint32_t net_key_id)
 	if (!net)
 		return NET_IDX_INVALID;
 
+	if (frnd)
+		*frnd = false;
+
 	subnet = l_queue_find(net->subnets, match_key_id,
 						L_UINT_TO_PTR(net_key_id));
 
@@ -1780,8 +1784,12 @@ static uint16_t key_id_to_net_idx(struct mesh_net *net, uint32_t net_key_id)
 	friend = l_queue_find(net->friends, match_friend_key_id,
 						L_UINT_TO_PTR(net_key_id));
 
-	if (friend)
+	if (friend) {
+		if (frnd)
+			*frnd = true;
+
 		return friend->net_idx;
+	}
 
 	friend = l_queue_find(net->negotiations, match_friend_key_id,
 						L_UINT_TO_PTR(net_key_id));
@@ -2078,7 +2086,7 @@ static bool ctl_received(struct mesh_net *net, uint32_t net_key_id,
 			return false;
 
 		print_packet("Rx-NET_OP_FRND_REQUEST", pkt, len);
-		net_idx = key_id_to_net_idx(net, net_key_id);
+		net_idx = key_id_to_net_idx(net, net_key_id, NULL);
 		friend_request(net, net_idx, src, pkt[0], pkt[1],
 				l_get_be32(pkt + 1) & 0xffffff,
 				l_get_be16(pkt + 5), pkt[7],
@@ -2269,7 +2277,8 @@ static void send_msg_pkt(struct mesh_net *net, uint8_t cnt, uint16_t interval,
 }
 
 static enum _relay_advice packet_received(void *user_data,
-				uint32_t net_key_id, uint32_t iv_index,
+				uint32_t net_key_id, uint16_t net_idx,
+				bool frnd, uint32_t iv_index,
 				const void *data, uint8_t size, int8_t rssi)
 {
 	struct mesh_net *net = user_data;
@@ -2278,16 +2287,11 @@ static enum _relay_advice packet_received(void *user_data,
 	uint8_t net_ttl, key_aid, net_segO, net_segN, net_opcode;
 	uint32_t net_seq, cache_cookie;
 	uint16_t net_src, net_dst, net_seqZero;
-	uint16_t net_idx;
 	uint8_t packet[31];
 	bool net_ctl, net_segmented, net_szmic, net_relay;
 
 	memcpy(packet + 2, data, size);
 
-	net_idx = key_id_to_net_idx(net, net_key_id);
-	if (net_idx == NET_IDX_INVALID)
-		return RELAY_NONE;
-
 	print_packet("RX: Network [clr] :", packet + 2, size);
 
 	if (!mesh_crypto_packet_parse(packet + 2, size, &net_ctl, &net_ttl,
@@ -2389,6 +2393,13 @@ static enum _relay_advice packet_received(void *user_data,
 			return RELAY_DISALLOWED;
 	}
 
+	/*
+	 * Messages that are encrypted with friendship credentials
+	 * should *always* be relayed
+	 */
+	if (frnd)
+		return RELAY_ALWAYS;
+
 	/* If relay not enable, or no more hops allowed */
 	if (!net->relay.enable || net_ttl < 0x02)
 		return RELAY_NONE;
@@ -2414,7 +2425,9 @@ static void net_rx(void *net_ptr, void *user_data)
 	uint8_t *out;
 	size_t out_size;
 	uint32_t net_key_id;
+	uint16_t net_idx;
 	int8_t rssi = 0;
+	bool frnd;
 	bool ivi_net = !!(net->iv_index & 1);
 	bool ivi_pkt = !!(data->data[0] & 0x80);
 
@@ -2438,9 +2451,21 @@ static void net_rx(void *net_ptr, void *user_data)
 		rssi = data->info->rssi;
 	}
 
-	relay_advice = packet_received(net, net_key_id, iv_index, out, out_size,
-									rssi);
+	net_idx = key_id_to_net_idx(net, net_key_id, &frnd);
+
+	if (net_idx == NET_IDX_INVALID)
+		return;
+
+	relay_advice = packet_received(net, net_key_id, net_idx, frnd,
+						iv_index, out, out_size, rssi);
 	if (relay_advice > data->relay_advice) {
+		/*
+		 * If packet was encrypted with friendship credentials,
+		 * relay it using master credentials
+		 */
+		if (frnd && !mesh_net_get_key(net, false, net_idx, &net_key_id))
+			return;
+
 		data->iv_index = iv_index;
 		data->relay_advice = relay_advice;
 		data->net_key_id = net_key_id;