rnsd.py
1 #!/usr/bin/env python3 2 3 # Reticulum License 4 # 5 # Copyright (c) 2016-2025 Mark Qvist 6 # 7 # Permission is hereby granted, free of charge, to any person obtaining a copy 8 # of this software and associated documentation files (the "Software"), to deal 9 # in the Software without restriction, including without limitation the rights 10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 # copies of the Software, and to permit persons to whom the Software is 12 # furnished to do so, subject to the following conditions: 13 # 14 # - The Software shall not be used in any kind of system which includes amongst 15 # its functions the ability to purposefully do harm to human beings. 16 # 17 # - The Software shall not be used, directly or indirectly, in the creation of 18 # an artificial intelligence, machine learning or language model training 19 # dataset, including but not limited to any use that contributes to the 20 # training or development of such a model or algorithm. 21 # 22 # - The above copyright notice and this permission notice shall be included in 23 # all copies or substantial portions of the Software. 24 # 25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 # SOFTWARE. 32 33 import RNS 34 import argparse 35 import time 36 37 from RNS._version import __version__ 38 39 40 def program_setup(configdir, verbosity = 0, quietness = 0, service = False, interactive=False): 41 targetverbosity = verbosity-quietness 42 43 if service: 44 targetlogdest = RNS.LOG_FILE 45 targetverbosity = None 46 else: 47 targetlogdest = RNS.LOG_STDOUT 48 49 reticulum = RNS.Reticulum(configdir=configdir, verbosity=targetverbosity, logdest=targetlogdest) 50 if reticulum.is_connected_to_shared_instance: 51 RNS.log("Started rnsd version {version} connected to another shared local instance, this is probably NOT what you want!".format(version=__version__), RNS.LOG_WARNING) 52 else: 53 # TODO: Rethink why this was added 54 # if RNS.Reticulum.get_instance().shared_instance_interface: 55 # RNS.Reticulum.get_instance().shared_instance_interface.server.daemon_threads = True 56 RNS.log("Started rnsd version {version}".format(version=__version__), RNS.LOG_NOTICE) 57 58 if interactive: import code; code.interact(local=globals()) 59 else: 60 while True: time.sleep(1) 61 62 def main(): 63 try: 64 parser = argparse.ArgumentParser(description="Reticulum Network Stack Daemon") 65 parser.add_argument("--config", action="store", default=None, help="path to alternative Reticulum config directory", type=str) 66 parser.add_argument('-v', '--verbose', action='count', default=0) 67 parser.add_argument('-q', '--quiet', action='count', default=0) 68 parser.add_argument('-s', '--service', action='store_true', default=False, help="rnsd is running as a service and should log to file") 69 parser.add_argument('-i', '--interactive', action='store_true', default=False, help="drop into interactive shell after initialisation") 70 parser.add_argument("--exampleconfig", action='store_true', default=False, help="print verbose configuration example to stdout and exit") 71 parser.add_argument("--version", action="version", version="rnsd {version}".format(version=__version__)) 72 73 args = parser.parse_args() 74 75 if args.exampleconfig: 76 print(__example_rns_config__) 77 exit() 78 79 if args.config: 80 configarg = args.config 81 else: 82 configarg = None 83 84 program_setup(configdir = configarg, verbosity=args.verbose, quietness=args.quiet, service=args.service, interactive=args.interactive) 85 86 except KeyboardInterrupt: 87 print("") 88 exit() 89 90 __example_rns_config__ = '''# This is an example Reticulum config file. 91 # You should probably edit it to include any additional, 92 # interfaces and settings you might need. 93 94 [reticulum] 95 96 # If you enable Transport, your system will route traffic 97 # for other peers, pass announces and serve path requests. 98 # This should be done for systems that are suited to act 99 # as transport nodes, ie. if they are stationary and 100 # always-on. This directive is optional and can be removed 101 # for brevity. 102 103 enable_transport = No 104 105 106 # By default, the first program to launch the Reticulum 107 # Network Stack will create a shared instance, that other 108 # programs can communicate with. Only the shared instance 109 # opens all the configured interfaces directly, and other 110 # local programs communicate with the shared instance over 111 # a local socket. This is completely transparent to the 112 # user, and should generally be turned on. This directive 113 # is optional and can be removed for brevity. 114 115 share_instance = Yes 116 117 118 # If you want to run multiple *different* shared instances 119 # on the same system, you will need to specify different 120 # instance names for each. On platforms supporting domain 121 # sockets, this can be done with the instance_name option: 122 123 instance_name = default 124 125 # Some platforms don't support domain sockets, and if that 126 # is the case, you can isolate different instances by 127 # specifying a unique set of ports for each: 128 129 # shared_instance_port = 37428 130 # instance_control_port = 37429 131 132 133 # If you want to explicitly use TCP for shared instance 134 # communication, instead of domain sockets, this is also 135 # possible, by using the following option: 136 137 # shared_instance_type = tcp 138 139 140 # On systems where running instances may not have access 141 # to the same shared Reticulum configuration directory, 142 # it is still possible to allow full interactivity for 143 # running instances, by manually specifying a shared RPC 144 # key. In almost all cases, this option is not needed, but 145 # it can be useful on operating systems such as Android. 146 # The key must be specified as bytes in hexadecimal. 147 148 # rpc_key = e5c032d3ec4e64a6aca9927ba8ab73336780f6d71790 149 150 151 # It is possible to allow remote management of Reticulum 152 # systems using the various built-in utilities, such as 153 # rnstatus and rnpath. You will need to specify one or 154 # more Reticulum Identity hashes for authenticating the 155 # queries from client programs. For this purpose, you can 156 # use existing identity files, or generate new ones with 157 # the rnid utility. 158 159 # enable_remote_management = yes 160 # remote_management_allowed = 9fb6d773498fb3feda407ed8ef2c3229, 2d882c5586e548d79b5af27bca1776dc 161 162 163 # For easier management, discovery and configuration of 164 # networks with many individual transport instances, 165 # you can specify a network identity to be used across 166 # a set of instances. If sending interface discovery 167 # announces, these will all be signed by the specified 168 # network identity, and other nodes discovering your 169 # interfaces will be able to identify that they belong 170 # to the same network, even though they exist on different 171 # transport nodes. 172 173 # network_identity = ~/.reticulum/storage/identity/network 174 175 176 # You can configure whether Reticulum should discover 177 # available interfaces from other Transport Instances over 178 # the network. If this option is enabled, Reticulum will 179 # collect interface information discovered from the network. 180 181 # discover_interfaces = No 182 183 184 # If you only want to discover interfaces from specific 185 # networks, you can provide a list of network identities 186 # from which to discover interfaces. If this option is not 187 # provided, interfaces will be discovered from all transport 188 # instances on all connected networks. 189 190 # interface_discovery_sources = 78616ff7c4b8d3886d67d494b440f333, cb127015e13aa6ea1e0a606cdc9123d0 191 192 193 # It is possible to automatically bring up and connect new 194 # interfaces discovered over the network. This option is 195 # disabled by default, but allows you to specify a maximum 196 # number of discovered interfaces to automatically connect. 197 # Additionally, if this option is enabled, Reticulum will 198 # also try to autoconnect available auto-discovered inter- 199 # faces on startup, up to the maximum number specified. 200 201 # autoconnect_discovered_interfaces = 0 202 203 204 # To prevent interface discovery spamming, a valid crypto- 205 # graphic stamp is required per announced interface. You 206 # can configure the minimum required value to accept as 207 # valid for discovered interfaces. 208 209 # required_discovery_value = 14 210 211 212 # You can configure Reticulum to panic and forcibly close 213 # if an unrecoverable interface error occurs, such as the 214 # hardware device for an interface disappearing. This is 215 # an optional directive, and can be left out for brevity. 216 # This behaviour is disabled by default. 217 218 # panic_on_interface_error = No 219 220 221 # When Transport is enabled, it is possible to allow the 222 # Transport Instance to respond to probe requests from 223 # the rnprobe utility. This can be a useful tool to test 224 # connectivity. When this option is enabled, the probe 225 # destination will be generated from the Identity of the 226 # Transport Instance, and printed to the log at startup. 227 # Optional, and disabled by default. 228 229 # respond_to_probes = No 230 231 232 # You can publish your local list of blackholed identities 233 # for other transport instances to use for automatic, 234 # network-wide blackhole management. 235 236 # publish_blackhole = No 237 238 # List of remote transport identities from which to auto- 239 # matically source lists of blackholed identities. 240 # 241 # If you're connecting to a large external network, you 242 # can use one or more external blackhole list to block 243 # spammy and excessive announces onto your network. This 244 # funtionality is especially useful if you're hosting public 245 # entrypoints or gateways. The list source below provides a 246 # functional example, but better, more timely maintained 247 # lists probably exist in the community. 248 249 # blackhole_sources = 521c87a83afb8f29e4455e77930b973b 250 251 252 [logging] 253 # Valid log levels are 0 through 7: 254 # 0: Log only critical information 255 # 1: Log errors and lower log levels 256 # 2: Log warnings and lower log levels 257 # 3: Log notices and lower log levels 258 # 4: Log info and lower (this is the default) 259 # 5: Verbose logging 260 # 6: Debug logging 261 # 7: Extreme logging 262 263 loglevel = 4 264 265 266 # The interfaces section defines the physical and virtual 267 # interfaces Reticulum will use to communicate on. This 268 # section will contain examples for a variety of interface 269 # types. You can modify these or use them as a basis for 270 # your own config, or simply remove the unused ones. 271 272 [interfaces] 273 274 # This interface enables communication with other 275 # link-local Reticulum nodes over UDP. It does not 276 # need any functional IP infrastructure like routers 277 # or DHCP servers, but will require that at least link- 278 # local IPv6 is enabled in your operating system, which 279 # should be enabled by default in almost any OS. See 280 # the Reticulum Manual for more configuration options. 281 282 [[Default Interface]] 283 type = AutoInterface 284 enabled = yes 285 286 287 # The following example enables communication with other 288 # local Reticulum peers using UDP broadcasts. 289 290 [[UDP Interface]] 291 type = UDPInterface 292 enabled = no 293 listen_ip = 0.0.0.0 294 listen_port = 4242 295 forward_ip = 255.255.255.255 296 forward_port = 4242 297 298 # The above configuration will allow communication 299 # within the local broadcast domains of all local 300 # IP interfaces. 301 302 # Instead of specifying listen_ip, listen_port, 303 # forward_ip and forward_port, you can also bind 304 # to a specific network device like below. 305 306 # device = eth0 307 # port = 4242 308 309 # Assuming the eth0 device has the address 310 # 10.55.0.72/24, the above configuration would 311 # be equivalent to the following manual setup. 312 # Note that we are both listening and forwarding to 313 # the broadcast address of the network segments. 314 315 # listen_ip = 10.55.0.255 316 # listen_port = 4242 317 # forward_ip = 10.55.0.255 318 # forward_port = 4242 319 320 # You can of course also communicate only with 321 # a single IP address 322 323 # listen_ip = 10.55.0.15 324 # listen_port = 4242 325 # forward_ip = 10.55.0.16 326 # forward_port = 4242 327 328 329 # This example demonstrates a TCP server interface. 330 # It will listen for incoming connections on the 331 # specified IP address and port number. 332 333 [[TCP Server Interface]] 334 type = TCPServerInterface 335 enabled = no 336 337 # This configuration will listen on all IP 338 # interfaces on port 4242 339 340 listen_ip = 0.0.0.0 341 listen_port = 4242 342 343 # Alternatively you can bind to a specific IP 344 345 # listen_ip = 10.0.0.88 346 # listen_port = 4242 347 348 # Or a specific network device 349 350 # device = eth0 351 # port = 4242 352 353 354 # To connect to a TCP server interface, you would 355 # naturally use the TCP client interface. Here's 356 # an example. The target_host can either be an IP 357 # address or a hostname 358 359 [[TCP Client Interface]] 360 type = TCPClientInterface 361 enabled = no 362 target_host = 127.0.0.1 363 target_port = 4242 364 365 366 # This example shows how to make your Reticulum 367 # instance available over I2P, and connect to 368 # another I2P peer. Please be aware that you 369 # must have an I2P router running on your system 370 # with the SAMv3 API enabled for this to work. 371 372 [[I2P]] 373 type = I2PInterface 374 enabled = no 375 connectable = yes 376 peers = ykzlw5ujbaqc2xkec4cpvgyxj257wcrmmgkuxqmqcur7cq3w3lha.b32.i2p 377 378 379 # Here's an example of how to add a LoRa interface 380 # using the RNode LoRa transceiver. 381 382 [[RNode LoRa Interface]] 383 type = RNodeInterface 384 385 # Enable interface if you want use it! 386 enabled = no 387 388 # Serial port for the device 389 port = /dev/ttyUSB0 390 391 # It is also possible to use BLE devices 392 # instead of wired serial ports. The 393 # target RNode must be paired with the 394 # host device before connecting. BLE 395 # devices can be connected by name, 396 # BLE MAC address or by any available. 397 398 # Connect to specific device by name 399 # port = ble://RNode 3B87 400 401 # Or by BLE MAC address 402 # port = ble://F4:12:73:29:4E:89 403 404 # Or connect to the first available, 405 # paired device 406 # port = ble:// 407 408 # Set frequency to 867.2 MHz 409 frequency = 867200000 410 411 # Set LoRa bandwidth to 125 KHz 412 bandwidth = 125000 413 414 # Set TX power to 7 dBm (5 mW) 415 txpower = 7 416 417 # Select spreading factor 8. Valid 418 # range is 7 through 12, with 7 419 # being the fastest and 12 having 420 # the longest range. 421 spreadingfactor = 8 422 423 # Select coding rate 5. Valid range 424 # is 5 throough 8, with 5 being the 425 # fastest, and 8 the longest range. 426 codingrate = 5 427 428 # You can configure the RNode to send 429 # out identification on the channel with 430 # a set interval by configuring the 431 # following two parameters. The trans- 432 # ceiver will only ID if the set 433 # interval has elapsed since it's last 434 # actual transmission. The interval is 435 # configured in seconds. 436 # This option is commented out and not 437 # used by default. 438 # id_callsign = MYCALL-0 439 # id_interval = 600 440 441 # For certain homebrew RNode interfaces 442 # with low amounts of RAM, using packet 443 # flow control can be useful. By default 444 # it is disabled. 445 flow_control = False 446 447 448 # An example KISS modem interface. Useful for running 449 # Reticulum over packet radio hardware. 450 451 [[Packet Radio KISS Interface]] 452 type = KISSInterface 453 454 # Enable interface if you want use it! 455 enabled = no 456 457 # Serial port for the device 458 port = /dev/ttyUSB1 459 460 # Set the serial baud-rate and other 461 # configuration parameters. 462 speed = 115200 463 databits = 8 464 parity = none 465 stopbits = 1 466 467 # Set the modem preamble. A 150ms 468 # preamble should be a reasonable 469 # default, but may need to be 470 # increased for radios with slow- 471 # opening squelch and long TX/RX 472 # turnaround 473 preamble = 150 474 475 # Set the modem TX tail. In most 476 # cases this should be kept as low 477 # as possible to not waste airtime. 478 txtail = 10 479 480 # Configure CDMA parameters. These 481 # settings are reasonable defaults. 482 persistence = 200 483 slottime = 20 484 485 # You can configure the interface to send 486 # out identification on the channel with 487 # a set interval by configuring the 488 # following two parameters. The KISS 489 # interface will only ID if the set 490 # interval has elapsed since it's last 491 # actual transmission. The interval is 492 # configured in seconds. 493 # This option is commented out and not 494 # used by default. 495 # id_callsign = MYCALL-0 496 # id_interval = 600 497 498 # Whether to use KISS flow-control. 499 # This is useful for modems that have 500 # a small internal packet buffer, but 501 # support packet flow control instead. 502 flow_control = false 503 504 505 # If you're using Reticulum on amateur radio spectrum, 506 # you might want to use the AX.25 KISS interface. This 507 # way, Reticulum will automatically encapsulate it's 508 # traffic in AX.25 and also identify your stations 509 # transmissions with your callsign and SSID. 510 # 511 # Only do this if you really need to! Reticulum doesn't 512 # need the AX.25 layer for anything, and it incurs extra 513 # overhead on every packet to encapsulate in AX.25. 514 # 515 # A more efficient way is to use the plain KISS interface 516 # with the beaconing functionality described above. 517 518 [[Packet Radio AX.25 KISS Interface]] 519 type = AX25KISSInterface 520 521 # Set the station callsign and SSID 522 callsign = NO1CLL 523 ssid = 0 524 525 # Enable interface if you want use it! 526 enabled = no 527 528 # Serial port for the device 529 port = /dev/ttyUSB2 530 531 # Set the serial baud-rate and other 532 # configuration parameters. 533 speed = 115200 534 databits = 8 535 parity = none 536 stopbits = 1 537 538 # Whether to use KISS flow-control. 539 # This is useful for modems with a 540 # small internal packet buffer. 541 flow_control = false 542 543 # Set the modem preamble. A 150ms 544 # preamble should be a reasonable 545 # default, but may need to be 546 # increased for radios with slow- 547 # opening squelch and long TX/RX 548 # turnaround 549 preamble = 150 550 551 # Set the modem TX tail. In most 552 # cases this should be kept as low 553 # as possible to not waste airtime. 554 txtail = 10 555 556 # Configure CDMA parameters. These 557 # settings are reasonable defaults. 558 persistence = 200 559 slottime = 20 560 561 ''' 562 563 if __name__ == "__main__": 564 main()