Compare commits

...

24 Commits

Author SHA1 Message Date
Pranav Jerry 5f7c59d4b8
Modified CHANGELOG.md for releasing new version 2021-09-20 12:28:59 +05:30
Pranav Jerry c8f032a3d0
couple of changes, see full commit message
* make will now build every time naxalnet/__init__.py is changed.
* Changed content related to online classes in README.md. It seems online
  classes are a luxury even in urban areas in some parts of India.
* Added argument -V as alias for --verbose
2021-09-11 22:42:08 +05:30
Pranav Jerry 74a061507f Merge pull request 'Convert into daemon' (#17) from daemon into master
Reviewed-on: pranav/naxalnet#17
2021-09-10 14:59:01 +00:00
Pranav Jerry 5eb55c19a2
changed version to 0.3.0a3
Ready for merge!
2021-09-10 20:23:06 +05:30
Pranav Jerry 2a8930ce00
remove ipfs url from README.md
I don't use IPFS anymore. If anyone if willing to maintain a copy of
this repo on ipfs, send me an email.

Small change in CHANGELOG, and edited comments in systemd service.
And added a docstring to setup.py so the editor won't complain of
missing docstring anymore.
2021-09-10 11:42:18 +05:30
Pranav Jerry f9c969d233
updated README.md
Now that naxalnet is a daemon, there was some things which didn't make
sense anymore. So they were removed.
2021-09-08 15:52:14 +05:30
Pranav Jerry c638de4c9c
updated README, added pyproject.toml 2021-09-08 11:57:10 +05:30
Pranav Jerry ca1e721c9e
fixed logging issue and another bug
There was a problem with indentation which made the line starting adhoc
not being run at all.
Updated CHANGELOG
Moved some things to other places
log.py is back! It isn't needed, but it doesn't do any harm anyway.
2021-09-07 18:45:11 +05:30
Pranav Jerry 68b53ccad1
implemented daemon
naxalnet is now a daemon! When run from systemd, it checks for new
devices or removal of devices and reloads the wifi configuration.
Updated the systemd service and changed Type to notify. Unfortunately,
there is some problem with logging. The messages from naxalnet.iwd could
not be found in the systemd journal or while running without --systemd.
2021-09-07 11:19:14 +05:30
Pranav Jerry 6fff558405
many changes, see full commit message
- Renamed here_be_dragons() to main().
- Added daemon.py (doesn't do anything yet).
- Added GPL disclaimer to all python files and removed the shebang #!
  from all files.
- args is now defined outside any function in scripts.py
- Changed arguments of some functions in scripts.py
2021-09-06 21:54:24 +05:30
Pranav Jerry 0bcd31b6e3
removed log.py 2021-09-06 15:00:34 +05:30
Pranav Jerry 2d9aee4d3a
added --systemd and --verbose arguments
When run without --systemd, naxalnet will log to stderr.
Otherwise, it will log to systemd journal.

log.py is no longer needed.
2021-09-06 14:57:54 +05:30
Pranav Jerry a3e9b45050
more logging messages and code cleanup
Removed log messages from config.py
2021-09-06 12:23:07 +05:30
Pranav Jerry 33156e6a8d Merge pull request 'logging' (#16) from logging into master
Reviewed-on: pranav/naxalnet#16

See CHANGELOG and issue #13 for details
2021-09-05 08:33:32 +00:00
Pranav Jerry 4d9de4d3c3
updated changelog again 2021-09-05 14:00:11 +05:30
Pranav Jerry 97b1f46535
updated CHANGELOG and version in __init__.py
Ready for merge
2021-09-05 13:47:54 +05:30
Pranav Jerry ee341d6967
updated README.md
Made the requirements more clear
2021-09-04 20:00:00 +05:30
Pranav Jerry 3774076e03
updated README
Added new dependency python-systemd
2021-09-04 18:37:30 +05:30
Pranav Jerry 87c5d48144
added more logging info 2021-09-04 14:24:53 +05:30
Pranav Jerry e4a7fa5d3f
renamed systemd-networkd config files 2021-09-04 12:59:26 +05:30
Pranav Jerry 4db6d9457f
improved README, more logging 2021-09-04 11:53:08 +05:30
Pranav Jerry 4ea53e5a35
implemented logging
- New dependency -- python-systemd for logging to journal
- Changed service file to start after networkd
- New submodule which contains "logger" for use by all other submodules
- Removed bus argument from Device and Adapter classes
2021-08-25 15:52:46 +05:30
Pranav Jerry 09ea47e609
fixed typo in README.md 2021-08-23 10:52:08 +05:30
Pranav Jerry d8dcf10b76
changed version in CHANGELOG.md
As usual, I screwed up at the right time.
2021-08-19 13:08:31 +05:30
24 changed files with 566 additions and 195 deletions

151
.gitignore vendored
View File

@ -1,10 +1,145 @@
.DS_Store
.idea
*.log
tmp/
# Created by https://www.toptal.com/developers/gitignore/api/python
# Edit at https://www.toptal.com/developers/gitignore?templates=python
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*.egg*
build
htmlcov
__pycache__
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# End of https://www.toptal.com/developers/gitignore/api/python

View File

@ -1,6 +1,16 @@
# Changelog
## [Unreleased][] - 2021-08-19
## [v0.4.0][] - 2021-09-20
- naxalnet is now a daemon! naxalnet will reconfigure the WiFi network
every time a WiFi adapter is plugged in or removed
- **Logging**: logs to systemd journal when run from systemd, stderr
otherwise
- New dependency `python-systemd`
- Fixed dependency order in systemd service
- Added `--verbose` argument
## [v0.3.0][] - 2021-08-19
- Support for arguments
- Configuration file support with fallback values
@ -17,10 +27,12 @@
## [v0.1.0][] - 2021-06-19
Initial version. At first, this was a shell script. Than it was converted
into a single python file that did just what the shell script used to do.
The shell script was not given a version.
Initial python version. At first, this was a shell script. Than it was
converted into a single python file that did just what the shell script
used to do. The shell script was not given a version.
[unreleased]: https://git.disroot.org/pranav/naxalnet/compare/v0.2.0...HEAD
[unreleased]: https://git.disroot.org/pranav/naxalnet/compare/v0.4.0...HEAD
[v0.4.0]: https://git.disroot.org/pranav/naxalnet/compare/v0.3.0...v0.4.0
[v0.3.0]: https://git.disroot.org/pranav/naxalnet/compare/v0.2.0...v0.3.0
[v0.2.0]: https://git.disroot.org/pranav/naxalnet/compare/v0.1.0...v0.2.0
[v0.1.0]: https://git.disroot.org/pranav/naxalnet/releases/tag/v0.1.0

View File

@ -7,7 +7,7 @@ DESTDIR:= /
all: build
build:
build: naxalnet/__init__.py
$(PYTHON) setup.py build
install: build
@ -16,7 +16,7 @@ install: build
uninstall:
$(PIP) uninstall -y naxalnet
rm -rf /usr/share/naxalnet /usr/lib/systemd/system/naxalnet.service
@-test -d /etc/naxalnet && echo "The directory /etc/naxalnet was not removed." && \
@echo "The directory /etc/naxalnet was not removed." && \
echo "Do 'sudo make purge' to remove it."
# remove config files, like apt purge

138
README.md
View File

@ -3,8 +3,7 @@
**naxalnet** is a program to create a wireless mesh network for
communicating with each other. It can be useful during an
[internet shutdown](#internet-shutdown), or to join
[online classes](#online-class-in-remote-areas) with a group
of laptops.
[online classes](#online-class) with a group of laptops.
It uses [B.A.T.M.A.N. Advanced][batman-adv], an implementation
of the B.A.T.M.A.N. routing protocol to communicate with peers.
The name naxal comes from Naxalbari, a village in Darjeeling,
@ -17,14 +16,13 @@ network.
<!-- NOTE TO ACTIVISTS
Running this program in the world's largest partly-free democracy
may result in you getting arrested under the UAPA, and not
getting bail because of false evidence planted in your phone by
Running this program in the world's largest (partly-free) democracy
may result in you getting arrested under the Act Which Must Not Be Named,
and not getting bail because of false evidence planted in your phone by
Pegasus, or by a forensic lab in Gujarat.
The author, much like the Government of India, does not wish
to take responsibility in your well-being if you get arrested under
a draconian national security law.
The author, much like the GoI, does not wish to take responsibility in your
well-being if you get arrested under a draconian national security law.
-->
<!-- UNCOMMENT WHEN NECESSARY
@ -32,7 +30,7 @@ a draconian national security law.
**Disclaimer**:
In case you are either 1) a complete idiot; or 2) a member of the saffron
brigade; or 3) both, please be aware that this project is not affiliated
with any groups designated as "terrorist" groups in India.
with any human rights groups designated as "terrorist" groups in India.
Using the name naxal does not imply any form of connection
with anyone currently at risk of death in overcrowded prisons.
@ -41,16 +39,17 @@ with anyone currently at risk of death in overcrowded prisons.
## Requirements
- [systemd v248 or more][batman-systemd]
- [systemd-networkd v248 or more][batman-systemd]
- Linux kernel with batman-adv module
- [iwd][]
- python
- python-setuptools (for building and installing)
- [dasbus][]
- WiFi adapter with ad-hoc support
- two or more computers, or laptops with WiFi adapter, called nodes
- [iwd][] for controlling the WiFi adapter
- python3
- python3-setuptools, for building and installing naxalnet
- [python-systemd][], for logging to systemd journal
- [dasbus][], for communicating with iwd
- two or more machines with a WiFi adapter having ibss support, called
nodes or peers
- batctl (optional, for debugging)
- python pip (optional, for uninstalling)
- python3-pip (for installing dasbus on Debian-based distributions)
## Installing
@ -74,17 +73,17 @@ you need it.
naxalnet is not packaged for Ubuntu, so you will have to build
and install it manually.
Currently, only the [unreleased 21.10][ubuntu-systemd] comes with the
required version of systemd. Therefore, naxalnet won't work on Ubuntu
21.04 or older.
Currently, only the **unreleased 21.10** comes with the
required version of systemd. Therefore, naxalnet **won't work on Ubuntu
21.04 or older**.
<!-- TODO: remove this message when systemd 248 arrives in 21.04 -->
<!-- TODO: remove this message if systemd 248 arrives in 21.04 -->
Install the requirements from the Ubuntu repositories:
```sh
# batctl is optional
sudo apt install systemd python3-pip iwd batctl build-essential
sudo apt install python3-pip python3-systemd iwd batctl build-essential
# Now, install dasbus with pip
sudo pip3 install dasbus
```
@ -96,11 +95,11 @@ Now follow the instructions in the
naxalnet is not packaged for Fedora, so it should be installed
manually. naxalnet requires atleast systemd v248 which is only
available on Fedora 34 and above. Install the dependencies:
available on **Fedora 34 and above**. Install the dependencies:
```sh
# systemd-resolved may be required for rawhide
sudo dnf install systemd-networkd iwd python3-dasbus python3-setuptools
sudo dnf install systemd-networkd iwd python3-dasbus python3-setuptools python3-systemd
```
Now head over to the [next section][install-manual] to install naxalnet.
@ -116,15 +115,10 @@ git clone https://git.disroot.org/pranav/naxalnet.git
cd naxalnet
```
Or, if you have an [IPFS client][ipfs] running, try this instead:
```sh
git clone http://k51qzi5uqu5dlye74be0n9iihwk6sm54vexo7bf7pdr4w811y6mmrcp25djozv.ipns.localhost:8080/naxalnet.git
```
Now, install naxalnet:
Now, build and install naxalnet:
```sh
make
sudo make install
```
@ -135,13 +129,24 @@ service files:
sudo systemctl daemon-reload
```
To upgrade, clean the build files, update the repo and reinstall:
```sh
make clean
git pull
make
sudo make uninstall install
```
This will keep the configuration files.
## How to use
You need more than one machine running naxalnet for the connection to work.
### Start naxalnet
Though naxalnet can run from the commandline, it was designed to be
Though naxalnet can run from the command line, it was designed to be
run as a systemd service.
To start naxalnet, do the command on all the nodes:
@ -151,25 +156,25 @@ sudo systemctl start naxalnet.service
This will start a mesh network and connect to all nodes.
To test if it works, run `sudo batctl n -w` and check for
nodes. If there are any nodes, your network is up.
nodes. If there are any nodes, your network is up. Press
Ctrl+C to stop `batctl`.
### Getting internet access
Connect an ethernet cable from a router to any of the peers and
[start naxalnet][startnx]. If it was already started, you should
Connect an ethernet cable from a router to any of the nodes and
renew the DHCP connection of all peers. To do this, type
`sudo networkctl renew bridge0` on all peers.
`sudo networkctl renew bridge0` on all nodes.
### Tethering via WiFi AP
If there are two adapters in a peer, naxalnet will start a
WiFi ap (also called WiFi hotspot) on one of them.
Connect two WiFi adapters on a device and [start naxalnet][startnx].
Now an ap will be started on one of the adapters.
Type `naxalnet --print-WiFi` to get the WiFi SSID and password.
Connect two WiFi adapters on a node.
Now an AP will be started on one of the adapters.
Type `naxalnet --print-wifi` to get the WiFi SSID and password.
If you had set up internet access on one of the peers, internet
If you had set up internet access on one of the nodes, internet
can be accessed from the AP.
### Running at boot
@ -221,10 +226,10 @@ naxalnet --help
## How it works
There are three modes commonly supported by WiFi adapters -
`ap` (WiFi hotspot), `station` (for joining WiFi networks) and `ad-hoc`
(for decentralised networks). There are some other modes too,
like `p2p` (WiFi direct), but we won't go into the details.
There are three modes commonly supported by WiFi adapters - `ap` (WiFi
hotspot), `station` (for joining WiFi networks) and `ad-hoc` (or ibss, for
decentralised networks). There are other modes supported by some WiFi
adapters too, like `p2p` (WiFi direct), but this program doesn't use them.
naxalnet uses two modes - `ad-hoc` and `ap`, for connecting to the
mesh. naxalnet uses iwd to start an `ad-hoc` network and configures
@ -234,26 +239,33 @@ naxalnet starts an ad-hoc on one of them and an ap on the other.
You can use the ap for connecting mobile phones and other devices
to the mesh network.
Read the code to learn the details.
See [systemd-networkd](systemd-networkd) to see how
Read the code and the documentation in the code to learn the details.
See the directory [systemd-networkd](systemd-networkd) to see how
systemd-networkd configures the network.
## Use cases
### Online class in remote areas
### Online class
naxalnet can be used to share connections in remote areas.
naxalnet can be used to share connections to join online classes.
You need at least one device with internet access.
<!--
### Malign democracies and well-established institutions
Withheld due to national security reasons.
-->
### Internet shutdown
You can communicate with neighbouring devices running naxalnet,
using services like [IPFS][], [Jami][], [Secure Scuttlebutt][ssb]
and others which can work on an intranet.
They should be installed on your machine _before_ your friendly
democratic government announces an [internet shutdown][], since you
cannot download and install them during a shutdown.
When a shutdown occurs, [enable naxalnet][enablenx]
You can communicate with neighbouring devices running naxalnet, using
services like [IPFS][], [Jami][], [Secure Scuttlebutt][ssb] and others
which can work on an intranet. They should be installed on your
machine _before_ your friendly democratic government announces an
[internet shutdown][], since you cannot download and install them
during a shutdown. When a shutdown occurs, [enable naxalnet][enablenx].
## Uninstalling
@ -273,10 +285,16 @@ See [HACKING.md](HACKING.md)
## Similar projects
The following projects are similar to naxalnet, but are not designed
to be used in a machine 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.
Many projects make setting up B.A.T.M.A.N. Advanced mesh networks with
WiFi routers easier. They are easier to setup and are more
configurable. But naxalnet is different from them. It simplifies
setting up mesh networks with _laptops or computers_, and was not
made to work with routers.
The following projects does something similar to naxalnet, but
requires special devices or routers to work. If you live in an area
where the materials are easily available, consider using them instead
of naxalnet.
- [LibreMesh][]: framework for OpenWrt-based firmwares
- [disaster.radio][]: solar-powered communications network
@ -306,6 +324,6 @@ See [LICENSE](LICENSE) for the complete version of the license.
[iwd]: https://iwd.wiki.kernel.org "WiFi daemon"
[free-sw]: https://gnu.org/philosophy/free-sw.html "What is free software?"
[enablenx]: #running-at-boot
[ubuntu-systemd]: https://packages.ubuntu.com/impish/systemd
[requirements]: #requirements
[install-manual]: #manually
[python-systemd]: https://github.com/systemd/python-systemd

View File

@ -18,5 +18,6 @@ name = NxMesh
[ap]
# An AP is started if your machine has more than one WiFi adapter.
ssid = MeshWiFi
# Note the spelling. It's passwd, not password.
passwd = naxalnet256

View File

@ -7,6 +7,8 @@ Requires=systemd-networkd.service
Requires=iwd.service
Wants=systemd-resolved.service
After=iwd.service
After=systemd-networkd.service
After=systemd-resolved.service
# Stops NetworkManager and wpa_supplicant if already running
Conflicts=NetworkManager.service
Conflicts=wpa_supplicant.service
@ -15,33 +17,24 @@ After=NetworkManager.service
After=wpa_supplicant.service
[Service]
Type=oneshot
RemainAfterExit=yes
Type=notify
NotifyAccess=all
Restart=on-failure
RestartSec=2sec
# IWD takes some time to find devices.
# If naxalnet is run before iwd finds devices,
# naxalnet cannot start a mesh network but exits without errors.
# So, we give a 2s delay.
ExecStartPre=/usr/bin/sleep 2
ExecStart=/usr/bin/naxalnet
# Reload systemd-networkd after naxalnet exits
ExecStart=/usr/bin/naxalnet --systemd
# Reload systemd-networkd after naxalnet signals it is ready
ExecStartPost=/usr/bin/networkctl reload
# Delete all files in /run/systemd/network
ExecStop=/usr/bin/find /run/systemd/network -type f -delete
# Delete the interfaces created...
# When naxalnet exits, delete all files starting
# with mesh.* in /run/systemd/network
ExecStopPost=/usr/bin/find /run/systemd/network -type f -delete -name "mesh.*"
# Then delete the two interfaces created...
ExecStopPost=/usr/bin/networkctl delete bridge0 bat0
# ... and reload the configuration files.
ExecStopPost=/usr/bin/networkctl reload
# Make python flush messages instead of buffering.
# When reading the systemd journal, we need to see the messages
# in the exact order. There will suddenly be a lot of messages
# from naxalnet, networkd, iwd and resolved. When buffering is on,
# we won't see the messages from naxalnet in the order they were
# printed. This, among other problems, make it hard while debugging.
# This will no longer be needed when naxalnet sends its messages
# directly to the systtemd journal instead of stdout.
Environment=PYTHONUNBUFFERED=1
# naxalnet already logs to systemd journal so we don't need
# stdout and stderr.
StandardOutput=null
StandardError=null
[Install]
WantedBy=multi-user.target

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# This file is part of naxalnet.
# Copyright (C) 2021 The naxalnet Authors
# This program is free software: you can redistribute it and/or modify
@ -36,4 +35,4 @@ See README.md for documentation.
#
# In case you forgot to change the version, skip the number
# and put the next number in the next commit.
__version__ = "0.3.0"
__version__ = "0.4.0"

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# This file is part of naxalnet.
# Copyright (C) 2021 The naxalnet Authors
# This program is free software: you can redistribute it and/or modify
@ -15,13 +14,14 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
If called as python -m naxalnet, this file makes naxalnet run like
it was called from the commandline. Try:
python -m naxalnet --help
"""
from naxalnet.scripts import here_be_dragons
from naxalnet.scripts import main
if __name__ == "__main__":
here_be_dragons()
main()

View File

@ -1,4 +1,18 @@
#!/usr/bin/env python3
# This file is part of naxalnet.
# 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/>.
"""
config.py
@ -54,6 +68,7 @@ def get_config_files():
of files that exists as pathlib.Path objects
"""
config_files = []
for directory in CONFIG_DIRS:
path = Path(directory)
if path.exists():
@ -68,12 +83,14 @@ def parse_config():
Parse all configuration files, with the values in
default.py as fallback
"""
# logger.debug("Parsing config files")
parser = ConfigParser()
# encoded defaults
parser.read_dict(CONFIG)
# read config files
files = get_config_files()
for i in files:
# logger.debug("Reading config file %s", str(i))
parser.read_file(i.open())
return parser
@ -134,11 +151,27 @@ def parse_args() -> Namespace:
help="volatile directory where configuration files of systemd-networkd should be copied",
)
parser.add_argument(
"--systemd",
action="store_true",
default=False,
help="send log messages to systemd journal",
)
parser.add_argument(
"--version",
"-V",
default=False,
action="store_true",
help="prints the version and exit",
)
parser.add_argument(
"-v", "--verbose", action="count", default=0, help="increase output verbosity"
)
# logger.debug("Parsing arguments")
return parser.parse_args()
args = parse_args()

69
naxalnet/daemon.py Normal file
View File

@ -0,0 +1,69 @@
# This file is part of naxalnet.
# 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/>.
"""
daemon.py
---------
The daemon part. This is currently under construction.
"""
from dasbus.loop import EventLoop
from naxalnet.iwd import IWD, IWD_DEVICE_INTERFACE
from naxalnet.log import logger
class Daemon:
"""implements the daemon part"""
def __init__(self):
self.loop = EventLoop()
self.iwd = IWD()
def on_device_add(self, path, data):
"""
this function will be run every time a device is added
"""
if IWD_DEVICE_INTERFACE in data:
logger.debug("New device %s found", str(data[IWD_DEVICE_INTERFACE]["Name"]))
logger.info("Reloading")
self.callback()
def on_device_remove(self, path, data):
"""
this function will be run every time a device is removed
"""
if IWD_DEVICE_INTERFACE in data:
logger.debug("A device was removed")
logger.info("Reloading")
self.callback()
def add_callback(self, callback):
"""
register the callback with D-Bus so that callback is
run every time a device is added or removed
"""
self.callback = callback
proxy = self.iwd._proxy
proxy.InterfacesAdded.connect(self.on_device_add)
proxy.InterfacesRemoved.connect(self.on_device_remove)
def start(self):
"""
start the daemon
"""
logger.debug("Starting daemon")
self.loop.run()

View File

@ -1,4 +1,18 @@
#!/usr/bin/env python3
# This file is part of naxalnet.
# 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/>.
"""
default.py

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# This file is part of naxalnet.
# Copyright (C) 2021 The naxalnet Authors
# This program is free software: you can redistribute it and/or modify
@ -15,7 +14,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
iwd.py
------
@ -60,6 +58,7 @@ and what they mean:
"""
from dasbus.connection import SystemMessageBus
from naxalnet.log import logger
IWD_BUS = "net.connman.iwd"
IWD_ROOT_PATH = "/"
@ -165,8 +164,8 @@ class Device:
adapter: name of adapter (str)
"""
def __init__(self, name: str, bus=SystemMessageBus()):
self._iwd = IWD(bus)
def __init__(self, name: str):
self._iwd = IWD()
self._bus = self._iwd._bus
self._path = self._iwd.get_device_path_from_name(name)
self.reload()
@ -181,11 +180,13 @@ class Device:
def power_on(self):
"""Turn on the device and reload the proxy"""
self._proxy.Powered = True
logger.debug("Powered on %s", self.name)
self.reload()
def power_off(self):
"""Turn off the device and reload the proxy"""
self._proxy.Powered = False
logger.debug("Powered off %s", self.name)
self.reload()
def reload(self):
@ -225,6 +226,7 @@ class Device:
def set_mode(self, mode: str):
"""change the device mode to mode"""
self._proxy.Mode = mode
logger.debug("Set mode on %s to %s", self.name, mode)
self.reload()
def start_adhoc_open(self, name: str):
@ -233,6 +235,7 @@ class Device:
if it isn't already on ad-hoc and power onn the device
if it is off
"""
print("Starting adhoc", name)
if self.get_mode() != "ad-hoc":
self.set_mode("ad-hoc")
@ -242,11 +245,13 @@ class Device:
# Stop adhoc if already started
self.stop_adhoc()
logger.debug("Starting ad-hoc on %s", self.name)
self._proxy.StartOpen(name)
def stop_adhoc(self):
"""stop adhoc if adhoc is started"""
if self.is_adhoc_started():
logger.debug("Stopping ad-hoc on %s", self.name)
self._proxy.Stop()
self.reload()
@ -265,11 +270,13 @@ class Device:
# Stop ap if already started
self.stop_ap()
logger.debug("Starting ap on %s with ssid %s", self.name, ssid)
self._proxy.Start(ssid, passwd)
def stop_ap(self):
"""stop ap if an ap is started"""
if self.is_ap_started():
logger.debug("Stopping ap on %s", self.name)
self._proxy.Stop()
self.reload()
@ -277,8 +284,8 @@ class Device:
class Adapter:
"""represents an adapter as a python object"""
def __init__(self, name: str, bus=SystemMessageBus()):
self._iwd = IWD(bus)
def __init__(self, name: str):
self._iwd = IWD()
self._bus = self._iwd._bus
self._path = self._iwd.get_adapter_path_from_name(name)
# Initialise self._proxy
@ -300,10 +307,14 @@ class Adapter:
def power_on(self):
"""power on the adapter"""
self._proxy.Powered = True
logger.debug("Powered on adapter %s", self.name)
self.reload()
def power_off(self):
"""power off the adapter"""
self._proxy.Powered = False
logger.debug("Powered off adapter %s", self.name)
self.reload()
def supports_mode(self, mode: str) -> bool:
"""

54
naxalnet/log.py Normal file
View File

@ -0,0 +1,54 @@
# This file is part of naxalnet.
# 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/>.
"""
log.py
------
Initialise the logger for other submodules to import. Do not
import any submodules here except for naxallnet.config
"""
import logging
from systemd.journal import JournalHandler
from naxalnet.config import args
def get_logger():
"""
Initialise the logger and return it.
This function is meant to be used only by naxalnet.log.
If you want to import the logger, use:
from naxalnet.log import logger
"""
log = logging.getLogger("naxalnet")
# --verbose
if args.verbose >= 2:
loglevel = logging.DEBUG
elif args.verbose == 1:
loglevel = logging.INFO
else:
loglevel = logging.WARNING
# if --systemd is given, log to systemd journal
if args.systemd:
logging.basicConfig(level=logging.DEBUG)
log.addHandler(JournalHandler())
else:
logging.basicConfig(level=loglevel)
return log
logger = get_logger()

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# This file is part of naxalnet.
# Copyright (C) 2021 The naxalnet Authors
# This program is free software: you can redistribute it and/or modify
@ -24,94 +23,116 @@ and doing the things this program is supposed to do.
This file is named scripts.py because the original developer
of this program could not think of a better name that suits this file.
If you want to hack naxalnet, this is the right place to start.
When run from the commandline, the function here_be_dragons() is called.
When run from the commandline, the function main() is called.
"""
import sys
from pathlib import Path
from shutil import copy
from dasbus.error import DBusError
from systemd.daemon import notify
from naxalnet import __version__
from naxalnet.log import logger
from naxalnet.iwd import Adapter, Device, IWD
from naxalnet.config import parse_args
from naxalnet.config import args
from naxalnet.daemon import Daemon
def copy_files(args):
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)
"""
try:
notify("STATUS=Configuring the network...")
logger.info("Copying network config files")
dest = Path(args.networkd_runtime_dir)
src = Path(args.networkd_config_dir)
print("Copying network config files")
dest = Path(args.networkd_runtime_dir)
src = Path(args.networkd_config_dir)
# Create the volatile directory if it doesn't exist
dest.mkdir(parents=True, exist_ok=True)
# 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)
# Copy all files in src to dest
for i in src.iterdir():
copy(i, dest)
except PermissionError as error:
logger.error("Cannot copy file: %s", error)
sys.exit(3)
def setup_devices(args):
def setup_devices():
"""
Setup wifi interfaces using iwd
This function should be called every time an interface
is connected or removed.
args should be what parse_args() returns
"""
iwd = IWD()
devices = iwd.get_devices()
adhoc_devices = []
ap_devices = []
try:
notify("STATUS=Setting up mesh...")
iwd = IWD()
devices = iwd.get_devices()
adhoc_devices = []
ap_devices = []
# Find devices supporting ad-hoc and ap
for i in devices:
# For each device, check if its adapter supports
# ad-hoc or ap. Many adapters will support both,
# so we will prioritise ad-hoc over ap.
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)
# Find devices supporting ad-hoc and ap
for i in devices:
# For each device, check if its adapter supports
# ad-hoc or ap. Many adapters will support both,
# so we will prioritise ad-hoc over ap.
device = Device(i)
logger.debug("Found device %s", device.name)
adapter = Adapter(device.adapter)
if adapter.supports_mode("ad-hoc"):
logger.debug("The device %s can be used for ad-hoc", device.name)
adhoc_devices.append(i)
if adapter.supports_mode("ap"):
logger.debug("The device %s can be used for ap", device.name)
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.
# So we will remove adhoc_device from ap_devices if it exists there
if adhoc_device.name in ap_devices:
ap_devices.remove(adhoc_device.name)
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.
# So we will remove adhoc_device from ap_devices if it exists there
if adhoc_device.name in ap_devices:
ap_devices.remove(adhoc_device.name)
print("Starting mesh on", adhoc_device.name)
# 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(args.adhoc_name)
# Start Access point if ap_device is not empty,
# ie, we have more devices
if len(ap_devices) != 0:
ap_device = Device(ap_devices.pop())
print("Starting WiFi Access point on", ap_device.name)
print('Use "naxalnet --print-wifi" to get password')
# 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(args.ap_ssid, args.ap_passwd)
adhoc_adapter = Adapter(adhoc_device.adapter)
if not adhoc_adapter.is_powered_on():
logger.debug("Adapter %s is off. Turning on", adhoc_adapter.name)
adhoc_adapter.power_on()
logger.info("Starting mesh on %s", adhoc_device.name)
adhoc_device.start_adhoc_open(args.adhoc_name)
# Start Access point if ap_device is not empty,
# ie, we have more devices
if len(ap_devices) != 0:
ap_device = Device(ap_devices.pop())
logger.info("Starting WiFi Access Point on %s", ap_device.name)
logger.info("Use naxalnet --print-wifi to get password")
# Turn on adapter if it is off
# See issue #9
ap_adapter = Adapter(ap_device.adapter)
if not ap_adapter.is_powered_on():
logger.debug("Adapter %s is off. Turning on", ap_adapter.name)
ap_adapter.power_on()
ap_device.start_ap(args.ap_ssid, args.ap_passwd)
else:
logger.warning("Not setting up WiFi AP.")
else:
logger.warning(
"No device found to setup mesh. Make sure a WiFi adapter is connected"
)
except DBusError:
logger.exception("Error while communicating with iwd")
sys.exit(4)
def print_wifi(args):
def print_wifi():
"""
Prints the name and password of the adhoc, and ap
from the arguments
@ -126,32 +147,33 @@ def print_version():
print(__version__)
def here_be_dragons():
def main():
"""
This is where the magic happens!
This function is run every time you
execute naxalnet from the commandline
"""
args = parse_args()
if args.print_wifi:
print_wifi(args)
print_wifi()
sys.exit(0)
elif args.version:
print_version()
sys.exit(0)
copy_files()
try:
copy_files(args)
except PermissionError as error:
print(error)
sys.exit("Make sure you are root")
setup_devices()
# Notify systemd that naxalnet is ready.
# see man:sd_notify(3)
notify("READY=1")
try:
setup_devices(args)
except DBusError as error:
print(error)
sys.exit("An error occured while communicating with iwd")
# Start the daemon so that setup_devices() is called every
# time a device is connected or removed.
daemon = Daemon()
daemon.add_callback(setup_devices)
# naxalnet will print Bye if no errors occured
print("Bye")
notify("STATUS=Waiting for changes")
daemon.start()
# naxalnet prints Bye while exiting.
logger.info("Bye")

3
pyproject.toml Normal file
View File

@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

View File

@ -19,24 +19,29 @@ packages = find:
python_requires = >=3.6
install_requires =
dasbus
# pathlib, configparser and argparse are already
# in the standard library
configparser
pathlib
argparse
systemd
[options.entry_points]
console_scripts =
naxalnet = naxalnet.scripts:here_be_dragons
naxalnet = naxalnet.scripts:main
[options.data_files]
lib/systemd/system =
naxalnet.service
# If installing with pip, this file will be copied to some other place.
# This is the reason we use setup.py instead of pip.
/etc/naxalnet =
naxalnet.conf.example
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
systemd-networkd/mesh.01-batman.netdev
systemd-networkd/mesh.02-bridge.netdev
systemd-networkd/mesh.03-wireless-ad-hoc.network
systemd-networkd/mesh.04-batman.network
systemd-networkd/mesh.05-wireless-ap.network
systemd-networkd/mesh.06-eth.network
systemd-networkd/mesh.07-bridge.network

View File

@ -1,5 +1,7 @@
#!/usr/bin/env python3
"""
See setup.py --help for usage
"""
from setuptools import setup
setup()