diff options
Diffstat (limited to 'mesh')
-rw-r--r-- | mesh/net.c | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/mesh/net.c b/mesh/net.c index 577121f30..a1b586a0b 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; |