Improved reachable_on discovery announce field handling

This commit is contained in:
Mark Qvist
2026-01-17 17:09:01 +01:00
parent fa4b69181f
commit fdbf287fee
2 changed files with 31 additions and 3 deletions

View File

@@ -1,7 +1,9 @@
import os import os
import re
import RNS import RNS
import time import time
import threading import threading
import ipaddress
import subprocess import subprocess
from .vendor import umsgpack as msgpack from .vendor import umsgpack as msgpack
@@ -113,12 +115,19 @@ class InterfaceAnnouncer():
exec_stdout = exec_result.stdout.decode("utf-8") exec_stdout = exec_result.stdout.decode("utf-8")
if exec_result.returncode != 0: raise ValueError("Non-zero exit code from subprocess") if exec_result.returncode != 0: raise ValueError("Non-zero exit code from subprocess")
reachable_on = self.sanitize(exec_stdout) reachable_on = self.sanitize(exec_stdout)
if not (is_ip_address(reachable_on) or is_hostname(reachable_on)):
raise ValueError(f"Valid IP address or hostname was not found in external script output \"{reachable_on}\"")
except Exception as e: except Exception as e:
RNS.log(f"Error while getting reachable_on from executable at {interface.reachable_on}: {e}", RNS.LOG_ERROR) RNS.log(f"Error while getting reachable_on from executable at {interface.reachable_on}: {e}", RNS.LOG_ERROR)
RNS.log(f"Aborting discovery announce", RNS.LOG_ERROR) RNS.log(f"Aborting discovery announce", RNS.LOG_ERROR)
return None return None
if not (is_ip_address(reachable_on) or is_hostname(reachable_on)):
RNS.log(f"The configured reachable_on parameter \"{reachable_on}\" for {interface} is not a valid IP address or hostname", RNS.LOG_ERROR)
RNS.log(f"Aborting discovery announce", RNS.LOG_ERROR)
return None
if interface_type in ["BackboneInterface", "TCPServerInterface"]: if interface_type in ["BackboneInterface", "TCPServerInterface"]:
info[REACHABLE_ON] = reachable_on info[REACHABLE_ON] = reachable_on
info[PORT] = interface.bind_port info[PORT] = interface.bind_port
@@ -233,6 +242,10 @@ class InterfaceAnnounceHandler:
"longitude": unpacked[LONGITUDE], "longitude": unpacked[LONGITUDE],
"height": unpacked[HEIGHT]} "height": unpacked[HEIGHT]}
if REACHABLE_ON in unpacked:
if not (is_ip_address(unpacked[REACHABLE_ON]) or is_hostname(unpacked[REACHABLE_ON])):
raise ValueError("Invalid data in reachable_on field of announce")
if IFAC_NETNAME in unpacked: info["ifac_netname"] = unpacked[IFAC_NETNAME] if IFAC_NETNAME in unpacked: info["ifac_netname"] = unpacked[IFAC_NETNAME]
if IFAC_NETKEY in unpacked: info["ifac_netkey"] = unpacked[IFAC_NETKEY] if IFAC_NETKEY in unpacked: info["ifac_netkey"] = unpacked[IFAC_NETKEY]
@@ -319,7 +332,7 @@ class InterfaceAnnounceHandler:
if self.callback and callable(self.callback): self.callback(info) if self.callback and callable(self.callback): self.callback(info)
except Exception as e: except Exception as e:
RNS.log(f"An error occurred while trying to decode discovered interface. The contained exception was: {e}", RNS.LOG_ERROR) RNS.log(f"An error occurred while trying to decode discovered interface. The contained exception was: {e}", RNS.LOG_DEBUG)
class InterfaceDiscovery(): class InterfaceDiscovery():
THRESHOLD_UNKNOWN = 24*60*60 THRESHOLD_UNKNOWN = 24*60*60
@@ -670,3 +683,17 @@ class BlackholeUpdater():
RNS.trace_exception(e) RNS.trace_exception(e)
time.sleep(self.job_interval) time.sleep(self.job_interval)
def is_ip_address(address_string):
try:
ipaddress.ip_address(address_string)
return True
except: return False
def is_hostname(hostname):
if hostname[-1] == ".": hostname = hostname[:-1]
if len(hostname) > 253: return False
components = hostname.split(".")
if re.match(r"[0-9]+$", components[-1]): return False
allowed = re.compile(r"(?!-)[a-z0-9-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(label) for label in components)

View File

@@ -239,7 +239,8 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
if "sf" in i: print(f"Sprd. Factor : {i['sf']}") if "sf" in i: print(f"Sprd. Factor : {i['sf']}")
if "cr" in i: print(f"Coding Rate : {i['cr']}") if "cr" in i: print(f"Coding Rate : {i['cr']}")
if "modulation" in i: print(f"Modulation : {i['modulation']}") if "modulation" in i: print(f"Modulation : {i['modulation']}")
if "reachable_on" in i: print(f"Address : {i['reachable_on']}:{i['port']}") if "reachable_on" in i: print(f"Address : {i['reachable_on']}")
if "reachable_on" in i: print(f"Port : {i['port']}")
print(f"Stamp Value : {i['value']}") print(f"Stamp Value : {i['value']}")