updated documentation and some other changes

Made messages printed in Makefile more understandable. Removed full path
of naxalnet from the systemd service. Now you can start naxalnet even if
it is installed in /usr/local/bin, if systemd allows (I have not tested
it). Many comments were made to respect the 80 chars per line rule.
And, of course, added some political commentary to insult the global
superpower (superpower in terms of money, military and something else I
forgot). And removed MANIFEST.in, which probably haven't changed anything.
This commit is contained in:
Pranav Jerry 2021-10-02 14:13:53 +05:30
parent a7304a986b
commit 61a96ea3b3
No known key found for this signature in database
GPG Key ID: F1DCDC4FED0A0C5B
16 changed files with 218 additions and 164 deletions

View File

@ -35,7 +35,7 @@
## [v0.1.0][] - 2021-06-19
Rewrite to python. At first, this was a shell script. Than it was
Rewrite to python. At first, this was a shell script. Then 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.

View File

@ -25,6 +25,6 @@ Currently this program is only packaged for Arch Linux.
naxalnet needs packages in GNU+Linux+systemd
distributions such as Debian, Fedora, openSUSE,
and nixos. If you know/like to package it in your distro,
post to issue #6.
post a message to issue #6.
[hack]: https://catb.org/jargon/html/H/hack.html

View File

@ -1,5 +0,0 @@
include LICENSE
include README.md
include naxalnet.service
include naxalnet.conf.example
recursive-include systemd-networkd *

View File

@ -1,15 +1,19 @@
# This makefile uses setup.py under the hood.
# In ubuntu, python and pip are symlinks to python2 and pip2, not
# python3. So we have to specify python as python3 by default.
# This makefile uses setup.py under the hood. In debian, and therefore
# ubuntu, and in fedora, python and pip are symlinks to python2 and pip2,
# not python3. So we have to specify python as python3 by default.
PYTHON := python3
PIP := pip3
# This can be changed when creating a package for your POSIX distribution
DESTDIR:= /
all: build
build: build/lib/naxalnet/__init__.py
build/lib/naxalnet/__init__.py: naxalnet/__init__.py
# Build only when naxalnet/__init__.py changes. We assume here that anyone
# creating a new commit will first update the __version__ in
# naxalnet/__init__.py
build: naxalnet/__init__.py
$(PYTHON) setup.py build
install:
@ -18,10 +22,11 @@ install:
uninstall:
$(PIP) uninstall -y naxalnet
rm -rf /usr/share/naxalnet /usr/lib/systemd/system/naxalnet.service
@echo "The directory /etc/naxalnet was not removed." && \
@echo "make uninstall will not remove anything in /etc/naxalnet" && \
echo "Do 'sudo make purge' to remove it."
# remove config files, like apt purge
# Remove config files, like apt purge. Purge should first do what
# uninstall does, so we add uninstall as a dependency to this rule.
purge: uninstall
rm -rf /etc/naxalnet

View File

@ -187,12 +187,26 @@ sudo systemctl enable naxalnet.service
```
Now naxalnet will start a mesh on every boot.
Disable the service to stop running at boot:
If you have NetworkManager enabled, which is the default in Ubuntu and
Fedora, it should be disabled:
```sh
sudo systemctl disable NetworkManager.service
```
To stop running at boot, you should disable `naxalnet.service`:
```sh
sudo systemctl disable naxalnet.service
```
If you had disabled `NetworkManager` before, enable it:
```sh
sudo systemctl enable NetworkManager.service
```
### Stopping the service
```sh

View File

@ -21,7 +21,7 @@ Type=notify
NotifyAccess=all
Restart=on-failure
RestartSec=2sec
ExecStart=/usr/bin/naxalnet --systemd
ExecStart=naxalnet --systemd
KillSignal=SIGINT
# naxalnet already logs to systemd journal so we don't need
# stdout and stderr.

View File

@ -1,25 +1,32 @@
# 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 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.
# 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/>.
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
"""
naxalnet
========
Create mesh networks with batman-adv, systemd-networkd and iwd.
See README.md for documentation.
See README.md and the docstrings for documentation. You can read
documentaion in the python interpretor using something like the example
given below.
>>> help("naxalnet")
>>> help("naxalnet.config")
"""
# GUIDE FOR CHANGING __version__
@ -35,4 +42,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.4.0a5.dev8"
__version__ = "0.4.0a5.dev9"

