diff --git a/README.md b/README.md index 2b2dbe6..f592d57 100644 --- a/README.md +++ b/README.md @@ -15,20 +15,20 @@ West Bengal. ## Requirements -- systemd v248 or more (for batman support) +- systemd{,-networkd} v248 or more (for batman support) - Linux kernel with batman-adv module (if `modinfo batman-adv` shows no error then you already have it) - iwd (for starting ad-hoc network) @@ -36,17 +36,22 @@ advocating the constitutional rights). - [python-dasbus][] - wifi adapter with ad-hoc support - two or more computers with wifi adapter +- systemd-resolved (optional, for DNS) +- batctl (optional, for debugging) ## Installing ### Arch Linux -Install [naxalnet-git][] from the AUR: +Install [naxalnet-git][] from the AUR with your favourite helper: ```sh yay -S naxalnet-git ``` +Optionally, [setup systemd-resolved][arch-resolved] if any of the +computers have internet access. + ### Manually Clone the repo and cd into it. @@ -61,15 +66,41 @@ without rebooting: sudo systemctl daemon-reload ``` -## Running the program +## How to use You need more than one computer running for the connection to work. -Start the naxalnet service: + +### Communicate between peers + +Connect a wifi adapter to all the computers you intend to run +naxalnet. +Start the naxalnet service on all of them: ```sh sudo systemctl start naxalnet.service ``` +To test if it works, run `ip addr` to find out your address. +Note the `inet` or `inet6` address of `bridge0`. Ping the address +from another computer (example: `ping 169.254.62.90`) to find out +if it is online. Press Ctrl-C to stop. + +### Getting internet access + +Connect an ethernet to any of the peers and start naxalnet. +Now all the peers should be able to connect after renewing +their DHCP connection (`sudo networkctl renew bridge0`). + +### Tethering via WiFi AP + +Connect two wifi adapters on a device and start naxalnet. +Now an ap will be created on one of the devices with +SSID `NaxalNet` and password `naxalnet256`. +If you had set up internet access on one of the peers, internet +can be accessed from the AP. + +### Running at boot + Starting the service will stop `NetworkManager.service` and `wpa_supplicant.service` if it is running. If you start either of these services after naxalnet is started, systemd will stop naxalnet. @@ -125,3 +156,4 @@ This project is in alpha stage. Documentation is incomplete. [ssb]: https://scuttlebutt.nz [python-dasbus]: https://github.com/rhinstaller/dasbus [naxalnet-git]: https://aur.archlinux.org/packages/naxalnet-git +[arch-resolved]: https://wiki.archlinux.org/title/Systemd-resolved#DNS diff --git a/naxalnet b/naxalnet index 124a1bc..57d6f49 100755 --- a/naxalnet +++ b/naxalnet @@ -22,7 +22,6 @@ with systemd-networkd and iwd import sys -import time from pathlib import Path from shutil import copy from dasbus.connection import SystemMessageBus @@ -30,12 +29,13 @@ from dasbus.error import DBusError NETWORKD_CONFIGS = "/usr/share/naxalnet/networkd" NETWORKD_VOLATILE_DIR = "/run/systemd/network" -RESOLVED_STUB_RESOLVE = "/run/systemd/resolve/stub-resolv.conf" -RESOLV_CONF = "/etc/resolv.conf" ADHOC_SSID = "HelloWorld" - +AP_SSID = "NaxalNet" +AP_PASSWD = "naxalnet256" # Copy networkd configs to volatile dir. -# See man:systemd.networkm(5) +# The D-Bus API does not support creating new interfaces +# or linking to bridges. So we use config files. +# See man:systemd.network(5) try: print("Copying network config files") dest = Path(NETWORKD_VOLATILE_DIR) @@ -51,36 +51,6 @@ except PermissionError as error: print(error) sys.exit("Make sure you are root") - -# Symlink resolvd.conf to systemd's stub-resolvd.conf -# This is needed for DNS resolution to work. -# see https://wiki.archlinux.org/title/Systemd-resolved#DNS -try: - print("Checking resolv.conf") - r = Path(RESOLV_CONF) - if r.is_symlink(): - # Naxalnet will be started before resolved, so the destination - # is unlikely to exist at the time - # If r is linked to resolved's resolv.conf, dont change it - if r.samefile(RESOLVED_STUB_RESOLVE): - print(r, "is already linked to stub-resolv.conf. Not changing") - # Else if the destination exists - elif r.exists(): - print(r, "is a symlink that exists. Not removing") - else: - print(r, "is a symlink to a destination that doesn't exist. Removing") - r.unlink() - elif r.exists(): - print(r, "is not a symlink") - x = r.rename(RESOLV_CONF + ".naxalnet-bkp") - print(r, "was moved to", x) - print("Linking resolv.conf") - r.symlink_to(RESOLVED_STUB_RESOLVE) -except PermissionError as error: - print(error) - sys.exit("An error occured while linking resolv.conf") - - # Now, the iwd part try: # connect to the System bus @@ -90,47 +60,75 @@ try: # Get list of all devices print("Finding connected devices") objects = iwd.GetManagedObjects() - devices = [] - for name, obj in objects.items(): + # devices that support ad-hoc + adhoc_devices = [] + # devices that support ap + ap_devices = [] + for path, obj in objects.items(): if "net.connman.iwd.Device" in obj: # add all devices to the list - print("Found device:", obj["net.connman.iwd.Device"]["Name"]) - devices.append(name) + name = obj["net.connman.iwd.Device"]["Name"] + print("Found device", name) + adapter_path = obj["net.connman.iwd.Device"]["Adapter"].get_string() + adapter = objects[adapter_path]["net.connman.iwd.Adapter"] + if "ad-hoc" in adapter["SupportedModes"]: + print(name, "supports ad-hoc") + adhoc_devices.append(path) + if "ap" in adapter["SupportedModes"]: + print(name, "supports ap") + ap_devices.append(path) - # Start ad-hoc on first device - devpath = devices.pop() - print("Working on first device", devpath) - dev1 = bus.get_proxy("net.connman.iwd", devpath) - if not dev1.Powered: - print("Device is off. Turning on") - dev1.Powered = True - if dev1.Mode != "ad-hoc": - print("Device is in", dev1.Mode) - print("Switching to ad-hoc") - dev1.Mode = "ad-hoc" - # Changing Mode requires connecting to the proxy again - dev1 = bus.get_proxy("net.connman.iwd", devpath) - print("Starting ad-hoc network") - dev1.StartOpen(ADHOC_SSID) - # TODO: If there is a second device, start AP - # in it + if len(adhoc_devices) != 0: + # Start ad-hoc on first device supporting ad-hoc + dev1path = adhoc_devices.pop() + # The same device is likely to have ap support too. + # But we can't start ad-hoc and ap on the same interface. + # Remove dev1 from ap_devices if it exists there + if dev1path in ap_devices: + ap_devices.remove(dev1path) + print("Working on ad-hoc") + dev1 = bus.get_proxy("net.connman.iwd", dev1path) + print("Starting ad-hoc on", dev1.Name) + if not dev1.Powered: + print("Device is off. Turning on") + dev1.Powered = True + if dev1.Mode != "ad-hoc": + print("Device is in", dev1.Mode) + print("Switching to ad-hoc") + dev1.Mode = "ad-hoc" + # Changing Mode needs connecting to the proxy again + dev1 = bus.get_proxy("net.connman.iwd", dev1path) + # If already connected to ad-hoc, stop it + if dev1.Started is True: + print("Already connected to ad-hoc. Stopping") + dev1.Stop() + # Reconnect to proxy or StartOpen won't work + dev1 = bus.get_proxy("net.connman.iwd", dev1path) + print("Starting ad-hoc network") + dev1.StartOpen(ADHOC_SSID) + + # Start Access point if ap_device is not empty, + # ie, we have more devices + if len(ap_devices) != 0: + print("Working on AP") + dev2path = ap_devices.pop() + dev2 = bus.get_proxy("net.connman.iwd", dev2path) + if not dev1.Powered: + print("Device is off. Turning on") + dev1.Powered = True + if dev2.Mode != "ap": + print(dev2.Name, "is in", dev2.Mode) + print("Switching to ap") + dev2.Mode = "ap" + dev2 = bus.get_proxy("net.connman.iwd", dev2path) + if dev2.Started is True: + print("An AP is already started on", dev2.Name) + print("Stopping") + dev2.Stop() + dev2 = bus.get_proxy("net.connman.iwd", dev2path) + print("Starting AP on", dev2.Name) + dev2.Start(AP_SSID, AP_PASSWD) except DBusError: sys.exit("An error occured while communicating with iwd") -# Sleep my little baby-oh -# Sleep until you waken -# When you wake you'll see the world -# If I'm not mistaken... -# -# Kiss a lover -# Dance a measure, -# Find your name -# And buried treasure... -# -# Face your life -# Its pain, -# Its pleasure, -# Leave no path untaken. -# -# -- Neil Gaiman, The Graveyard Book print("Bye") diff --git a/naxalnet.service b/naxalnet.service index 19a6182..1f7880f 100644 --- a/naxalnet.service +++ b/naxalnet.service @@ -15,9 +15,12 @@ After=wpa_supplicant.service [Service] Type=oneshot RemainAfterExit=yes -# Temporary (maybe permanent) fix to aborting after changing to ad-hoc Restart=on-failure RestartSec=5sec +# IWD takes some time to find devices. +# Without the sleep 5, naxalnet could not detect the second +# device while testing. +ExecStartPre=/usr/bin/sleep 5 ExecStart=/usr/bin/naxalnet [Install]