From 71f6f721fd46bd54b42d067125c08d8912b960a6 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Fri, 19 Jun 2026 19:27:52 +0200 Subject: [PATCH] Added internal interface mode --- RNS/Interfaces/Interface.py | 3 ++- RNS/Reticulum.py | 4 ++++ RNS/Transport.py | 16 ++++++++++++++++ RNS/Utilities/rnstatus.py | 1 + docs/source/interfaces.rst | 9 +++++++++ docs/source/understanding.rst | 26 ++++++++++++++++++-------- 6 files changed, 50 insertions(+), 9 deletions(-) diff --git a/RNS/Interfaces/Interface.py b/RNS/Interfaces/Interface.py index 351da716..f8949872 100755 --- a/RNS/Interfaces/Interface.py +++ b/RNS/Interfaces/Interface.py @@ -48,10 +48,11 @@ class Interface: MODE_ROAMING = 0x04 MODE_BOUNDARY = 0x05 MODE_GATEWAY = 0x06 + MODE_INTERNAL = 0x07 # Which interface modes a Transport Node should # actively discover paths for. - DISCOVER_PATHS_FOR = [MODE_ACCESS_POINT, MODE_GATEWAY, MODE_ROAMING] + DISCOVER_PATHS_FOR = [MODE_ACCESS_POINT, MODE_GATEWAY, MODE_ROAMING, MODE_INTERNAL] # How many samples to use for announce # frequency calculations diff --git a/RNS/Reticulum.py b/RNS/Reticulum.py index b8691f7d..fcfb0736 100755 --- a/RNS/Reticulum.py +++ b/RNS/Reticulum.py @@ -710,6 +710,8 @@ class Reticulum: interface_mode = Interface.Interface.MODE_BOUNDARY elif c["mode"] == "gateway" or c["mode"] == "gw": interface_mode = Interface.Interface.MODE_GATEWAY + elif c["mode"] == "internal": + interface_mode = Interface.Interface.MODE_INTERNAL elif "mode" in c: c["mode"] = str(c["mode"]).lower() @@ -725,6 +727,8 @@ class Reticulum: interface_mode = Interface.Interface.MODE_BOUNDARY elif c["mode"] == "gateway" or c["mode"] == "gw": interface_mode = Interface.Interface.MODE_GATEWAY + elif c["mode"] == "internal": + interface_mode = Interface.Interface.MODE_INTERNAL ifac_size = None if "ifac_size" in c: diff --git a/RNS/Transport.py b/RNS/Transport.py index 644fabd5..37be9338 100755 --- a/RNS/Transport.py +++ b/RNS/Transport.py @@ -1196,6 +1196,22 @@ class Transport: RNS.log("Blocking announce broadcast on "+str(interface)+" due to AP mode", RNS.LOG_EXTREME) if RNS.sl(RNS.LOG_EXTREME) else None should_transmit = False + elif interface.mode == RNS.Interfaces.Interface.Interface.MODE_INTERNAL: + from_interface = Transport.next_hop_interface(packet.destination_hash) + if from_interface == None or not hasattr(from_interface, "mode"): + should_transmit = False + if from_interface == None: + RNS.log("Blocking announce broadcast on "+str(interface)+" since next hop interface doesn't exist", RNS.LOG_EXTREME) if RNS.sl(RNS.LOG_EXTREME) else None + elif not hasattr(from_interface, "mode"): + RNS.log("Blocking announce broadcast on "+str(interface)+" since next hop interface has no mode configured", RNS.LOG_EXTREME) if RNS.sl(RNS.LOG_EXTREME) else None + else: + if from_interface.mode == RNS.Interfaces.Interface.Interface.MODE_ROAMING: + RNS.log("Blocking announce broadcast on "+str(interface)+" due to roaming-mode next-hop interface", RNS.LOG_EXTREME) if RNS.sl(RNS.LOG_EXTREME) else None + should_transmit = False + elif from_interface.mode == RNS.Interfaces.Interface.Interface.MODE_BOUNDARY: + RNS.log("Blocking announce broadcast on "+str(interface)+" due to boundary-mode next-hop interface", RNS.LOG_EXTREME) if RNS.sl(RNS.LOG_EXTREME) else None + should_transmit = False + elif interface.mode == RNS.Interfaces.Interface.Interface.MODE_ROAMING: local_destination = None with Transport.destinations_map_lock: diff --git a/RNS/Utilities/rnstatus.py b/RNS/Utilities/rnstatus.py index 92d8284c..428d1996 100644 --- a/RNS/Utilities/rnstatus.py +++ b/RNS/Utilities/rnstatus.py @@ -423,6 +423,7 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json= elif ifstat["mode"] == RNS.Interfaces.Interface.Interface.MODE_ROAMING: modestr = "Roaming" elif ifstat["mode"] == RNS.Interfaces.Interface.Interface.MODE_BOUNDARY: modestr = "Boundary" elif ifstat["mode"] == RNS.Interfaces.Interface.Interface.MODE_GATEWAY: modestr = "Gateway" + elif ifstat["mode"] == RNS.Interfaces.Interface.Interface.MODE_INTERNAL: modestr = "Internal" else: modestr = "Full" diff --git a/docs/source/interfaces.rst b/docs/source/interfaces.rst index f22aefca..b68f5e0a 100644 --- a/docs/source/interfaces.rst +++ b/docs/source/interfaces.rst @@ -1291,6 +1291,15 @@ the default mode. public Transport Node available on the Internet, the interface connecting over the Internet should be set to ``boundary`` mode. + * | The ``internal`` mode designates interfaces that belong to an + network different from any marked as ``boundary``. Announces from + a ``boundary`` interface will not propagate to interfaces set as + ``internal``, but announces *will* propagate from ``internal`` *to* + ``boundary``. Devices on the ``internal`` side of the network will + still be able to resolve paths to destinations across the boundary + when needed, since recursive path requests are enabled for ``internal`` + mode interfaces by default. + For a table describing the impact of all modes on announce propagation, please see the :ref:`Announce Propagation Rules` section. diff --git a/docs/source/understanding.rst b/docs/source/understanding.rst index 2a9e1072..a4c12180 100644 --- a/docs/source/understanding.rst +++ b/docs/source/understanding.rst @@ -714,23 +714,33 @@ See the :ref:`Interface Modes` section for a conceptual overvi .. (.. code-block:: text) Full ────── ✓ ──┐ ┌── ✓ ── Full - AP ──────── ✓ ──┼───> Full >───┼── ✕ ── AP - Boundary ── ✓ ──┤ ├── ✓ ── Boundary + AP ──────── ✓ ──┤ ├── ✕ ── AP + Boundary ── ✓ ──┼───> Full >───┼── ✓ ── Boundary + Internal ── ✓ ──┤ ├── ✓ ── Internal Roaming ─── ✓ ──┘ └── ✓ ── Roaming Full ────── ✕ ──┐ ┌── ✓ ── Full - AP ──────── ✕ ──┼────> AP >────┼── ✕ ── AP - Boundary ── ✕ ──┤ ├── ✓ ── Boundary + AP ──────── ✕ ──┤ ├── ✕ ── AP + Boundary ── ✕ ──┼────> AP >────┼── ✓ ── Boundary + Internal ── ✕ ──┤ ├── ✓ ── Internal Roaming ─── ✕ ──┘ └── ✓ ── Roaming Full ────── ✓ ──┐ ┌── ✓ ── Full - AP ──────── ✓ ──┼─> Roaming >──┼── ✕ ── AP - Boundary ── ✕ ──┤ ├── ✕ ── Boundary + AP ──────── ✓ ──┤ ├── ✕ ── AP + Boundary ── ✕ ──┼─> Roaming >──┼── ✕ ── Boundary + Internal ── ✕ ──┤ ├── ✕ ── Internal Roaming ─── ✕ ──┘ └── ✕ ── Roaming Full ────── ✓ ──┐ ┌── ✓ ── Full - AP ──────── ✓ ──┼─> Boundary >─┼── ✕ ── AP - Boundary ── ✓ ──┤ ├── ✓ ── Boundary + AP ──────── ✓ ──┤ ├── ✕ ── AP + Boundary ── ✓ ──┼─> Boundary >─┼── ✓ ── Boundary + Internal ── ✓ ──┤ ├── ✕ ── Internal + Roaming ─── ✕ ──┘ └── ✕ ── Roaming + + Full ────── ✓ ──┐ ┌── ✓ ── Full + AP ──────── ✓ ──┤ ├── ✕ ── AP + Boundary ── ✕ ──┼─> Internal >─┼── ✓ ── Boundary + Internal ── ✓ ──┤ ├── ✓ ── Internal Roaming ─── ✕ ──┘ └── ✕ ── Roaming