View File

@ -16,9 +16,16 @@
"""
__main__.py
-----------
If called as python -m naxalnet, this file makes naxalnet run like
it was called from the commandline. Try:
python -m naxalnet --help
WARNING: Using naxalnet might threaten the soverignity and integrity of
your nation-state. The authors are not responsible for any damage caused
while using this software.
"""
from naxalnet.scripts import main

View File

@ -1,59 +1,56 @@
# 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 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.
# 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/>.
# 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
---------
This file contains functions to parse configuration files
and arguments. Most of these functions are meant to be used
by parse_args() internally, so only parse_args() should
be imported outside this file.
This file contains functions to parse configuration files and arguments.
Most of these functions are meant to be used by parse_args() internally,
so only parse_args() should be imported outside this file.
Some parts of naxalnet can be configured by configuration
files and arguments. First, the default values from
default.py is taken. Then, key-value pairs from the
configuration files are read, if they exist, in the
following order:
Some parts of naxalnet can be configured by configuration files and
arguments in a specific order. First, the default values from default.py
is taken. Then, key-value pairs from the configuration files are read, if
they exist, in the following order:
- First it reads /usr/share/naxalnet/naxalnet.conf and then from
/usr/share/naxalnet/naxalnet.conf.d/*.conf where *.conf means any file
with the name ending with ".conf". The files in this directory are
intended to be used by distribution and package maintainers.
- First it reads /usr/share/naxalnet/naxalnet.conf
and then from /usr/share/naxalnet/naxalnet.conf.d/*.conf
where *.conf means any file with the name ending with
".conf". The files in this directory are intended
to be used by distribution and package maintainers.
- Next, it does the same with /usr/local/share/naxalnet
- Then, it looks for the files naxalnet.conf and
naxalnet.conf.d/*.conf from the directory
/etc/naxalnet, like it did up above. This directory is where
the user creates and stores the config file.
- Then it parses the arguments from the commandline,
storing the values in the files parsed until now
as fallback. Finally you get an argpase.Namespace object
from parse_args().
Because of the way this is implemented, all key-value
pairs in the configuration should have an argument
too, or they won't be parsed.
All the key-value pairs are replaced successively if they exist
by each new configuration file parsed, similar
to how systemd parses configuration and service files.
If any of the files checked does not exist, then they are
ignored and the next combination is checked. If none of
the config files exist and no arguments are given, the
fallback data from default.py is used.
- Then, it looks for the files naxalnet.conf and naxalnet.conf.d/*.conf
from the directory /etc/naxalnet, like it did up above. This directory
is where the user creates and stores the config file.
- Then it parses the arguments from the commandline, storing the values in
the files parsed until now as fallback. Finally you get an
argpase.Namespace object from parse_args(). Because of the way this is
implemented, all key-value pairs in the configuration should have an
argument too, or they won't be parsed.
All the key-value pairs are replaced successively if they exist by each
new configuration file parsed, similar to how systemd parses configuration
and service files. If any of the files checked does not exist, then they
are ignored and the next combination is checked. If none of the config
files exist and no arguments are given, the fallback data from default.py
is used.
"""
from pathlib import Path
@ -191,4 +188,7 @@ def parse_args() -> Namespace:
return parser.parse_args()
# This is defined here because log.py needs some arguments to determine
# the loglevel and where to send the log message to. If you know a better
# way of implementing it, create an issue
args = parse_args()

View File

@ -1,24 +1,25 @@
# 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 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.
# 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/>.
# 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.
The daemon part. This is used to perform some work when a new wifi adapter
is plugged in, or it is removed.
"""
from dasbus.loop import EventLoop
@ -39,7 +40,7 @@ class Daemon:
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.debug("New device %s found", data[IWD_DEVICE_INTERFACE]["Name"])
logger.info("Reloading")
self.callback()

View File

@ -1,29 +1,28 @@
# 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 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.
# 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/>.
# 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
----------
This file contains default values for configuration.
This is taken as fallback data by config.py if no
configuration files were found, or if a key-value pair
was not present in the config file. The data will be
further changed by arguments if naxalnet is called
from the commandline. See config.py for more info.
This file contains default values for configuration. This is taken as
fallback data by config.py if no configuration files were found, or if a
key-value pair was not present in the config file. The data will be
further changed by arguments if naxalnet is called from the commandline.
See config.py for more info.
"""
CONFIG = {

View File

@ -1,60 +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 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.
# 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/>.
# 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
------
This file contains methods to communicate with iwd via
its D-Bus API and control WiFi adapters.
This file contains methods to communicate with iwd via its D-Bus API and
control WiFi adapters.
Some terms used here, such as device and adapter might
confuse you if you haven't used iwctl before.
Just as a quick reference, here is a list of terms
and what they mean:
Some terms used here, such as device and adapter might confuse you if you
haven't used iwctl before. Just as a quick reference, here is a list of
terms and what they mean:
- ad-hoc: a mode supported by some WiFi adapters to
start a decentralised network, where there
is no central point of failure.
- ad-hoc: a mode supported by some WiFi adapters to start a decentralised
network, where there is no central point of failure.
- ap: a mode used to start a central access point
so that other machines without naxalnet can
connect to the mesh. AP is also known as
WiFi hotspot.
- ap: a mode used to start a central access point so that other machines
without naxalnet can connect to the mesh. AP is also known as WiFi
hotspot.
- station: this is the mode most WiFi adapters use
by default. This mode is used to connect to
an ap. naxalnet DOES NOT use this mode.
- station: this is the mode most WiFi adapters use by default. This mode
is used to connect to an ap. naxalnet DOES NOT use this mode.
- adapter: a physical WiFi chip or something similar
that is present inside most laptops and phones
or can be connected via USB to a machine.
- adapter: a physical WiFi chip or something similar that is present
inside most laptops and phones or can be connected via USB to a
machine.
- device: an interface provided by the kernel to control
an adapter. Some adapters can have multiple
devices so that you can start an ap on one device
and an ad-hoc on the other. By default, iwd starts
- device: an interface provided by the kernel to control an adapter. Some
adapters can have multiple devices so that you can start an ap
on one device and an ad-hoc on the other. By default, iwd starts
only one device each for one adapter.
- machine: Since iwd uses the term device for a
WiFi interface, we use the word machine to
refer to a computer, or a laptop, or a phone.
- machine: Since iwd uses the term device for a WiFi interface, we use the
word machine to refer to a computer, or a laptop, or a phone.
- node: a machine that runs naxalnet and is therefore
connected to the mesh.
- node: a machine that runs naxalnet and is therefore connected to the
mesh.
"""
from dasbus.connection import SystemMessageBus
@ -74,7 +68,7 @@ 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 and self._proxy are meant for use only in this submodule
self._bus = bus
self.reload()
@ -95,9 +89,9 @@ class IWD:
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
# See comment in the function below
path = i
return path
def get_adapter_path_from_name(self, name: str) -> str:
"""returns path of adapter as str"""
@ -105,9 +99,10 @@ class IWD:
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
# We could have just used return here, but shutting up
# pylint has a greter priority at the moment
path = i
return path
def get_all_device_paths(self) -> list:
"""returns list of paths of all devices"""
@ -132,7 +127,8 @@ class IWD:
def get_devices(self) -> list:
"""
returns list of device names as str
returns list of all device names as str
example: ["wlan0", "wlan1"]
"""
devices = []
@ -146,6 +142,7 @@ class IWD:
def get_adapters(self) -> list:
"""
returns list of adapters
example: ["phy0","phy1"]
"""
adapters = []
@ -160,6 +157,7 @@ class IWD:
class Device:
"""
control devices with iwd
name: name of device (str)
adapter: name of adapter (str)
"""
@ -190,7 +188,10 @@ class Device:
self.reload()
def reload(self):
"""reload the proxy after changing mode"""
"""
Reload the proxy. Used liberally by other
members to work around errors
"""
self._proxy = self._bus.get_proxy(IWD_BUS, self._path)
self.name = self._proxy.Name
adapter_path = self._proxy.Adapter
@ -235,16 +236,15 @@ class Device:
if it isn't already on ad-hoc and power onn the device
if it is off
"""
print("Starting adhoc", name)
# Stop adhoc if already started
self.stop_adhoc()
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()
logger.debug("Starting ad-hoc on %s", self.name)
self._proxy.StartOpen(name)
@ -261,15 +261,16 @@ class Device:
if it isn't already on ap and turning
on the device if it is off
"""
# Stop ap if already started
self.stop_ap()
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()
logger.debug("Starting ap on %s with ssid %s", self.name, ssid)
self._proxy.Start(ssid, passwd)

View File

@ -18,8 +18,9 @@
log.py
------
Initialise the logger for other submodules to import. Do not
import any submodules here except for naxallnet.config
Initialise the logger for other submodules to import. Do not import any
submodules here other than naxallnet.config, which is needed to set the
loglevel and to add the systemd journal handler
"""
import logging
from systemd.journal import JournalHandler

View File

@ -18,9 +18,15 @@
network.py
----------
This submodule manages the systemd-networkd configuration.
TODO: Add more details
This submodule manages the systemd-networkd configuration. This is used to
add configuration files to the systemd-networkd runtime directory.
Some configuration files have variables which should be substituted by
str.format() in python. The values for these variables can be set using
NetworkD.set_vars(). See files in the systemd-networkd directory for
examples.
"""
import subprocess
from pathlib import Path
from dasbus.connection import SystemMessageBus
@ -31,7 +37,11 @@ NETWORKD_PATH = "/org/freedesktop/network1"
class NetworkD:
"""control systemd-networkd"""
"""
Control systemd-networkd using configuration files. Since these
were made for use by naxalnet only, the class is not suitable for
importing outside naxalnet.
"""
def __init__(self, runtime_dir="/run/systemd/network", bus=SystemMessageBus()):
self._bus = bus
@ -51,7 +61,10 @@ class NetworkD:
self.proxy = self._bus.get_proxy(NETWORKD_BUS, NETWORKD_PATH)
def reload(self) -> None:
"""reload the systemd-networkd configuration"""
"""
Reload the systemd-networkd configuration. This is used by many
class methods after doing their job.
"""
self.proxy.Reload()
def add_config(self, name: str) -> None:
@ -79,7 +92,13 @@ class NetworkD:
self.reload()
def disable_config(self, name: str) -> None:
"""Disable the config of the given name"""
"""
Disable or mask the config of the same name. This can only be
used for configs in /usr/lib/systemd/network and
/usr/local/lib/systemd/network. It works on the same principle
used by systemctl mask, that is, it created a symlink of the same
name in the runtime directory and links it to /dev/null.
"""
path = self.runtime_path / name
path.symlink_to("/dev/null")
self.reload()

View File

@ -89,14 +89,18 @@ def setup_mesh(gateway_mode: str = "off"):
gateway_mode=gateway_mode,
)
# Fix for issue #19
# Fix for issue #19. There should be a switch to disable this
# humanitarian intervention. We don't want to adopt the U.S.
# foreign policy here.
networkd.disable_config("80-wifi-adhoc.network")
for i in get_sorted_glob(args.networkd_config_dir, MESH_GLOB):
logger.debug("Adding network config %s", i)
networkd.add_config(i)
except PermissionError:
logger.exception("A PermissionError occured while copying files")
logger.exception(
"A PermissionError occured while copying files. Make sure you are root."
)
logger.error(REPORT_BUG_INFO)
sys.exit(3)
except:
@ -234,8 +238,8 @@ def main():
# see man:sd_notify(3)
notify("READY=1")
# Gateway mode comes in handy when many nodes have a DHCP server
# and you want to prevent conflicts.
# Gateway mode comes in handy when many nodes have a DHCP server and
# you want to prevent conflicts. It defaults to "auto" in naxalnet.
# https://www.open-mesh.org/projects/batman-adv/wiki/Gateways
if args.gateway_mode == "auto":
logger.info("Checking for internet connection")

View File

@ -1,3 +1,4 @@
# This program is not meant to be distributed through PyPi
[metadata]
name = naxalnet
version = attr: naxalnet.__version__