fix: evaluate pre-hop hop_start bitfield guard post-decode instead of before decryption
This commit is contained in:
+6
-8
@@ -2835,14 +2835,12 @@ HopStartStatus classifyHopStart(const meshtastic_MeshPacket &p)
|
|||||||
return HopStartStatus::INVALID;
|
return HopStartStatus::INVALID;
|
||||||
|
|
||||||
if (p.hop_start == 0) {
|
if (p.hop_start == 0) {
|
||||||
// hop_start == hop_limit == 0: intentional zero-hop broadcast (e.g. beacon). Valid by definition —
|
// hop_start == 0 is either a modern zero-hop broadcast (e.g. beacon) or pre-2.3.0 firmware (585805c)
|
||||||
// the packet was never meant to travel any hops, so no hop_start ambiguity applies.
|
// that never populated hop_start. Firmware 2.5.0 (bf34329) introduced a bitfield that is always
|
||||||
if (p.hop_limit == 0)
|
// present; use it to tell the two apart. The bitfield is encrypted under the channel key, so this can
|
||||||
return HopStartStatus::VALID;
|
// only be resolved for decoded packets — until then the status stays MISSING_OR_UNKNOWN. Callers
|
||||||
// Firmware prior to 2.3.0 (585805c) lacked a hop_start field. Firmware version 2.5.0 (bf34329) introduced a
|
// acting before decode must therefore not treat UNKNOWN as a drop (the bitfield isn't readable yet);
|
||||||
// bitfield that is always present. Use the presence of the bitfield to determine if the origin's firmware
|
// the verdict is re-checked post-decode in Router::handleReceived.
|
||||||
// version is guaranteed to have hop_start populated. Note that this can only be done for decoded packets as
|
|
||||||
// the bitfield is encrypted under the channel encryption key.
|
|
||||||
if (p.which_payload_variant == meshtastic_MeshPacket_decoded_tag && p.decoded.has_bitfield)
|
if (p.which_payload_variant == meshtastic_MeshPacket_decoded_tag && p.decoded.has_bitfield)
|
||||||
return HopStartStatus::VALID;
|
return HopStartStatus::VALID;
|
||||||
return HopStartStatus::MISSING_OR_UNKNOWN;
|
return HopStartStatus::MISSING_OR_UNKNOWN;
|
||||||
|
|||||||
+4
-1
@@ -147,7 +147,10 @@ inline bool shouldDropPacketForPreHop(const meshtastic_MeshPacket &p)
|
|||||||
if (isFromUs(&p)) {
|
if (isFromUs(&p)) {
|
||||||
return false; // local-originated packets should never be dropped by pre-hop drop policy
|
return false; // local-originated packets should never be dropped by pre-hop drop policy
|
||||||
}
|
}
|
||||||
return classifyHopStart(p) != HopStartStatus::VALID;
|
// Pre-decode: the channel-encrypted bitfield isn't readable yet, so a missing/unknown hop_start can't be
|
||||||
|
// distinguished from a modern packet. Only drop the provably-corrupt case here; the bitfield-dependent
|
||||||
|
// verdict is re-checked post-decode in Router::handleReceived.
|
||||||
|
return classifyHopStart(p) == HopStartStatus::INVALID;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -823,6 +823,18 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
|||||||
else
|
else
|
||||||
printPacket("handleReceived(REMOTE)", p);
|
printPacket("handleReceived(REMOTE)", p);
|
||||||
|
|
||||||
|
#if MESHTASTIC_PREHOP_DROP
|
||||||
|
// Pre-hop firmware drop, post-decode half: the bitfield that proves the origin populated hop_start is
|
||||||
|
// encrypted under the channel key, so it can only be evaluated now that the packet is decoded. A packet
|
||||||
|
// whose hop_start is still missing/unknown comes from pre-hop firmware — keep it out of module
|
||||||
|
// processing, admin handling, phone delivery, MQTT and rebroadcast. Local-origin packets are exempt.
|
||||||
|
if (!isFromUs(p) && classifyHopStart(*p) != HopStartStatus::VALID) {
|
||||||
|
logHopStartDrop(*p, "post-decode pre-hop drop");
|
||||||
|
cancelSending(p->from, p->id);
|
||||||
|
skipHandle = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Neighbor info module is disabled, ignore expensive neighbor info packets
|
// Neighbor info module is disabled, ignore expensive neighbor info packets
|
||||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
||||||
p->decoded.portnum == meshtastic_PortNum_NEIGHBORINFO_APP &&
|
p->decoded.portnum == meshtastic_PortNum_NEIGHBORINFO_APP &&
|
||||||
|
|||||||
Reference in New Issue
Block a user