Added compatibility between nodes on different Presets through Mesh via UDP

This commit is contained in:
ViezeVingertjes 2025-08-26 16:57:01 +02:00
parent 3d825c51dd
commit 71812d220b
5 changed files with 54 additions and 0 deletions

View File

@ -422,6 +422,29 @@ bool Channels::decryptForHash(ChannelIndex chIndex, ChannelHash channelHash)
}
}
bool Channels::setDefaultPresetCryptoForHash(ChannelHash channelHash)
{
// Iterate all known presets
for (int preset = _meshtastic_Config_LoRaConfig_ModemPreset_MIN; preset <= _meshtastic_Config_LoRaConfig_ModemPreset_MAX; ++preset) {
const char *name = DisplayFormatters::getModemPresetDisplayName((meshtastic_Config_LoRaConfig_ModemPreset)preset, false);
if (!name) continue;
if (strcmp(name, "Invalid") == 0) continue; // skip invalid placeholder
uint8_t h = xorHash((const uint8_t *)name, strlen(name));
// Expand default PSK alias 1 to actual bytes and xor into hash
uint8_t tmp = h ^ xorHash(defaultpsk, sizeof(defaultpsk));
if (tmp == channelHash) {
// Set crypto to defaultpsk and report success
CryptoKey k;
memcpy(k.bytes, defaultpsk, sizeof(defaultpsk));
k.length = sizeof(defaultpsk);
crypto->setKey(k);
LOG_INFO("Matched default preset '%s' for hash 0x%x; set default PSK", name, channelHash);
return true;
}
}
return false;
}
/** Given a channel index setup crypto for encoding that channel (or the primary channel if that channel is unsecured)
*
* This method is called before encoding outbound packets

View File

@ -94,6 +94,8 @@ class Channels
bool ensureLicensedOperation();
bool setDefaultPresetCryptoForHash(ChannelHash channelHash);
private:
/** Given a channel index, change to use the crypto key specified by that index
*

View File

@ -68,6 +68,13 @@ bool FloodingRouter::isRebroadcaster()
void FloodingRouter::perhapsRebroadcast(const meshtastic_MeshPacket *p)
{
if (!isToUs(p) && (p->hop_limit > 0) && !isFromUs(p)) {
// If this packet arrived via UDP and is still encrypted, skip rebroadcast.
// We expect the router to decode and then re-encode to our local preset before sending.
if (p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP &&
p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag) {
LOG_DEBUG("Skip rebroadcast of UDP-encrypted packet; awaiting local decode/re-encode");
return;
}
if (p->id != 0) {
if (isRebroadcaster()) {
meshtastic_MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it

View File

@ -416,6 +416,27 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
}
}
}
// Fallback: for UDP multicast, try default preset names with default PSK if normal channel match failed
if (!decrypted && p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP) {
if (channels.setDefaultPresetCryptoForHash(p->channel)) {
memcpy(bytes, p->encrypted.bytes, rawSize);
crypto->decrypt(p->from, p->id, rawSize, bytes);
meshtastic_Data decodedtmp;
memset(&decodedtmp, 0, sizeof(decodedtmp));
if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &decodedtmp) &&
decodedtmp.portnum != meshtastic_PortNum_UNKNOWN_APP) {
p->decoded = decodedtmp;
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag;
// Map to our primary channel index so subsequent processing and re-encoding use local preset
chIndex = channels.getPrimaryIndex();
decrypted = true;
} else {
LOG_WARN("UDP fallback decode attempted but failed for hash 0x%x", p->channel);
}
}
}
if (decrypted) {
// parsing was successful
p->channel = chIndex; // change to store the index instead of the hash

View File

@ -54,6 +54,7 @@ class UdpMulticastHandler final
LOG_DEBUG("Decoding MeshPacket from UDP len=%u", packetLength);
bool isPacketDecoded = pb_decode_from_bytes(packet.data(), packetLength, &meshtastic_MeshPacket_msg, &mp);
if (isPacketDecoded && router && mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag) {
mp.transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP;
mp.pki_encrypted = false;
mp.public_key.size = 0;
memset(mp.public_key.bytes, 0, sizeof(mp.public_key.bytes));