Compare commits
29 Commits
Author | SHA1 | Date |
---|---|---|
Pranav Jerry | 5068250ad6 | |
Pranav Jerry | 19137faab3 | |
Pranav Jerry | b3710633cc | |
Pranav Jerry | 86042b9852 | |
Pranav Jerry | 1500f486ef | |
Pranav Jerry | 9c6081ea87 | |
Pranav Jerry | c8e98b2c4f | |
Pranav Jerry | adb8c62407 | |
Pranav Jerry | e0d2602552 | |
Pranav Jerry | c2fba89816 | |
Pranav Jerry | b2f30bad62 | |
Pranav Jerry | af5fc0e285 | |
Pranav Jerry | f0689016ce | |
Pranav Jerry | b9592696f2 | |
Pranav Jerry | 809c09afe0 | |
Pranav Jerry | 3c22fa63f4 | |
Pranav Jerry | 91be0b0189 | |
Pranav Jerry | b1d970a0f6 | |
Pranav Jerry | 7b7c3f0b2e | |
Pranav Jerry | 8bf05ba334 | |
Pranav Jerry | 0e7a69be53 | |
Pranav Jerry | d4e6b929d2 | |
Pranav Jerry | e4fd0ff04d | |
Pranav Jerry | f4a490210d | |
Pranav Jerry | ba2425f008 | |
Pranav Jerry | 8bdeddf08e | |
Pranav Jerry | d57c92588f | |
Pranav Jerry | 47f2324604 | |
Pranav Jerry | af98a57b0e |
|
@ -0,0 +1,10 @@
|
|||
.DS_Store
|
||||
.idea
|
||||
*.log
|
||||
tmp/
|
||||
|
||||
*.py[cod]
|
||||
*.egg*
|
||||
build
|
||||
htmlcov
|
||||
__pycache__
|
|
@ -0,0 +1,23 @@
|
|||
# Hacking
|
||||
|
||||
Everyone <!-- including anti-nationals and urban naxals are -->
|
||||
is welcome to [hack][] naxalnet. See below for how to hack.
|
||||
|
||||
## Reporting issues and suggesting ideas
|
||||
|
||||
To report a bug or suggest an idea, create a new issue at
|
||||
<https://git.disroot.org/pranav/naxalnet/issues> with a
|
||||
relevant label.
|
||||
|
||||
## Contribute code
|
||||
|
||||
To push to this repo, you need your username to be in the
|
||||
contributors list. See issue #8.
|
||||
|
||||
## Packaging
|
||||
|
||||
naxalnet needs distro packages in Debian, Fedora, openSUSE,
|
||||
and nixos. If you know/like to package it in your distro,
|
||||
post to issue #6.
|
||||
|
||||
[hack]: https://catb.org/jargon/html/H/hack.html
|
|
@ -0,0 +1,4 @@
|
|||
include LICENSE
|
||||
include README.md
|
||||
include naxalnet.service
|
||||
include systemd-networkd/*
|
23
Makefile
23
Makefile
|
@ -1,16 +1,11 @@
|
|||
PREFIX := /usr
|
||||
# This makefile uses setup.py under the hood
|
||||
all: build
|
||||
|
||||
install: naxalnet
|
||||
install -d $(DESTDIR)$(PREFIX)/bin
|
||||
install -d $(DESTDIR)$(PREFIX)/lib/systemd/system/
|
||||
install -m644 naxalnet.service $(DESTDIR)$(PREFIX)/lib/systemd/system/
|
||||
install naxalnet $(DESTDIR)$(PREFIX)/bin/
|
||||
install -d $(DESTDIR)$(PREFIX)/share/naxalnet/networkd
|
||||
install -m644 systemd-networkd/* $(DESTDIR)$(PREFIX)/share/naxalnet/networkd
|
||||
build:
|
||||
python setup.py build
|
||||
|
||||
testdeps:
|
||||
@for i in networkctl systemctl python3; do \
|
||||
echo "Checking for $$i"; \
|
||||
which $$i > /dev/null && echo " $$i found" || \
|
||||
(echo " $$i not found"; exit 1); \
|
||||
done
|
||||
install: build
|
||||
python setup.py install --root="$(DESTDIR)/" --optimize=1 --skip-build
|
||||
|
||||
clean:
|
||||
rm -rf build naxalnet.egg-info
|
||||
|
|
63
README.md
63
README.md
|
@ -33,6 +33,7 @@ or anyone else advocating for their rights).
|
|||
no error then you already have it)
|
||||
- iwd (for starting ad-hoc network)
|
||||
- python3
|
||||
- python-setuptools (for building)
|
||||
- [python-dasbus][]
|
||||
- wifi adapter with ad-hoc support
|
||||
- two or more computers with wifi adapter, called nodes
|
||||
|
@ -43,10 +44,11 @@ or anyone else advocating for their rights).
|
|||
|
||||
### Arch Linux
|
||||
|
||||
Install [naxalnet-git][] from the AUR with your favourite helper:
|
||||
Install [naxalnet][aur] (or [naxalnet-git][aur-devel] for the
|
||||
development version) from the AUR with your favourite helper:
|
||||
|
||||
```sh
|
||||
yay -S naxalnet-git
|
||||
yay -S naxalnet
|
||||
```
|
||||
|
||||
Optionally, [setup systemd-resolved][arch-resolved] for DNS if any
|
||||
|
@ -56,6 +58,17 @@ of the nodes have internet access.
|
|||
|
||||
Clone the repo and cd into it.
|
||||
|
||||
```sh
|
||||
git clone https://git.disroot.org/pranav/naxalnet.git
|
||||
cd naxalnet
|
||||
```
|
||||
|
||||
Or, if you have an [IPFS client][ipfs] running, try:
|
||||
|
||||
```sh
|
||||
git clone http://k51qzi5uqu5dlye74be0n9iihwk6sm54vexo7bf7pdr4w811y6mmrcp25djozv.ipns.localhost:8080/naxalnet.git
|
||||
```
|
||||
|
||||
Run `sudo make install` to install naxalnet. This will install naxalnet in
|
||||
`/usr/bin/naxalnet`.
|
||||
|
||||
|
@ -94,7 +107,7 @@ 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
|
||||
Now an ap will be created on one of the adapters 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.
|
||||
|
@ -118,28 +131,53 @@ Disable the service to stop running at boot:
|
|||
sudo systemctl disable naxalnet.service
|
||||
```
|
||||
|
||||
### Stopping the service
|
||||
|
||||
```sh
|
||||
# Stop the services
|
||||
sudo systemctl stop naxalnet systemd-networkd systemd-resolved iwd
|
||||
# Delete the virtual interfaces created by naxalnet
|
||||
sudo networkctl delete bat0 bridge0
|
||||
```
|
||||
|
||||
If your distribution uses NetworkManager, starting `naxalnet.service`
|
||||
will have stopped it. Start NetworkManager again:
|
||||
|
||||
```sh
|
||||
sudo systemctl start NetworkManager.service
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
The program naxalnet copies predefined systemd-networkd configuration
|
||||
The program naxalnet copies some `systemd-networkd` configuration files
|
||||
into networkd's runtime configuration directory. It uses iwd to start
|
||||
an ad-hoc network named "HelloWorld". See the
|
||||
[systemd-networkd](systemd-networkd) directory
|
||||
to see how systemd-networkd configures the network. You can now use
|
||||
to see how systemd-networkd configures the network. You can use
|
||||
services like [IPFS][], [Jami][], [Secure Scuttlebutt][ssb]
|
||||
and others which can work without internet access.
|
||||
and others which can work on an intranet.
|
||||
|
||||
## Uninstalling
|
||||
|
||||
Currently there is now way to uninstall naxalnet than manually removing
|
||||
the files:
|
||||
If you installed naxalnet manually, there is no way to uninstall
|
||||
than manually removing the files:
|
||||
|
||||
```sh
|
||||
sudo rm -rf /usr/{bin,share}/naxalnet \
|
||||
/usr/lib/systemd/system/naxalnet.service
|
||||
sudo pip uninstall naxalnet
|
||||
sudo rm -rf /usr/share/naxalnet* /usr/lib/systemd/system/naxalnet.service
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
See [HACKING.md](HACKING.md)
|
||||
|
||||
## Similar projects
|
||||
|
||||
The following projects are similar to naxalnet, but are not designed
|
||||
to be used in a laptop or computer with wifi adapter. If you live in
|
||||
an area where the materials required for any of them are easily
|
||||
available, consider using them instead of naxalnet.
|
||||
|
||||
- [LibreMesh][libremesh]: framework for OpenWrt-based
|
||||
firmwares
|
||||
- [disaster.radio][]: solar-powered communications network
|
||||
|
@ -154,14 +192,13 @@ the Free Software Foundation, either version 3 of the License, or
|
|||
See [LICENSE](LICENSE) for the complete version of the
|
||||
license.
|
||||
|
||||
This project is in alpha stage. Documentation is incomplete.
|
||||
|
||||
[batman-adv]: https://www.open-mesh.org/projects/batman-adv/wiki
|
||||
[ipfs]: https://ipfs.io
|
||||
[jami]: https://jami.net
|
||||
[ssb]: https://scuttlebutt.nz
|
||||
[python-dasbus]: https://github.com/rhinstaller/dasbus
|
||||
[naxalnet-git]: https://aur.archlinux.org/packages/naxalnet-git
|
||||
[aur]: https://aur.archlinux.org/packages/naxalnet
|
||||
[aur-devel]: https://aur.archlinux.org/packages/naxalnet-git
|
||||
[arch-resolved]: https://wiki.archlinux.org/title/Systemd-resolved#DNS
|
||||
[batman-systemd]: https://www.open-mesh.org/news/101
|
||||
[libremesh]: https://libremesh.org
|
||||
|
|
134
naxalnet
134
naxalnet
|
@ -1,134 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Setup a working BATMAN Advanced network
|
||||
with systemd-networkd and iwd
|
||||
"""
|
||||
|
||||
# Copyright (C) 2021 The Authors
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from shutil import copy
|
||||
from dasbus.connection import SystemMessageBus
|
||||
from dasbus.error import DBusError
|
||||
|
||||
NETWORKD_CONFIGS = "/usr/share/naxalnet/networkd"
|
||||
NETWORKD_VOLATILE_DIR = "/run/systemd/network"
|
||||
ADHOC_SSID = "HelloWorld"
|
||||
AP_SSID = "NaxalNet"
|
||||
AP_PASSWD = "naxalnet256"
|
||||
# Copy networkd configs to volatile dir.
|
||||
# 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)
|
||||
src = Path(NETWORKD_CONFIGS)
|
||||
|
||||
# Create the volatile directory if it doesn't exist
|
||||
dest.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Copy all files in src to dest
|
||||
for i in src.iterdir():
|
||||
copy(i, dest)
|
||||
except PermissionError as error:
|
||||
print(error)
|
||||
sys.exit("Make sure you are root")
|
||||
|
||||
# Now, the iwd part
|
||||
try:
|
||||
# connect to the System bus
|
||||
bus = SystemMessageBus()
|
||||
# iwd proxy
|
||||
iwd = bus.get_proxy("net.connman.iwd", "/")
|
||||
# Get list of all devices
|
||||
print("Finding connected devices")
|
||||
objects = iwd.GetManagedObjects()
|
||||
# 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
|
||||
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)
|
||||
|
||||
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")
|
||||
|
||||
print("Bye")
|
|
@ -1,11 +1,15 @@
|
|||
# naxalnet systemd service
|
||||
# See man:systemd.service(5) and man:systemd.unit(5)
|
||||
# before editing this file.
|
||||
[Unit]
|
||||
Description=Naxalnet
|
||||
Requires=systemd-networkd.service
|
||||
Requires=iwd.service
|
||||
Wants=systemd-resolved.service
|
||||
# naxalnet does not reload networkd, so networkd
|
||||
# should be started only afer naxalnet exits
|
||||
Before=systemd-networkd.service
|
||||
After=iwd.service
|
||||
|
||||
# Stops NetworkManager and wpa_supplicant if already running
|
||||
Conflicts=NetworkManager.service
|
||||
Conflicts=wpa_supplicant.service
|
||||
|
@ -16,11 +20,12 @@ After=wpa_supplicant.service
|
|||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
Restart=on-failure
|
||||
RestartSec=5sec
|
||||
# Probably not needed now
|
||||
RestartSec=2sec
|
||||
# IWD takes some time to find devices.
|
||||
# Without the sleep 5, naxalnet could not detect the second
|
||||
# Without the delay, naxalnet could not detect the second
|
||||
# device while testing.
|
||||
ExecStartPre=/usr/bin/sleep 5
|
||||
ExecStartPre=/usr/bin/sleep 2
|
||||
ExecStart=/usr/bin/naxalnet
|
||||
|
||||
[Install]
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2021 The naxalnet Authors
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
__version__ = "0.1.0a"
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2021 The naxalnet Authors
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from naxalnet.scripts import here_be_dragons
|
||||
|
||||
if __name__ == "__main__":
|
||||
here_be_dragons()
|
|
@ -0,0 +1,273 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2021 The naxalnet Authors
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
"""Manage wifi adapter via iwd D-Bus api"""
|
||||
|
||||
from dasbus.connection import SystemMessageBus
|
||||
|
||||
IWD_BUS = "net.connman.iwd"
|
||||
IWD_ROOT_PATH = "/"
|
||||
IWD_DEVICE_INTERFACE = "net.connman.iwd.Device"
|
||||
IWD_ADAPTER_INTERFACE = "net.connman.iwd.Adapter"
|
||||
|
||||
# If you are new to D-Bus, you might want to use a program
|
||||
# such as D-Feet (https://wiki.gnome.org/Apps/DFeet) for reference.
|
||||
# And try out iwctl to understand iwd's bus objects
|
||||
|
||||
|
||||
class IWD:
|
||||
"""Manage iwd via dbus"""
|
||||
|
||||
def __init__(self, bus=SystemMessageBus()):
|
||||
# self._bus and self._proxy are meant for use only in this file
|
||||
self._bus = bus
|
||||
self.reload()
|
||||
|
||||
def reload(self):
|
||||
"""reload the proxy"""
|
||||
self._proxy = self._bus.get_proxy(IWD_BUS, IWD_ROOT_PATH)
|
||||
|
||||
def get_name_from_path(self, path: str) -> str:
|
||||
"""
|
||||
returns device or adapter name when d-bus path is given as arg
|
||||
"""
|
||||
proxy = self._bus.get_proxy(IWD_BUS, path)
|
||||
return proxy.Name
|
||||
|
||||
def get_device_path_from_name(self, name: str) -> str:
|
||||
"""returns path of device as str"""
|
||||
device_paths = self.get_all_device_paths()
|
||||
for i in device_paths:
|
||||
proxy = self._bus.get_proxy(IWD_BUS, i)
|
||||
if proxy.Name == name:
|
||||
return i
|
||||
# If no devices were found, return None
|
||||
return None
|
||||
|
||||
def get_adapter_path_from_name(self, name: str) -> str:
|
||||
"""returns path of adapter as str"""
|
||||
adapter_paths = self.get_all_adapter_paths()
|
||||
for i in adapter_paths:
|
||||
proxy = self._bus.get_proxy(IWD_BUS, i)
|
||||
if proxy.Name == name:
|
||||
return i
|
||||
# If no adapters were found
|
||||
return None
|
||||
|
||||
def get_all_device_paths(self) -> list:
|
||||
"""returns list of paths of all devices"""
|
||||
objects = self._proxy.GetManagedObjects()
|
||||
paths = []
|
||||
for key, value in objects.items():
|
||||
# if value is a device, add its path to paths
|
||||
if IWD_DEVICE_INTERFACE in value:
|
||||
paths.append(key)
|
||||
return paths
|
||||
|
||||
def get_all_adapter_paths(self) -> list:
|
||||
"""returns list of paths of all adapters"""
|
||||
objects = self._proxy.GetManagedObjects()
|
||||
paths = []
|
||||
|
||||
for key, value in objects.items():
|
||||
# if value is an adapter, add its path to paths
|
||||
if IWD_ADAPTER_INTERFACE in value:
|
||||
paths.append(key)
|
||||
return paths
|
||||
|
||||
def get_devices(self) -> list:
|
||||
"""
|
||||
returns list of device names as str
|
||||
example: ["wlan0", "wlan1"]
|
||||
"""
|
||||
devices = []
|
||||
device_paths = self.get_all_device_paths()
|
||||
|
||||
for i in device_paths:
|
||||
name = self.get_name_from_path(i)
|
||||
devices.append(name)
|
||||
return devices
|
||||
|
||||
def get_adapters(self) -> list:
|
||||
"""
|
||||
returns list of adapters
|
||||
example: ["phy0","phy1"]
|
||||
"""
|
||||
adapters = []
|
||||
adapter_paths = self.get_all_adapter_paths()
|
||||
|
||||
for i in adapter_paths:
|
||||
name = self.get_name_from_path(i)
|
||||
adapters.append(name)
|
||||
return adapters
|
||||
|
||||
|
||||
class Device:
|
||||
"""
|
||||
control devices with iwd
|
||||
name: name of device (str)
|
||||
adapter: name of adapter (str)
|
||||
"""
|
||||
|
||||
def __init__(self, name: str, bus=SystemMessageBus()):
|
||||
self._iwd = IWD(bus)
|
||||
self._bus = self._iwd._bus
|
||||
self._path = self._iwd.get_device_path_from_name(name)
|
||||
self.reload()
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def is_powered_on(self) -> bool:
|
||||
"""returns True if devie is powered on"""
|
||||
return self._proxy.Powered
|
||||
|
||||
def power_on(self):
|
||||
"""Turn on the device and reload the proxy"""
|
||||
self._proxy.Powered = True
|
||||
self.reload()
|
||||
|
||||
def power_off(self):
|
||||
"""Turn off the device and reload the proxy"""
|
||||
self._proxy.Powered = False
|
||||
self.reload()
|
||||
|
||||
def reload(self):
|
||||
"""reload the proxy after changing mode"""
|
||||
self._proxy = self._bus.get_proxy(IWD_BUS, self._path)
|
||||
self.name = self._proxy.Name
|
||||
adapter_path = self._proxy.Adapter
|
||||
# name of adapter ('phy0' for example)
|
||||
self.adapter = self._iwd.get_name_from_path(adapter_path)
|
||||
|
||||
def is_adhoc_started(self):
|
||||
"""
|
||||
Returns True if an adhoc network is started on this device.
|
||||
Returns None if device is not powered on or not in ad-hoc mode.
|
||||
"""
|
||||
if self.is_powered_on() and self.get_mode() == "ad-hoc":
|
||||
return self._proxy.Started
|
||||
# If above condition is not true, return None
|
||||
return None
|
||||
|
||||
def is_ap_started(self):
|
||||
"""
|
||||
Same as is_adhoc_started(), but for ap
|
||||
"""
|
||||
if self.is_powered_on() and self.get_mode() == "ap":
|
||||
return self._proxy.Started
|
||||
return None
|
||||
|
||||
def get_mode(self) -> str:
|
||||
"""
|
||||
returns the mode in which the device is in
|
||||
example: "ap"
|
||||
"""
|
||||
return self._proxy.Mode
|
||||
|
||||
def set_mode(self, mode: str):
|
||||
"""change the device mode to mode"""
|
||||
self._proxy.Mode = mode
|
||||
self.reload()
|
||||
|
||||
def start_adhoc_open(self, name: str):
|
||||
"""
|
||||
Create ad-hoc network with name, changing mode to ad-hoc
|
||||
if it isn't already on ad-hoc and power onn the device
|
||||
if it is off
|
||||
"""
|
||||
if self.get_mode() != "ad-hoc":
|
||||
self.set_mode("ad-hoc")
|
||||
|
||||
if not self.is_powered_on():
|
||||
self.power_on()
|
||||
|
||||
# Stop adhoc if already started
|
||||
self.stop_adhoc()
|
||||
|
||||
self._proxy.StartOpen(name)
|
||||
|
||||
def stop_adhoc(self):
|
||||
"""stop adhoc if adhoc is started"""
|
||||
if self.is_adhoc_started():
|
||||
self._proxy.Stop()
|
||||
self.reload()
|
||||
|
||||
def start_ap(self, ssid, passwd):
|
||||
"""
|
||||
Create ap network, changing mode to ap
|
||||
if it isn't already on ap and turning
|
||||
on the device if it is off
|
||||
"""
|
||||
if self.get_mode() != "ap":
|
||||
self.set_mode("ap")
|
||||
|
||||
if not self.is_powered_on():
|
||||
self.power_on()
|
||||
|
||||
# Stop ap if already started
|
||||
self.stop_ap()
|
||||
|
||||
self._proxy.Start(ssid, passwd)
|
||||
|
||||
def stop_ap(self):
|
||||
"""stop ap if an ap is started"""
|
||||
if self.is_ap_started():
|
||||
self._proxy.Stop()
|
||||
self.reload()
|
||||
|
||||
|
||||
class Adapter:
|
||||
"""represents an adapter as a python object"""
|
||||
|
||||
def __init__(self, name: str, bus=SystemMessageBus()):
|
||||
self._iwd = IWD(bus)
|
||||
self._bus = self._iwd._bus
|
||||
self._path = self._iwd.get_adapter_path_from_name(name)
|
||||
# Initialise self._proxy
|
||||
self.reload()
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def reload(self):
|
||||
"""reload the proxy after changing mode"""
|
||||
self._proxy = self._bus.get_proxy(IWD_BUS, self._path)
|
||||
self.name = self._proxy.Name
|
||||
self.supported_modes = self._proxy.SupportedModes
|
||||
self.model = self._proxy.Model
|
||||
self.vendor = self._proxy.Vendor
|
||||
|
||||
def is_powered_on(self) -> bool:
|
||||
"""returns True if adapter is powered on, False otherwise"""
|
||||
return self._proxy.Powered
|
||||
|
||||
def power_on(self):
|
||||
"""power on the adapter"""
|
||||
self._proxy.Powered = True
|
||||
|
||||
def power_off(self):
|
||||
"""power off the adapter"""
|
||||
self._proxy.Powered = False
|
||||
|
||||
def supports_mode(self, mode: str) -> bool:
|
||||
"""
|
||||
Returns True if the adapter supports the mode.
|
||||
mode can be "ad-hoc", "ap" or "station"
|
||||
"""
|
||||
return mode in self.supported_modes
|
|
@ -0,0 +1,115 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2021 The naxalnet Authors
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Setup a working BATMAN Advanced network
|
||||
with systemd-networkd and iwd
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from shutil import copy
|
||||
from dasbus.error import DBusError
|
||||
from naxalnet.iwd import IWD, Device, Adapter
|
||||
|
||||
NETWORKD_CONFIGS = "/usr/share/naxalnet/networkd"
|
||||
NETWORKD_VOLATILE_DIR = "/run/systemd/network"
|
||||
ADHOC_SSID = "HelloWorld"
|
||||
AP_SSID = "NaxalNet"
|
||||
AP_PASSWD = "naxalnet256"
|
||||
|
||||
|
||||
def copy_files():
|
||||
"""
|
||||
Copy networkd configs to volatile dir.
|
||||
The D-Bus API does not support creating new interfaces
|
||||
or linking to bridges. So we use config files.
|
||||
See man:systemd.network(5)
|
||||
"""
|
||||
|
||||
print("Copying network config files")
|
||||
dest = Path(NETWORKD_VOLATILE_DIR)
|
||||
src = Path(NETWORKD_CONFIGS)
|
||||
|
||||
# Create the volatile directory if it doesn't exist
|
||||
dest.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Copy all files in src to dest
|
||||
for i in src.iterdir():
|
||||
copy(i, dest)
|
||||
|
||||
|
||||
def here_be_dragons():
|
||||
"""
|
||||
This function is run every time you
|
||||
execute naxalnet from commandline
|
||||
"""
|
||||
try:
|
||||
copy_files()
|
||||
except PermissionError as error:
|
||||
print(error)
|
||||
sys.exit("Make sure you are root")
|
||||
|
||||
# Now, the iwd part
|
||||
try:
|
||||
iwd = IWD()
|
||||
devices = iwd.get_devices()
|
||||
adhoc_devices = []
|
||||
ap_devices = []
|
||||
|
||||
for i in devices:
|
||||
device = Device(i)
|
||||
adapter = Adapter(device.adapter)
|
||||
if adapter.supports_mode("ad-hoc"):
|
||||
adhoc_devices.append(i)
|
||||
if adapter.supports_mode("ap"):
|
||||
ap_devices.append(i)
|
||||
|
||||
if len(adhoc_devices) != 0:
|
||||
# Start ad-hoc on first device supporting ad-hoc
|
||||
adhoc_device = Device(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 adhoc_device from ap_devices if it exists there
|
||||
if adhoc_device.name in ap_devices:
|
||||
ap_devices.remove(adhoc_device.name)
|
||||
print("Working on ad-hoc")
|
||||
# Turn on adapter if it is off
|
||||
# See issue #9
|
||||
adhoc_adapter = Adapter(adhoc_device.adapter)
|
||||
if not adhoc_adapter.is_powered_on():
|
||||
adhoc_adapter.power_on()
|
||||
adhoc_device.reload()
|
||||
adhoc_device.start_adhoc_open(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")
|
||||
ap_device = Device(ap_devices.pop())
|
||||
# Turn on adapter if it is off
|
||||
# See issue #9
|
||||
ap_adapter = Adapter(ap_device.adapter)
|
||||
if not ap_adapter.is_powered_on():
|
||||
ap_adapter.power_on()
|
||||
ap_adapter.reload()
|
||||
ap_device.start_ap(AP_SSID, AP_PASSWD)
|
||||
except DBusError as error:
|
||||
print(error)
|
||||
sys.exit("An error occured while communicating with iwd")
|
||||
|
||||
# naxalnet will print Bye if no errors occured
|
||||
print("Bye")
|
|
@ -0,0 +1,36 @@
|
|||
[metadata]
|
||||
name = naxalnet
|
||||
version = attr: naxalnet.__version__
|
||||
description = create mesh networks with batman-adv and systemd
|
||||
long_description = file: README.md, LICENSE
|
||||
url = https://git.disroot.org/pranav/naxalnet
|
||||
author = Pranav Jerry
|
||||
author_email = libreinator@disroot.org
|
||||
license = GPLv3
|
||||
classifiers =
|
||||
License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
||||
Operating System :: POSIX :: Linux
|
||||
Programming Language :: Python :: 3 :: Only
|
||||
|
||||
[options]
|
||||
include_package_data = true
|
||||
packages = find:
|
||||
python_requires = >=3.6
|
||||
install_requires =
|
||||
dasbus
|
||||
|
||||
[options.entry_points]
|
||||
console_scripts =
|
||||
naxalnet = naxalnet.scripts:here_be_dragons
|
||||
|
||||
[options.data_files]
|
||||
/usr/lib/systemd/system =
|
||||
naxalnet.service
|
||||
/usr/share/naxalnet/networkd =
|
||||
systemd-networkd/01-batman.netdev
|
||||
systemd-networkd/02-bridge.netdev
|
||||
systemd-networkd/03-wireless-ad-hoc.network
|
||||
systemd-networkd/04-batman.network
|
||||
systemd-networkd/05-wireless-ap.network
|
||||
systemd-networkd/06-eth.network
|
||||
systemd-networkd/07-bridge.network
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup()
|
|
@ -1,5 +1,7 @@
|
|||
# This file links any interface in ap mode
|
||||
# to the bridge we created earlier
|
||||
# to the bridge we created earlier.
|
||||
# To start an AP, connect two adapters to the computer
|
||||
# before starting naxalnet.service
|
||||
# This file won't do anything if an ap interface is not found.
|
||||
|
||||
[Match]
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# to the bridge made in 02-bridge.netdev
|
||||
[Match]
|
||||
Name=en*
|
||||
Name=eth*
|
||||
|
||||
[Network]
|
||||
Bridge=bridge0
|
||||
|
|
Loading…
Reference in New Issue