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:
DeFiDude
2026-03-21 14:14:34 -06:00
parent 4a7b1935d5
commit 0c4fbb5cd5
2 changed files with 10 additions and 11 deletions

View File

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

View File

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