mirror of
https://github.com/ratspeak/ratdeck.git
synced 2026-03-30 14:15:39 +00:00
Drop oversized LoRa packets instead of silently truncating
The previous LORA_SAFE_LINK_PAYLOAD check only guarded link delivery, but opportunistic delivery also exceeds the 255-byte LoRa MTU for longer messages. Truncated packets corrupt the HMAC/ciphertext, wasting airtime and confusing receivers. Fix: LoRaInterface::send_outgoing() now rejects packets exceeding MAX_PACKET_SIZE before they reach the radio. This is a hard limit — messages too large for a single LoRa packet will not be sent until Resource-based multi-packet transfer is implemented.
This commit is contained in:
@@ -152,22 +152,12 @@ bool LXMFManager::sendDirect(LXMFMessage& msg) {
|
||||
linkPayload.insert(linkPayload.end(), msg.destHash.data(), msg.destHash.data() + 16);
|
||||
linkPayload.insert(linkPayload.end(), payload.begin(), payload.end());
|
||||
RNS::Bytes linkBytes(linkPayload.data(), linkPayload.size());
|
||||
// Token encryption adds ~48 bytes (IV:16 + HMAC:32 + AES padding).
|
||||
// LoRa packets are max 255 bytes (1 header + 19 Reticulum H1 + encrypted).
|
||||
// If the plaintext is too large, Token output exceeds LoRa MTU and
|
||||
// SX1262::write() silently truncates, corrupting the HMAC.
|
||||
// Cap link delivery to 180 bytes to stay safely under the limit.
|
||||
// Larger messages fall through to opportunistic delivery.
|
||||
static constexpr size_t LORA_SAFE_LINK_PAYLOAD = 180;
|
||||
if (linkBytes.size() <= LORA_SAFE_LINK_PAYLOAD) {
|
||||
if (linkBytes.size() <= RNS::Type::Reticulum::MDU) {
|
||||
Serial.printf("[LXMF] sending via link: %d bytes to %s\n",
|
||||
(int)linkBytes.size(), msg.destHash.toHex().substr(0, 8).c_str());
|
||||
RNS::Packet packet(_outLink, linkBytes);
|
||||
RNS::PacketReceipt receipt = packet.send();
|
||||
if (receipt) { sent = true; }
|
||||
} else {
|
||||
Serial.printf("[LXMF] link payload too large for LoRa (%d > %d), using opportunistic\n",
|
||||
(int)linkBytes.size(), (int)LORA_SAFE_LINK_PAYLOAD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,15 @@ void LoRaInterface::send_outgoing(const RNS::Bytes& data) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reject packets that exceed the LoRa MTU (255 bytes including 1-byte header).
|
||||
// Sending truncated packets corrupts encryption (HMAC failures on receiver).
|
||||
if (data.size() + RNODE_HEADER_L > MAX_PACKET_SIZE) {
|
||||
Serial.printf("[LORA_IF] TX DROPPED: packet too large (%d + %d = %d > %d)\n",
|
||||
(int)data.size(), RNODE_HEADER_L,
|
||||
(int)(data.size() + RNODE_HEADER_L), MAX_PACKET_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Build RNode-compatible 1-byte header:
|
||||
// Upper nibble: random sequence number (for split-packet tracking)
|
||||
// Lower nibble: flags (FLAG_SPLIT=0x01 if packet won't fit in single frame)
|
||||
|
||||
Reference in New Issue
Block a user