From a5ed0a4321e5fe1348f91b5bb3f99986ca555281 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Sat, 18 Jul 2026 21:26:57 +0200 Subject: [PATCH] Improved HDLC handling --- RNS/Interfaces/BackboneInterface.py | 18 ++++++++++++++++-- RNS/Interfaces/TCPInterface.py | 17 +++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/RNS/Interfaces/BackboneInterface.py b/RNS/Interfaces/BackboneInterface.py index 123559b4..8c3cba9e 100644 --- a/RNS/Interfaces/BackboneInterface.py +++ b/RNS/Interfaces/BackboneInterface.py @@ -759,6 +759,14 @@ class BackboneClientInterface(Interface): RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR) self.teardown() + def check_frame_len(self, frame_len): + if frame_len <= RNS.Reticulum.HEADER_MINSIZE: return False + elif frame_len > self.HW_MTU + (self.ifac_size or 0): return False + else: return True + + def invalid_frame(self, frame_len): + RNS.log(f"Invalid HDLC frame of {RNS.prettysize(frame_len)} received on {self}, dropping frame", RNS.LOG_DEBUG) if RNS.sl(RNS.LOG_DEBUG) else None + def receive(self, data_in): try: if len(data_in) > 0: @@ -772,12 +780,18 @@ class BackboneClientInterface(Interface): frame = self.frame_buffer[frame_start+1:frame_end] frame = frame.replace(bytes([HDLC.ESC, HDLC.FLAG ^ HDLC.ESC_MASK]), bytes([HDLC.FLAG])) frame = frame.replace(bytes([HDLC.ESC, HDLC.ESC ^ HDLC.ESC_MASK]), bytes([HDLC.ESC])) - if len(frame) > RNS.Reticulum.HEADER_MINSIZE: - self.process_incoming(frame) + frame_len = len(frame) + if frame_len != 0: + if self.check_frame_len(frame_len): self.process_incoming(frame) + else: self.invalid_frame(len(frame)) + self.frame_buffer = self.frame_buffer[frame_end:] + else: + if len(self.frame_buffer) > self.HW_MTU*2: self.frame_buffer = b"" flags_remaining = False else: + self.frame_buffer = b"" flags_remaining = False else: diff --git a/RNS/Interfaces/TCPInterface.py b/RNS/Interfaces/TCPInterface.py index a5566e31..5559732f 100644 --- a/RNS/Interfaces/TCPInterface.py +++ b/RNS/Interfaces/TCPInterface.py @@ -333,6 +333,13 @@ class TCPClientInterface(Interface): RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR) self.teardown() + def check_frame_len(self, frame_len): + if frame_len <= RNS.Reticulum.HEADER_MINSIZE: return False + elif frame_len > self.HW_MTU + (self.ifac_size or 0): return False + else: return True + + def invalid_frame(self, frame_len): + RNS.log(f"Invalid HDLC frame of {RNS.prettysize(frame_len)} received on {self}, dropping frame", RNS.LOG_DEBUG) if RNS.sl(RNS.LOG_DEBUG) else None def read_loop(self): try: @@ -389,12 +396,18 @@ class TCPClientInterface(Interface): frame = frame_buffer[frame_start+1:frame_end] frame = frame.replace(bytes([HDLC.ESC, HDLC.FLAG ^ HDLC.ESC_MASK]), bytes([HDLC.FLAG])) frame = frame.replace(bytes([HDLC.ESC, HDLC.ESC ^ HDLC.ESC_MASK]), bytes([HDLC.ESC])) - if len(frame) > RNS.Reticulum.HEADER_MINSIZE: - self.process_incoming(frame) + frame_len = len(frame) + if frame_len != 0: + if self.check_frame_len(frame_len): self.process_incoming(frame) + else: self.invalid_frame(len(frame)) + frame_buffer = frame_buffer[frame_end:] + else: + if len(frame_buffer) > self.HW_MTU*2: frame_buffer = b"" flags_remaining = False else: + frame_buffer = b"" flags_remaining = False else: